流利的接口不利于维护
流利的接口 (最初由Martin Fowler 創(chuàng)造)是一種非常方便的與OOP中的對(duì)象進(jìn)行通信的方式。 它使他們的外墻更易于使用和理解。 但是,它破壞了它們的內(nèi)部設(shè)計(jì),使它們更難以維護(hù)。 Marco Pivetta在他的博客文章Fluent Interfaces is Evil中說(shuō)了幾句話; 現(xiàn)在我加幾分錢。
唐尼·布拉斯科(1997)
讓我們看一下我自己的庫(kù)jcabi-http ,它是幾年前創(chuàng)建的,當(dāng)時(shí)我認(rèn)為流暢的接口是一件好事。 這是您使用庫(kù)發(fā)出HTTP請(qǐng)求并驗(yàn)證其輸出的方式:
String html = new JdkRequest("https://www.google.com").method("GET").fetch().as(RestResponse.class).assertStatus(200).body(); 這種便捷的方法鏈接使代碼簡(jiǎn)短明了,對(duì)吧? 是的,表面上確實(shí)如此。 但是,包括JdkRequest在內(nèi)的庫(kù)類的內(nèi)部設(shè)計(jì)遠(yuǎn)非優(yōu)雅。 最大的問(wèn)題是它們很大,而且
難
無(wú)法擴(kuò)展它們而不擴(kuò)大它們。
例如,現(xiàn)在JdkRequest具有方法method() , fetch()和其他一些方法。 需要新功能時(shí)會(huì)發(fā)生什么? 添加它的唯一方法是通過(guò)添加新方法來(lái)擴(kuò)大類的范圍,這是我們危害其可維護(hù)性的方式。 例如, 在這里 ,我們添加了multipartBody() , 在這里我們添加了timeout() 。
在jcabi-http中收到新功能請(qǐng)求時(shí),我總是感到害怕。 我了解這很可能意味著向Request , Response和其他已經(jīng)膨脹的接口和類添加新方法。
我實(shí)際上試圖在庫(kù)中做一些事情來(lái)解決這個(gè)問(wèn)題,但這并不容易。 查看此.as(RestResponse.class)方法調(diào)用。 它所做的是用RestResponse裝飾一個(gè)Response ,以便使其方法更豐富。 我只是不想讓Response包含50多種方法,就像許多其他庫(kù)一樣。 這是它的作用(這是偽代碼):
class Response {RestResponse as() {return new RestResponse(this);}// Seven methods } class RestResponse implements Response {private final Response origin;// Original seven methods from Response// Additional 14 methods }如您所見(jiàn),我沒(méi)有將所有可能的方法添加到Response ,而是將它們放置在補(bǔ)充修飾符RestResponse , JsonResponse , XmlResponse 等中 。 它有幫助,但是要使用Response類型的中心對(duì)象編寫(xiě)這些裝飾器,我們必須使用“ ugly”方法as() ,該方法as()很大程度上依賴于Reflection和類型轉(zhuǎn)換 。
流利的接口意味著大型類或某些丑陋的解決方法。
換句話說(shuō),流暢的界面意味著大型類或一些丑陋的解決方法。 當(dāng)我寫(xiě)有關(guān)Streams API和接口Stream的文章時(shí) ,我曾提到過(guò)這個(gè)問(wèn)題,它非常流暢。 有43種方法!
這是流暢接口的最大問(wèn)題-它們迫使對(duì)象變得巨大。
流利的接口非常適合其用戶,因?yàn)樗蟹椒ǘ荚谝粋€(gè)地方,并且類的數(shù)量非常少。 使用它們很容易,尤其是在大多數(shù)IDE中使用代碼自動(dòng)完成功能時(shí)。 它們也使客戶端代碼更具可讀性,因?yàn)椤傲骼摹苯Y(jié)構(gòu)看起來(lái)類似于純英語(yǔ)(aka DSL )。
沒(méi)錯(cuò)! 但是,它們對(duì)對(duì)象設(shè)計(jì)造成的損害是價(jià)格過(guò)高。
有什么選擇?
我建議您改為使用裝飾器和智能對(duì)象 。 如果現(xiàn)在可以做的話,這就是我設(shè)計(jì)jcabi-http的方法:
String html = new BodyOfResponse(new ResponseAssertStatus(new RequestWithMethod(new JdkRequest("https://www.google.com"),"GET"),200) ).toString();這與上面的第一個(gè)代碼段中的代碼相同,但是它更加面向?qū)ο蟆?當(dāng)然,此代碼的明顯問(wèn)題是IDE無(wú)法自動(dòng)完成幾乎所有操作。 同樣,我們將不得不記住許多類的名稱。 對(duì)于那些習(xí)慣了流利界面的人來(lái)說(shuō),該結(jié)構(gòu)看起來(lái)很難閱讀。 此外,它與DSL的想法相距甚遠(yuǎn)。
流暢的界面對(duì)用戶有利,但對(duì)開(kāi)發(fā)人員不利。 小對(duì)象對(duì)開(kāi)發(fā)人員有好處,但難以使用。
但是,這里是好處列表。 首先,每個(gè)對(duì)象都很小,非常有凝聚力,并且它們都是松散耦合的,這在OOP中是顯而易見(jiàn)的優(yōu)點(diǎn)。 其次,向庫(kù)中添加新功能就像創(chuàng)建新類一樣容易。 無(wú)需接觸現(xiàn)有課程。 第三,由于類很小,因此簡(jiǎn)化了單元測(cè)試。 第四,所有類都是不可變的,這在OOP中也很明顯 。
因此,有用性和可維護(hù)性之間似乎存在沖突。 流利的接口對(duì)用戶有利,但對(duì)庫(kù)開(kāi)發(fā)人員則不利。 小對(duì)象對(duì)開(kāi)發(fā)人員有好處,但難以理解和使用。
似乎是這樣,但前提是您已經(jīng)習(xí)慣于大型類和過(guò)程編程。 對(duì)我來(lái)說(shuō),大量的小班學(xué)習(xí)似乎是一種優(yōu)勢(shì) ,而不是缺點(diǎn)。 即使我不確定確切的類最適合我,內(nèi)部清晰,簡(jiǎn)單且易讀的庫(kù)也更易于使用。 即使沒(méi)有代碼自動(dòng)完成功能,我也可以自己解決,因?yàn)榇a很干凈。
另外,我經(jīng)常發(fā)現(xiàn)自己對(duì)在代碼庫(kù)內(nèi)部或通過(guò)對(duì)庫(kù)的拉取請(qǐng)求擴(kuò)展現(xiàn)有功能感興趣。 如果我知道所引入的更改是孤立的并且易于測(cè)試,那么我對(duì)此更感興趣 。
因此,我再也沒(méi)有流暢的界面,只有對(duì)象和裝飾器。
翻譯自: https://www.javacodegeeks.com/2018/03/fluent-interfaces-are-bad-for-maintainability.html
總結(jié)
以上是生活随笔為你收集整理的流利的接口不利于维护的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 农业备案立项流程(农业备案立项)
- 下一篇: 英雄安卓版(英雄牌安卓)