专栏名称: 逸言
文学与软件,诗意地想念。
目录
相关文章推荐
程序员的那些事  ·  趣图:我和 DeepSeek 互换角色 ·  昨天  
OSC开源社区  ·  2024年中国开源模型:崛起与变革 ·  昨天  
码农翻身  ·  漫画 | ... ·  22 小时前  
程序员小灰  ·  这款AI编程工具,将会取代Cursor! ·  昨天  
程序员小灰  ·  这个春节,小灰一天都没休息 ·  3 天前  
51好读  ›  专栏  ›  逸言

设计一个小接口展开的讨论

逸言  · 公众号  · 程序员  · 2020-11-27 22:08

正文


蔡了戴着耳机一边哼着歌一边晃着头沉浸在自己的音乐世界里。8点45分,距离早会还有半个多小时,放松一下,抽空自娱自乐!

“蔡了!”办公室传来中气十足的呼唤声,似乎整个写字楼都回荡着蔡了的名字。

“哎,明明就只隔几个工位,还要吼得整栋楼都听得到,不明真相的,还以为我又犯什么错了呢!”蔡了一边腹诽着,一边回应着“来了来了”,丢下耳机就向马大叔的工位跑去——没办法,头儿的呼唤,怎敢不从?

“马大叔!什么事啊?不会我的代码又没写好吧?”蔡了看着电脑屏幕的光线投射在马丁花那张老脸上,阴晴不明,心里一紧,说话也变得小心翼翼起来。

“没事就不能叫你?”马丁花脸一板,像指挥军队的将军一般将手一挥,说到:“过来,过来!我今早一来就pull了代码,正好看到你提交的代码。”

蔡了一听,知道老马又要上课了,赶紧推了一把椅子,收了心里的腹诽,像个乖乖女一般规规矩矩地坐下来,看着老马屏幕上打开的一个类。正是昨天自己写的一个工厂类Kafka251Factory。

“这样的工厂类我们写了很多,按理说你可以参考,但我看你写的代码却有些不同,为何这两个创建方法要定义为实例方法呢?”


“老大,我是这样想的。我觉得这两个创建方法传入的参数都一样,为了避免重复,我就将它们定义成了字段。因为要使用字段,就不能用静态方法罗!”蔡了一想到昨天自己灵机一动,通过提取字段有效避免了方法参数的重复定义,不免有些沾沾自喜。

“哦,小蔡不错哟,都有很强的重用意识了!但是——”话锋一转,马丁花开启了循循善诱的教导模式,“你有没有好好比较两种不同定义的调用代码呢?”一边说,一边在电脑上敲出如下代码:
//方式1new Kafka251Factory(config.kafka(), "topic").createSource();
//方式2Kafka251Factory.createSource(config.kafka(), "topic");

“这个……”蔡了转着大大的眼睛,努力想说出点颇有见地的答案,只可惜转了半天,还是想不出一二三。

马丁花看蔡了半天回答不上,也不着恼,缓缓说道:“你要学会站在调用者的角度看待API设计。这里虽然都是一行调用代码,但是要创建一个实例和直接调用类型的静态方法给人的观感还是不同的。虽然从可扩展性的角度看,面向对象鼓励我们尽可能定义实例方法,但对于工厂方法而言,方式2定义的静态工厂方法还是要更直接一些。更何况,作为一个工厂对象而言,频繁地创建工厂实例,既无必要,也增加了垃圾回收的负担。”

蔡了点点头,说道:“大叔,我貌似懂了,就是说从调用者的直觉来看,这样的静态工厂方法应该更符合调用者的期望。我说得对吗?”

“不错不错,朽木可雕也!”马丁花哈哈地笑起来,很欣慰自己的一番教导总算没有白费。可惜没有长长的胡须可以抚弄,否则倒有几分爷爷看孙女的感觉,如今这般笑着,无奈只得扫入怪大叔的行列了。

“可是,这样的定义不是导致方法参数的重复了吗?”蔡了仍不甘心推倒自己的重用成果,指着重构为静态工厂方法的Kafka251Factory类,继续问道。


“如果一个类的多个实例方法接收的输入参数相同,确实可以 将这些参数当做该类的字段,如此即可减少参数的传递 ,而且从生命周期来看,既然多个实例方法都会用到它们,说明它们的作用范围要广于方法的范围,可以认为是当前类自身携带的数据,将它们定义为字段,然后在构造函数中接收其值,这一设计是合理的。 但是,对于静态方法来说,由于 方法参数与 当前类的生命周期并非 一致 ,我们就不能贸然地将其改为实例方法,否则就会增加调用者的负担。如果静态方法的参数太多,大可以 通过提取 Parameter Object 封装 多个内聚的参数, 减少方法参数数量。

马丁花说到这里,想了想,继续说道:“若要说重复,代码中的config.item(label).topic()出现了两次,有着很明显的重复代码坏味道,可以再改进一下。”

“这个还不简单!”蔡了终于逮住表现自己的机会,一把抢过摆在电脑面前的键盘,熟练地将光标移到这行代码,按下Ctrl+Alt+M快捷键,将其提取为一个方法:


“看起来提取方法确实消除了重复,但你觉得它带来了有效的重用了吗?”马丁花点点头,又摇摇头,继续问道。

蔡了皱起眉:“呃……提取的方法做到了重用,可惜要重用的代码实在太少,看起来区别不大啊!”

“确实如此,然而……关键不在于这里。”马丁花说罢,接过键盘,把光标挪到getTopic方法下,解释道:“你看这里,两个工厂方法实际上希望获得的是topic,这个topic又是通过config的item与传入的label来获得的。虽说这段代码非常简短,实际上它仍然暴露了获取topic的细节。”马丁花的语气开始加重,这是要敲黑板了:“ 记住!当你发现调用一个对象时,频繁出现多个方法链式的调用,只要不是像Java Stream API那样的流畅接口,都说明它的封装不够彻底,属于Martin Fowler指出的Message Chain坏味道,有人也将这一坏味道称之为‘火车残骸’!






请到「今天看啥」查看全文


推荐文章
程序员的那些事  ·  趣图:我和 DeepSeek 互换角色
昨天
OSC开源社区  ·  2024年中国开源模型:崛起与变革
昨天
程序员小灰  ·  这款AI编程工具,将会取代Cursor!
昨天
程序员小灰  ·  这个春节,小灰一天都没休息
3 天前
人民日报  ·  今天,请为遇难同胞默哀
8 年前
普象工业设计小站  ·  【和静清寂】它起源于中国,却扬名于日本
8 年前
21世纪经济报道  ·  【夜读】高情商的人,都擅长“麻烦”别人
8 年前