无效方法为行为黑洞
如果“認(rèn)為有害”的文章本身不被認(rèn)為是有害的,則本帖標(biāo)題為“認(rèn)為有害的作廢方法”。 哦,好了
無(wú)效方法在大多數(shù)面向?qū)ο蟮拇a庫(kù)中無(wú)處不在。 在運(yùn)行時(shí)中某個(gè)地方發(fā)生可變狀態(tài)或I / O的直接后果是,您可以包裝功能編程狂熱者稱為impure的任何行為,該行為原則上沒(méi)有有意義的返回值。 一個(gè)常見(jiàn)的示例是在應(yīng)用程序引導(dǎo)期間,例如在Java中:
@Resource MyClass implements Runnable {// ...@PostConstruct public void init() {if(this.enabled) {this.executorService.scheduleAtFixedRate(this,0,500,TimeOut.MILLISECONDS);} }// ... }上面的代碼據(jù)說(shuō)不錯(cuò),但是公共無(wú)效方法,尤其是它們?cè)诮o定代碼庫(kù)中的擴(kuò)散,顯然是代碼的味道。 即使以面向?qū)ο髽邮竭M(jìn)行編碼。
您的
公共方法供您的類合作者使用,它們是類功能的門戶。 因此,它們應(yīng)盡可能簡(jiǎn)潔,并提供實(shí)現(xiàn)類行為所需的最小表面積。 任何函數(shù)定義的一個(gè)主要的自記錄部分自然就是其返回類型。
讓我們從前面的示例開(kāi)始:
@Resource MyClass implements Runnable {// ...@PostConstruct public void init() {if(this.enabled) {this.executorService.scheduleAtFixedRate(this,0,500,TimeOut.MILLISECONDS);} }// ... }我們的類可能在構(gòu)造時(shí)收到某種executorService實(shí)例,該實(shí)例可能是從某些依賴項(xiàng)注入粘合代碼獲得的,然后啟動(dòng)了工作計(jì)劃。 客戶代碼需要顯式調(diào)用init()的可能性通常很小。 這表明我們的@PostConstruct方法應(yīng)該具有更嚴(yán)格的可見(jiàn)性,可能是private或protected ,而這將是結(jié)束。
但是,真的嗎?
可測(cè)性
假設(shè)我們要實(shí)際測(cè)試工作線程的關(guān)閉行為,這通常是一件棘手的事情。 您想做的事情大致如下:
// changed code from the original MyClass file: @PostConstruct public ScheduledFuture<T> init() {if(this.enabled) {return this.executorService.scheduleAtFixedRate(this,0,500,TimeOut.MILLISECONDS);} }public testExecutorShutdown(){ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();MyClass c = new MyClass(service, true); // executorService, enabledScheduledFuture<T> scheduled = c.init();executorService.shutdown();scheduled.get(1, TimeUnit.SECONDS); // throws exception }上面的測(cè)試代碼測(cè)試了計(jì)劃的操作在執(zhí)行程序關(guān)閉后的1秒(或兩次計(jì)劃的迭代)內(nèi)終止。 這樣的測(cè)試依賴于訪問(wèn)由init方法返回的將來(lái)的對(duì)象。
自我記錄
人類的知覺(jué)被他們當(dāng)前的意識(shí)視野所遮蓋
– 埃利亞·懷斯
我們對(duì)init()方法所做的更改啟用了行為測(cè)試,但帶來(lái)了一個(gè)重要的副作用: ScheduledFuture對(duì)象現(xiàn)在是MyClass公共接口的一部分,這意味著現(xiàn)在任何客戶端代碼都可以與其進(jìn)行交互。 這是否是一個(gè)理想的屬性,實(shí)際上取決于MyClass旨在支持的用例,并且可能您希望將ScheduledFuture封裝在一個(gè)更友好的類中,例如,僅公開(kāi)bool isDone()類的東西。
無(wú)論如何,保持上述init方法為空將始終導(dǎo)致您的客戶端代碼(或開(kāi)發(fā)人員使用他/她的IDE瀏覽init簽名)而無(wú)視MyClass.init()的實(shí)際作用。 只需看看不同的簽名,然后想想自己針對(duì)每個(gè)簽名進(jìn)行編碼:
public void init() public ScheduledFuture<T> init()后者將在您每次需要使用它時(shí)為您節(jié)省大腦周期,因?yàn)樗宄卣f(shuō)明了其產(chǎn)生的效果,而無(wú)需查看代碼或更深層次的文檔。
一件事做好
當(dāng)函數(shù)一次執(zhí)行多個(gè)操作時(shí),堅(jiān)持函數(shù)返回一個(gè)值以明確聲明其行為的想法顯然是不可能的。 幸運(yùn)的是,它本身就是一種代碼味道 ,并且通過(guò)將返回類型視為函數(shù)的存在目的,可以使違反該原則變得更加奇怪。
結(jié)論
對(duì)您自己的未來(lái)以及對(duì)使用您的代碼的所有開(kāi)發(fā)人員都是好事,永遠(yuǎn)不要再在公共API中隱藏諸如返回值之類的寶貴信息。
擁抱與親吻c。
翻譯自: https://www.javacodegeeks.com/2018/05/void-methods-as-behavior-black-holes.html
總結(jié)
- 上一篇: 一个吉一个页是什么字 一个吉一个页是啥字
- 下一篇: wso2 esb_使用WSO2 ESB构