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