简单性与鲁棒性–在锁定文件处理中展示
今天,我們將討論在設(shè)計(jì)不足和過(guò)度設(shè)計(jì)之間保持簡(jiǎn)單,愚蠢(KISS)和魯棒性的設(shè)計(jì)價(jià)值之間的沖突。
我們正在編寫一個(gè)批處理Java應(yīng)用程序,需要確保在服務(wù)器上一次最多運(yùn)行一個(gè)實(shí)例。 一個(gè)團(tuán)隊(duì)成員有一個(gè)很好的想法,那就是使用鎖定文件,這確實(shí)有效并且對(duì)我們有很大幫助。 但是,最初的實(shí)現(xiàn)并不十分健壯,由于對(duì)該死的應(yīng)用程序拒絕運(yùn)行并查找鎖定文件進(jìn)行了故障排除,這使我們花費(fèi)了寶貴的時(shí)間和昂貴的上下文切換。
正如Comoyo的?yvindBakksj?最近解釋的那樣,軟件工程師與純粹的編碼器的區(qū)別在于,它不僅思考和關(guān)注遍歷代碼的快樂(lè)路徑,而且也關(guān)注不愉快的情況。 優(yōu)秀的工程師會(huì)考慮可能出現(xiàn)的問(wèn)題,并嘗試適當(dāng)?shù)靥幚硭鼈?#xff0c;以便依賴于它們和其用戶的代碼可以更輕松地處理有問(wèn)題的情況。 健壯性包括及早發(fā)現(xiàn)錯(cuò)誤,以適當(dāng)?shù)姆绞教幚礤e(cuò)誤以及提供有用和有用的錯(cuò)誤消息。 另一方面,簡(jiǎn)單性[TBD:Hickey]是系統(tǒng)的關(guān)鍵特征。 花太多時(shí)間來(lái)制作防彈代碼總是很容易,而不是將精力集中在對(duì)業(yè)務(wù)更有價(jià)值的地方。
過(guò)于簡(jiǎn)單的實(shí)現(xiàn)
最初的實(shí)現(xiàn)非常簡(jiǎn)單:
public class SimpleSingletonBatchJob {private static boolean getLock() {File file = new File(LOCK_DIRECTORY+File.separatorChar+Configuration.getGroupPrefix());try {return file.createNewFile();} catch (IOException e) {return false;}}private static void releaseLock() {File file = new File(LOCK_DIRECTORY+File.separatorChar+Configuration.getGroupPrefix());file.delete();}public static void exit(int nr) {releaseLock();System.exit(nr);}public static void main(String[] args) throws IOException {...if (! getLock()) { // #1 try to create lockSystem.out.println("Already running");return;}... // do the job (may throw exceptions)releaseLock(); // #2 release lock when done} }主要問(wèn)題是,如果該應(yīng)用程序失敗或被殺死,它將留下鎖定文件,而下次它將拒絕并以無(wú)用的錯(cuò)誤消息開頭。 您將需要了解/閱讀代碼以了解如何解決問(wèn)題。
有人認(rèn)為,這樣的失敗和故意的失敗只會(huì)很少發(fā)生,以致于沒(méi)有理由要求使代碼更健壯。 但是,我們需要花費(fèi)很少的精力來(lái)使代碼更加友好和健壯,f.ex。 通過(guò)在錯(cuò)誤消息中包括鎖定文件路徑并解釋為什么可能存在鎖定文件路徑以及如何解決該問(wèn)題(例如“如果應(yīng)用未運(yùn)行,則鎖定是失敗運(yùn)行后的遺留物,可能會(huì)刪除”)。 確保在失敗時(shí)刪除文件是一些瑣碎的代碼行,可以節(jié)省一些混亂和時(shí)間。 另外,值得一提的是使其更強(qiáng)大,從而不需要太多的手動(dòng)干預(yù)–對(duì)您的操作人員很友好。 (我希望是你。)
更強(qiáng)大的實(shí)施
這是改進(jìn)的版本,具有有用的錯(cuò)誤消息,并在失敗時(shí)刪除鎖:
public class RobustSingletonBatchJob {// Note: We could use File.deleteOnExit() but the docs says it is not 100% reliable and recommends to// use java.nio.channels.FileLock; however this code works well enough for usstatic synchronized boolean getLock() {File file = new File(LOCK_DIRECTORY, StaticConfiguration.getGroupPrefix());try {// Will try to create path to lockfile if it does not exist.file.getParentFile().mkdirs(); // #1 Create the lock dir if it doesn't existif (file.createNewFile()) {return true;} else {log.info("Lock file " + file.getAbsolutePath() + " already exists."); // #2 Helpful error msg w/ pathreturn false;}} catch (IOException e) {throw new RuntimeException("Failed to create lock file " + file.getAbsolutePath()+ " due to " + e + ". Fix the problem and retry.", e); // #3 Helpful error message with context (file path)}}private synchronized static void releaseLock() {File file = new File(LOCK_DIRECTORY, StaticConfiguration.getGroupPrefix());file.delete();}public static void main(String[] args) throws Exception {boolean releaseLockUponCompletion = true;try {...if (! getLock() {releaseLockUponCompletion = false;log.error("Lock file is present, exiting."); // Lock path already loggedthrow new RuntimeException("Lock file is present"); // throwing is nicer than System.exit/return}... // do the job (may throw exceptions)} finally {if (releaseLockUponCompletion) {releaseLock(); // #4 Always release the lock, even upon exceptions}} }改進(jìn)之處:
該代碼仍然不是完美的-如果您終止了該應(yīng)用程序,則鎖定文件仍將留下。 有多種方法可以解決該問(wèn)題(例如,將應(yīng)用程序的pid包含在文件中,在啟動(dòng)時(shí)不僅檢查其是否存在,而且還檢查該pid確實(shí)存在/是否為該應(yīng)用程序),但是在處理時(shí)間和增加成本方面都需要解決復(fù)雜性的確高于收益。
結(jié)論
KISS和魯棒性都是重要目標(biāo),并且經(jīng)常會(huì)發(fā)生沖突。 使您的代碼比必需的更健壯會(huì)使其變得過(guò)于復(fù)雜,并浪費(fèi)時(shí)間,并且機(jī)會(huì)成本(丟失)。 由于故障排除,使代碼過(guò)于簡(jiǎn)單會(huì)花費(fèi)您或它的用戶大量時(shí)間。 要實(shí)現(xiàn)正確的平衡,需要經(jīng)驗(yàn)并不斷地尋求平衡。 如果您的團(tuán)隊(duì)無(wú)法達(dá)成共識(shí),最好從一個(gè)簡(jiǎn)單的代碼開始,并根據(jù)其實(shí)際的健壯性需求收集硬數(shù)據(jù),而不是事先對(duì)其進(jìn)行過(guò)度設(shè)計(jì)。 不要像我一樣成為完美主義者,但也要對(duì)您的用戶和開發(fā)人員有益。 如果您可以毫不費(fèi)力地使您的應(yīng)用程序更強(qiáng)大,那就去做吧。 如果需要更多工作,請(qǐng)去收集數(shù)據(jù)以證明(或不需要)該工作。
翻譯自: https://www.javacodegeeks.com/2013/09/simplicity-vs-robustness-demonstrated-on-lock-file-handling.html
總結(jié)
以上是生活随笔為你收集整理的简单性与鲁棒性–在锁定文件处理中展示的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 刺客信条奥德赛电脑(刺客信条奥德赛电脑配
- 下一篇: 使用NetBeans 7.4 beta提