javascript
固执己见的框架(例如Spring Boot)的危险。 求知代码反转
我們開發人員喜歡抽象。 沒有它,我們將無法構建應用程序。 我們的編程學科甚至要求我們對抽象進行編碼,并避免將我們的代碼耦合到詳細的實現。
但是,什么是適合您的應用程序的正確抽象呢?
可悲的是,抽象的選擇確實來自我們對框架的選擇。 框架基本上是我們為解決問題而擴展的抽象解決方案。
不幸的是,諸如Spring Boot之類的框架對使用的線程模型,需要擴展的接口,可能的適用數據存儲庫以及關于問題空間的各種其他假設都持謹慎態度。 在編寫第一行代碼之前,這有很多限制。
我們真正想做的是首先探索問題空間。 這就是測試驅動設計的全部內容。 我們編寫測試來定義什么是成功的代碼。 然后,我們實現代碼以通過那些測試。 在編寫測試以掩蓋需求的過程中,我們隨后為應用程序編制了工作代碼。 隨著時間的流逝,我們可以獲得足夠的工作代碼以作為應用程序發布。
所以這導致我問,我們什么時候測試框架的選擇?
固執己見的框架在開發過程中過早強制抽象
好吧,我想我們會請經驗豐富的資深人士來做出此選擇。 因此,此選擇必須正確。 不會因為以下原因:
- 我(或我們的公司)只知道此框架,因此我們正在使用它
- 新閃亮,帶有很多流行語,我們必須使用它
- 我的簡歷有點舊,讓我們嘗試一些新的東西
- 這個便宜一點
- 建筑相信它在錫上說了什么
無論出于何種原因,測試框架選擇的唯一方法是使用它來構建應用程序。 而對于那些喜歡固執己見的框架(例如Spring Boot)的人,請告訴我您首先編寫最冒險的方面。 這樣,您可以快速發現框架的意見是否與您的問題相符。
令人遺憾的是,即使您使用最危險的方面進行測試,發現框架決策是錯誤的也會導致大量的代碼浪費。 可以說,這浪費了企業很多錢,并可能導致項目失敗。
例如,假設我們選擇“ Spring Reactive”。 是的,我們可以對各種微服務進行并發異步調用。 我們還可以使用NoSQL數據存儲中的最新數據。 這都是一個偉大的決定。 但是,隨著時間的流逝,我們意識到我們擁有少量數據,其中數據的完整性非常重要。 我們發現我們想使用關系數據庫來解決此問題,然后將JPA合并到該數據庫中以便更輕松地進行交互。 但是,我們選擇Spring Reactive不允許這樣做,因為它要求所有I / O都是異步的(JPA是同步數據庫調用)。 好的,是的,我們可以使用Scheduler,但是由于缺少事務,我似乎一直在不斷地工作。 數據一致性問題開始加劇,我們錯過了最后期限。 現在,我可以扔掉所有的Reactive代碼,還是繼續努力以希望它們都可以在一起。 我肯定需要調換職位,然后才能開始支持我們。 在下一份工作中,我學習了使用Spring Servlet解決這類問題。
這種情況的另一面也很容易發生。 我們開始是想讓Spring Servlet與數據庫進行JPA交互。 但是,隨著時間的流逝,我們意識到數據庫交互主要是只讀的。 我們真正想要的是Spring Reactive的異步I / O,以同時從多個微服務和數據存儲中收集數據。 不幸的是,由于我們選擇了Spring Servlet,因此數據收集太慢了。 我們的工作是使用異步Servlet和生成線程來發出并發請求。 最初可以正常工作,但隨著時間的推移,負載會增加。 這大大增加了線程數,導致線程調度不足,導致超時。 如果不對應用程序進行大量重寫,我真的無法解決此問題。 在下一份工作中,我學會了使用Spring Reactive解決此類問題。
因此,可以不必去扔掉所有代碼就能測試框架嗎?
反轉框架控制
依賴注入在反轉控制方面走了很長一段路。 當我編寫Servlet處理方法時,不再需要傳入所有依賴對象。 我將通過@Inject定義依賴項,以使框架使它們可用。 隨后,該框架不再規定我的實現可以依賴哪些對象。
但是,框架不僅僅是對象,還有很多其他功能。 框架將施加某種線程模型,并要求我擴展某些方法。 盡管依賴注入提供了對對象的引用,但是框架仍然必須調用對象上的方法以執行任何有用的操作。 例如,Spring一直在使方法變得靈活,但仍然通過方法所需的返回類型將您耦合到Reactive或Servlet編碼。
由于我需要Spring框架來進行測試的依賴注入,因此在編寫第一行代碼之前,我就已經耦合到特定的Spring Servlet / Reactive抽象。 如果我弄錯了,更改的前期選擇可能會非常昂貴!
我真正想做的是:
好,前兩個很簡單:
最后變得非常困難。 最后一個變得很困難的原因是沒有一致的方法來調用每個方法。 方法具有不同的名稱,不同的參數,不同的異常,可能不同的線程要求和不同的返回類型。 我們需要的是使這些方法看起來相同的方法的基礎。
(耦合)控制的反轉(IoC)通過ManagedFunction在方法上提供了這種外觀。 ManagedFunction接口不會指示要使用的線程,需要的參數/返回類型,也不會拋出異常。 所有這些都由所包含的方法實現指定。 耦合是反向的,因此實現可指定所需的條件。
耦合的這種反轉使得可以推遲框架決策。 因為我可以用一致的方式調用所有方法,所以我可以繼續并開始編寫實現。 這些實現可能需要響應式編碼來對不同的微服務進行異步調用。 其中一些實現可能需要使用JPA寫入關系數據庫。 我真的不應該在開始構建系統時就在意。 我正在解決具體問題,以更好地了解實際問題空間。 我知道我的方法可以通過將框架包裝在ManagedFunction中來調用。 一旦了解更多信息,我們便可以稍后確定合適的框架。
實際上,這允許實現選擇框架要提??供的適當抽象。 我的實現定義了所需的對象,所需的其他方法以及所需的線程模型。 這些實現有效地定義了從框架中需要什么抽象。
因此,它不再是框架。 允許對您的開發人員代碼提出意見。
然后,這可以使您的實現對使用的最合適的框架有意見。 您不再需要基于對問題空間的模糊理解來猜測框架。 您可以看到實現需要什么抽象,并可以更明智地選擇框架。
實際上,IoC已將框架的選擇推遲到開發過程的后期。 這樣,您可以更加自信地做出決定。 這不是敏捷所說的,將承諾推遲到最后一個負責任的時刻。
摘要
總而言之,為什么要被迫對您的應用做出太多的前期決策? 在選擇框架時,您正在做出一些重要的選擇來解決您的問題空間。 鑒于框架的存在,它們對您的解決方案造成了很多耦合。
相反,為什么我不能立即開始為具體問題編寫解決方案并擔心以后它們如何融合在一起? 當我對問題空間有更多了解時,這使我可以選擇適當的抽象(以及隨后的框架)。
當您被告知正確地做出決策時,(耦合)控制的反轉使此功能可以將抽象和框架選擇推遲到開發過程的后期。
翻譯自: https://www.javacodegeeks.com/2019/05/opinionated-frameworks-inverting-opinionated-code.html
總結
以上是生活随笔為你收集整理的固执己见的框架(例如Spring Boot)的危险。 求知代码反转的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为p40微信视频美颜怎么开
- 下一篇: 从Java应用程序中消除Null指针异常