《代碼整潔之道》讀書筆記

序,前言

  1. 重視代碼
    facebookcode review作為重點KPI考核裙犹,并采用連坐制雌续。
    code wins argument
    當兩人為一個問題爭執(zhí)不下時桌吃,不妨以最快的速度用代碼把想法寫出來,事實勝于雄辯。

  2. 代碼是負債不是資產(chǎn)
    代碼越多,維護所要付出的成本就越高琅坡。
    如果代碼結(jié)構(gòu)越好悉患,做了越多單元測試残家,代碼質(zhì)量越好、越小售躁、耦合越松坞淮,那么添加新代碼付出的成本就越少。

  3. 本書觀點:代碼質(zhì)量與整潔度成正比

一陪捷,整潔代碼

  • 糟糕混亂的代碼給項目帶來的負面影響
    略過回窘。

  • 什么是整潔代碼
    關(guān)鍵字: 只做好一件事,簡單直接市袖,意圖明確啡直,單元測試,盡量少的依賴關(guān)系苍碟,看起來像是專門解決那個問題而存在酒觅。

  • 破窗理論和童子軍軍規(guī)
    第一扇窗被打破,但是沒有人管微峰,接下來會有更多的窗被打破舷丹,爛代碼不去管它只會越來越爛。
    當你離開一個地方時蜓肆,要讓它比你來之前更干凈颜凯。

  • 代碼要易讀
    我們編寫代碼時,讀和寫花費的時間比例超過10:1仗扬,要想代碼易寫症概,首先做到易讀。

  • 面向?qū)ο笤O(shè)計的原則(SOLID)
    單一職責原則
    開閉原則
    里氏代換原則
    接口隔離原則
    依賴倒置原則

二早芭,有意義的命名

  1. 名副其實:為變量或函數(shù)起一個能反映其含義的名字并不容易彼城,但起名字花的時間是值得的,好的命名能讓讀者快速理解代碼,減少維護成本精肃。這和TDD四原則里的“揭示意圖”是一致的秤涩。

  2. 作者詳細介紹了命名需要注意的問題,

    naming.PNG

    結(jié)合我們的項目司抱,印象比較深的是“每個概念對應(yīng)一個詞”筐眷。
    項目代碼中通常會有一些特定職責的類,xxxHandler, xxxManager, xxxProcessor, xxxBuilder, xxxHelper... 這樣的類名含義模糊习柠,令人費解匀谣,而這些類往往在做類似的事情。

三资溃,函數(shù)的原則

  1. 短小
    if武翎、else、while語句內(nèi)的代碼塊應(yīng)該只有一行溶锭,該行大抵是一個函數(shù)調(diào)用語句宝恶。
    這樣的函數(shù)不僅能保持短小,而且調(diào)用的函數(shù)具有說明性的名稱趴捅,從而增加了文檔上的價值垫毙。
    所以函數(shù)的縮進不能多于兩層。

  2. 只做一件事
    寫函數(shù)是為了把大一些的概念(換言之拱绑,函數(shù)名稱)拆分為另一抽象層上的一系列步驟综芥。
    判斷函數(shù)是否不止做了一件事,還有一個辦法就是看是否還能再拆出一個函數(shù)猎拨。

  3. 每個函數(shù)一個抽象層級
    要讓代碼有自頂向下的閱讀順序膀藐,向下規(guī)則:每個函數(shù)后面跟著下一抽象層級的函數(shù)。

  4. Switch語句
    問題:太長红省,做了不止一件事额各,違反單一職責原則,違反開閉原則类腮,到處存在類似結(jié)構(gòu)的函數(shù)臊泰。
    解決方案:把switch語句放在工廠類,使用接口多態(tài)的接受派遣蚜枢。

  5. 使用描述性的名稱
    函數(shù)越短小缸逃,功能越集中,越便于取個好名字厂抽。

  6. 函數(shù)參數(shù)

  • 參數(shù)越少越好需频,參數(shù)超過三個時,排序筷凤、琢磨昭殉、忽略的問題都會加倍體現(xiàn)苞七。
  • 一元函數(shù)的普遍形式:A.操作參數(shù),轉(zhuǎn)換挪丢,返回蹂风。B.傳入event事件。
  • 參數(shù)過多乾蓬,最好先封裝成類再傳入惠啄。
  • 避免使用標識參數(shù),傳入true/false任内,明顯違反“只做一件事”的原則撵渡。
  • 避免使用輸出參數(shù),如果要修改對象的狀態(tài)死嗦,要調(diào)用對象自己的函數(shù):
    appendFooter(report);
    應(yīng)該改成
    report.appendFooter();
  1. 分隔指令與詢問
public boolean set(String attribute, String value);

該函數(shù)設(shè)置某個屬性的值趋距,如果設(shè)置成功返回true,如果不存在這個屬性返回false越除。
就會導(dǎo)致以下語句出現(xiàn):

if (set("userName", "Leo")) {...}

應(yīng)該改成

if (attributeExists("userName")) {
  set("userName", "Leo")
} 
  1. 使用異常替代返回錯誤碼
    從指令式函數(shù)返回Error Code节腐,輕微違反了指令與詢問分隔的原則,而且導(dǎo)致更深層次的嵌套結(jié)構(gòu)廊敌。使用異常铜跑,錯誤處理代碼就能從主路徑代碼中分離出來门怪,得到簡化骡澈。
if (deletePage(page) == E_OK) {
  if (registry.deleteReference(page.name) == E_OK) {
    if (configKeys.deleteKey(page.name.makeKey()) == E_OK){
      logger.log("page deleted");
    } else {
      logger.log("configKey not deleted"); 
    }
  } else {
    logger.log("deleteReference from registry failed"); 
  }
} else {
  logger.log("delete failed");
  return E_ERROR;
}

改成

try {
  deletePage(page);
  registry.deleteReference(page.name);
  configKeys.deleteKey(page.name.makeKey());
} catch (Exception e) {
  logger.log(e.getMessage());
}

try/catch代碼塊違反了只做一件事的原則,應(yīng)該把try和catch代碼塊主體部分抽出來掷空,另外形成函數(shù)

public void delete(Page page) {
  try {
    deletePageAndAllReferrence(page);
  } catch (Exception e) {
    logError(e);
  }
}

private void deletePageAndAllReferrence(Page page) {
    deletePage(page);
    registry.deleteReference(page.name);
    configKeys.deleteKey(page.name.makeKey());
}

private void logError(Exception e) {
  logger.log(e.getMessage());
}
  1. 別重復(fù)自己

  2. 結(jié)構(gòu)化編程
    只要函數(shù)保持短小肋殴,循環(huán)偶爾出現(xiàn)return, break, continue沒有問題,避免使用goto坦弟。

  3. 函數(shù)修改的策略
    對于冗長復(fù)雜的函數(shù)护锤,先加單元測試覆蓋每行丑陋的代碼,然后分解函數(shù)酿傍、修改名稱烙懦、消除重復(fù),同時保持單元測試通過赤炒。

小結(jié)
函數(shù)是動詞氯析,類是名稱,編程藝術(shù)是語言設(shè)計的藝術(shù)莺褒。大師級程序員把系統(tǒng)當成故事來講掩缓,而不是當作程序來寫。

四遵岩、注釋

當我們無法用代碼表達意圖時才使用注釋你辣。盡量避免使用注釋,用代碼表達意圖。

五舍哄、格式

  1. 格式的目的
  • 代碼格式關(guān)乎溝通宴凉。
  • 代碼風格和可讀性仍會影響到可維護性和擴展性。
  1. 垂直格式
  • 短文件通常比長文件易于理解表悬,盡量短小而精悍跪解。
  • 概念間垂直方向上的區(qū)隔,不同的思路段落之間用空白行隔開签孔,例如單元測試中的Given叉讥、When、Then用空白行隔開饥追。
  • 垂直方向上图仓,關(guān)系密切的概念應(yīng)該相互靠近。
  • 垂直順序但绕,被調(diào)用的函數(shù)應(yīng)該放在執(zhí)行調(diào)用的函數(shù)下面救崔。
  1. 橫向格式
  • 水平方向的區(qū)隔和靠近,賦值語句=號左右加空格捏顺,函數(shù)參數(shù)之間加空格六孵,運算符優(yōu)先級高的× / ÷左右不加空格,優(yōu)先級低的+/-左右加空格幅骄。
  • 水平對齊劫窒。
  • 縮進表示層次。
  • 空范圍拆座。
  • 格式范例:


    code format sample.PNG

六主巍、對象和數(shù)據(jù)結(jié)構(gòu)

  1. 數(shù)據(jù)抽象
    隱藏實現(xiàn)關(guān)乎抽象!類并不簡單的用getter挪凑、setter將其變量推向外間孕索,
    而是暴露抽象接口,以便用戶無需了解數(shù)據(jù)的實現(xiàn)就能操作數(shù)據(jù)本體躏碳。
    以抽象形態(tài)表述數(shù)據(jù)搞旭。
//具象點
public class Point {
  public double x;
  public double y;  
}

//抽象點
public interface Point {
  double getX();
  double getY();
  void setCartesian(double x, double y);
  double getR();
  double getTheta();
  void setPolar(double r, double theta);
}
//具象機動車
public interface Vehicle {
  double getFuelTankCapacityInGallons();
  double getGallonsOfGasoline();
}

//抽象機動車
public interface Vehicle {
  double getPercentFuelRemaining();
}
  1. 數(shù)據(jù)、對象的反對稱性
  • 對象把數(shù)據(jù)隱藏于抽象之后菇绵,暴露操作數(shù)據(jù)的函數(shù)肄渗。
    數(shù)據(jù)結(jié)構(gòu)暴露其數(shù)據(jù),沒有提供有意義的函數(shù)脸甘。

  • 對象與數(shù)據(jù)結(jié)構(gòu)之間的二分原理:
    過程式代碼(使用數(shù)據(jù)結(jié)構(gòu))便于在不改動數(shù)據(jù)結(jié)構(gòu)的前提下添加新函數(shù)恳啥,
    面向?qū)ο蟠a便于在不改動既有函數(shù)的前提下添加新類。
    反過來說丹诀,
    過程式代碼難以添加新數(shù)據(jù)結(jié)構(gòu)钝的,因為必須修改所有函數(shù)翁垂,
    面向?qū)ο蟠a難以添加新函數(shù),因為必須修改所有類硝桩。

    過程式代碼.PNG

    面向?qū)ο蠖鄳B(tài)代碼.PNG

  1. 德墨忒爾定律(迪米特法則沿猜,Law Of Demeter)
    也叫做“最少了解原理”,模塊不應(yīng)該了解它所操作對象的內(nèi)部情形碗脊。
    C類的函數(shù)f()只能調(diào)用以下對象的方法:
  • C類的對象
  • f()創(chuàng)建的對象
  • 通過參數(shù)傳入的對象
  • C類的實體變量對象

另一種解釋:只暴露應(yīng)該暴露的接口方法啼肩,只依賴需要依賴的對象

law of demeter sample.PNG

System應(yīng)該只暴露close()的接口方法衙伶,而不該暴露close()內(nèi)部的細節(jié)祈坠,
Person應(yīng)該只依賴Container(硬件設(shè)備容器)的接口,而不該直接依賴System(操作系統(tǒng))矢劲。
這樣做也符合依賴倒置原則赦拘,也就是面向接口編程

火車失事
下列代碼應(yīng)該切分成三行芬沉。

final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath();

是否違反德墨忒爾定律躺同,取決于ctxt、options丸逸、scratchDir蹋艺、absolutePath是對象還是數(shù)據(jù)結(jié)構(gòu)。
如果是對象黄刚,應(yīng)該隱藏內(nèi)部結(jié)構(gòu)捎谨。
如果是數(shù)據(jù)結(jié)構(gòu),則需要暴露內(nèi)部結(jié)構(gòu)隘击,不算違反德墨忒爾定律侍芝。

混雜
盡量避免混合結(jié)構(gòu),一半是對象埋同,一半是數(shù)據(jù)結(jié)構(gòu),既有執(zhí)行操作的函數(shù)棵红,又有g(shù)etter/setter凶赁。同時增加了添加函數(shù)和添加數(shù)據(jù)結(jié)構(gòu)的難度。

隱藏結(jié)構(gòu)
經(jīng)查逆甜,發(fā)現(xiàn)上述代碼獲取outputDir是為了根據(jù)路徑得到BufferedOutputStream虱肄,創(chuàng)建文件,

String outFile = outputDir + "/" +className.replace('.', '/') + ".class";
FileOutputStream fout = new FileOutputStream(outFile);
BufferedOutputStream bos = new BufferedOutputStream(fout);

ctxt應(yīng)該僅僅暴露獲取BufferedOutputStream的接口方法交煞,隱藏具體實現(xiàn)咏窿。

BufferedOutputStream bos = ctxt.createScratchFileStream(classFileName);
  1. 數(shù)據(jù)傳送對象
    DTO是只有公共變量(包括私有變量+公共getter/setter)、沒有函數(shù)的類素征,是最精煉的數(shù)據(jù)結(jié)構(gòu)集嵌。
    Active Record是一種特殊的DTO形式萝挤,同時也會擁有save、find方法根欧,通常是對數(shù)據(jù)庫或其他數(shù)據(jù)源的之間翻譯(就是我們項目中的Domain Object怜珍,一個類對應(yīng)數(shù)據(jù)庫一張表)。Active Record往往被塞進業(yè)務(wù)規(guī)則方法凤粗,導(dǎo)致數(shù)據(jù)結(jié)構(gòu)和對象的混雜體酥泛。
    應(yīng)該把Active Record當成數(shù)據(jù)結(jié)構(gòu),另外創(chuàng)建包含業(yè)務(wù)規(guī)則嫌拣、隱藏內(nèi)部數(shù)據(jù)的獨立對象柔袁。

小結(jié)

  • 數(shù)據(jù)結(jié)構(gòu)暴露數(shù)據(jù),沒有明顯行為异逐。
    過程式代碼操作數(shù)據(jù)結(jié)構(gòu)瘦馍,添加新的函數(shù)無需修改數(shù)據(jù)結(jié)構(gòu),但添加新的數(shù)據(jù)結(jié)構(gòu)需要修改所有函數(shù)应役。
  • 對象暴露行為情组,隱藏數(shù)據(jù)。
    面向?qū)ο笫酱a操作對象箩祥,添加新的類無需修改既有函數(shù)院崇,但添加新的函數(shù)需要修改所有類。
    不應(yīng)對任何一種抱有成見袍祖,根據(jù)具體情況使用底瓣。

七、錯誤處理

對錯誤的處理很有必要蕉陋,也很重要捐凭,要保證出現(xiàn)錯誤時程序仍能正常運行。
但不能因此讓代碼邏輯變得混亂凳鬓。

  1. 使用異常而非返回碼
    使用異常進行錯誤處理茁肠,能把實現(xiàn)部分和錯誤處理分離,以免錯誤處理影響實現(xiàn)部分的邏輯缩举。

  2. 先寫Try-Catch-Finally

  3. 使用不可控異常
    我的理解:可控異常違反開閉原則垦梆,修改內(nèi)層方法拋出一個可控異常,外層方法都必須修改捕獲這個異常仅孩,導(dǎo)致從內(nèi)到外的修改鏈托猩。
    但是使用java編寫文件處理、反射的程序時辽慕,不可避免的需要捕獲可控異常京腥。
    自定義的異常都應(yīng)該繼承RuntimeException(不可控異常)。

  4. 給出異常發(fā)生的環(huán)境說明

  5. 依調(diào)用者需要定義異常類
    定義異常溅蛉,要考慮它們?nèi)绾伪徊东@公浪。
    對于第三方API拋出各種不同異常的情況他宛,可以打包API拋出通用的異常類型,簡化調(diào)用時的代碼因悲。
    直接在調(diào)用API的地方捕獲異常:

    api exception1.PNG

    打包調(diào)用API堕汞,簡化調(diào)用代碼:
    api exception2.PNG

  6. 定義常規(guī)流程
    采取特例模式(SPECIAL CASE PATTERN),創(chuàng)建一個類或配置一個對象晃琳,用來處理特例讯检。客戶代碼就不用應(yīng)付異常行為了卫旱。

  7. 不要返回或傳遞null值
    方法返回null人灼,不如拋出異常或返回特例對象顾翼,否則會有NullPointerException的隱患投放。

小結(jié)
將錯誤處理和主要邏輯隔離,就能寫出整潔而強壯的代碼适贸。

八灸芳、邊界

我們不可避免的需要使用第三方或者其他團隊開發(fā)的組件,整合到我們自己的代碼中拜姿,這章主要講如何保持軟件邊界整潔烙样。

  1. 使用第三方代碼
  • Map的接口功能非常豐富,接收者不要刪除其中的映射
  • Map的接口一旦修改蕊肥,許多地方代碼需要修改
  • 不要把Map(或其他在邊界上的接口)在系統(tǒng)中傳遞谒获,否則也要保留在類中,避免從公共API返回邊界接口壁却,或把邊界接口作為參數(shù)傳遞給公共API批狱。
  1. 通過編寫學習型測試來理解第三方代碼

  2. 使用尚不存在的代碼

    使用尚不存在的代碼.PNG

    通信控制器依賴于Transmitter API,但API尚未定義且不受我們控制展东。
    先定義適合通信控制器使用的接口Transmitter赔硫,一旦提供了Transmitter API,就編寫Transmitter Adapter來跨接琅锻。適配器封裝了與API的互動卦停,并且如果API發(fā)生變動,只需要修改適配器恼蓬。

小結(jié)
邊界上會發(fā)生我們不可控的改動,要避免我們的代碼過多依賴第三方代碼的細節(jié)僵芹。
使用Sensor類封裝第三方接口的返回結(jié)果处硬,或使用Adapter模式將第三方接口轉(zhuǎn)換為我們需要的接口。
使用Adapter模式不僅能將不兼容的接口改寫成兼容的接口拇派,還能對第三方接口重新封裝來避免邊界變化對系統(tǒng)的影響荷辕。

九凿跳、單元測試

  1. TDD三定律
  • 在編寫不能通過的單元測試前,不能編寫生產(chǎn)代碼
  • 只能編寫剛好不能通過的單元測試疮方,不能編譯也算不通過
  • 只能編寫剛好足以通過當前失敗測試的生產(chǎn)代碼
    我對上述定律的理解控嗜,首先必須先寫單元測試再寫實現(xiàn),同時在寫單元測試和實現(xiàn)時必須保持小步前進骡显。由于真實項目的業(yè)務(wù)邏輯往往很復(fù)雜疆栏,一個story如何拆分tasking,需要在小步和項目進度之間做權(quán)衡惫谤,也取決于對TDD和重構(gòu)掌握的熟練程度壁顶。
  1. 整潔的測試
    測試代碼最重要的是可讀性,明確溜歪、簡潔若专、有足夠的表達力。

  2. 一個測試一個斷言
    作者認為單個斷言是個好的準則蝴猪,一個測試方法的斷言數(shù)量要盡量少调衰。
    但太過強調(diào)單個斷言,會導(dǎo)致given和when部分有很多重復(fù)代碼自阱。
    我自己TDD的體會咱士,一個測試方法對應(yīng)一個test-case,如果測試用例拆得足夠小胳赌,測試方法中的斷言自然就會少酥诽,這和作者提到的每個測試一個概念應(yīng)該是一致的。

  3. F.I.R.S.T
    測試還應(yīng)遵守以下5條規(guī)則琼懊。

  • 快速(fast) 測試應(yīng)該能快速運行阁簸,太慢了你就不會頻繁的運行,就不會盡早發(fā)現(xiàn)問題哼丈。
  • 獨立(independent) 測試應(yīng)該相互獨立启妹,某個測試不應(yīng)該為下個測試設(shè)定條件。當測試相互依賴醉旦,一個沒通過導(dǎo)致一連串的測試失敗饶米,使問題診斷變的困難。
  • 可重復(fù)(repeatable) 測試應(yīng)該可以在任何環(huán)境中重復(fù)通過车胡。
  • 自足驗證(self-validating) 測試應(yīng)該有布爾值輸出檬输,無論通過或失敗,不應(yīng)該是查看日志文件去確認
  • 及時(timely) 單元測試應(yīng)該恰好在使其通過的生產(chǎn)代碼之前編寫匈棘。

小結(jié)
關(guān)于單元測試的內(nèi)容還有很多丧慈,這一章主要還是強調(diào)保持整潔的測試

十、類

  1. 類的組織
    公共靜態(tài)常量 - 私有靜態(tài)變量 - 私有實體變量 - 公共方法 - 私有方法逃默,保證自頂向下的閱讀順序鹃愤。

  2. 類應(yīng)該短小
    如何判斷一個類是否太長,主要看類是否承擔了多個職責完域。
    單一職責原則是OO最容易理解和遵循的原則软吐,通常也是被違反得最多的原則。類或模塊應(yīng)有且只有一條加以修改的理由吟税。系統(tǒng)應(yīng)該有許多短小的類而不是巨大的類組成凹耙,每個小類封裝一個職責。

  3. 內(nèi)聚
    如果一個類中的每個變量都被每個方法所使用乌妙,則該類具有最大的內(nèi)聚性使兔。內(nèi)聚性高,意味著類中的方法和變量相互依賴藤韵,相互結(jié)合成一個邏輯整體虐沥。
    保持內(nèi)聚性就能得到短小的類,一旦發(fā)現(xiàn)類失去內(nèi)聚性泽艘,就拆分它欲险!當某些實體變量只被少數(shù)方法使用,就應(yīng)該拆分出一個類匹涮。

  4. 為了修改而組織
    通過多態(tài)將一個大類中的細節(jié)隔離天试,等同于把修改隔離,符合開閉原則然低。
    讓調(diào)用方依賴接口而不依賴細節(jié)喜每,符合依賴倒置原則
    隔離細節(jié)雳攘,更利于單元測試带兜。

十一、系統(tǒng)

將系統(tǒng)的構(gòu)造和使用分開:構(gòu)造和使用是不一樣的過程吨灭。

  1. 工廠
    使用抽象工廠模式刚照,將構(gòu)造的細節(jié)隔離于應(yīng)用程序之外。

  2. 依賴注入(DI/IOC)
    在依賴管理情景中喧兄,對象不應(yīng)該負責實例化對自身的依賴无畔,反之,它應(yīng)該將這份權(quán)責移交給其他有權(quán)利的機制吠冤,從而實現(xiàn)控制的反轉(zhuǎn)浑彰。

  3. 擴容
    “一開始就做對的系統(tǒng)”純屬神話。
    反之拯辙,我們應(yīng)該只實現(xiàn)今天的用戶的需求闸昨。
    然后重構(gòu),明天再擴容系統(tǒng)薄风,實現(xiàn)新用戶的需求饵较。

  4. 面向切面編程(AOP)
    AOP中,被稱為方面(aspect)的模塊構(gòu)造指明了系統(tǒng)中哪些點的行為會以某種一致的方式被修改遭赂,從而支持某種特定的場景循诉。這種說明是用某種簡潔的聲明(Attribute)或編程機制來實現(xiàn)的。

小結(jié)
這一章的概念和描述比較多撇他,例子不多茄猫,看完并沒有很深的體會。
但是工廠模式困肩、依賴注入划纽、AOP這些在項目中都有應(yīng)用,關(guān)于Spring AOP可以參考《Spring實戰(zhàn)》和這篇文章Spring之AOP由淺入深

十二锌畸、迭進

  1. 簡單設(shè)計規(guī)則1 運行所有測試
    緊耦合的代碼難以編寫測試勇劣。同樣編寫測試越多,就會越遵循DIP之類的原則潭枣,使用依賴注入比默,接口和抽象等工具盡可能減少耦合。如此一來設(shè)計就會有長足進步盆犁。遵循有關(guān)編寫測試并持續(xù)運行測試的命咐、明確的規(guī)則,系統(tǒng)就會更貼近OO低耦合度谐岁、高內(nèi)聚的目標醋奠。

  2. 簡單設(shè)計規(guī)則2 重構(gòu)
    在重構(gòu)過程中,可以應(yīng)用有關(guān)優(yōu)秀軟件設(shè)計的一切知識伊佃,提升內(nèi)聚性窜司,降低耦合度。換句話說:消除重復(fù)锭魔,保證表達力例证,盡可能的減少類和方法的數(shù)量。

  3. 不可重復(fù)
    重復(fù)代表著額外的工作迷捧、額外的風險和額外不必要的復(fù)雜度织咧。重復(fù)有多種表現(xiàn)。雷同的代碼行是一種漠秋。不但是從代碼行的角度笙蒙,也要從功能上消除重復(fù)。

  4. 揭示程序員意圖

十三庆锦、并發(fā)編程

  1. 為什么要并發(fā)
    并發(fā)是一種解耦策略捅位,它幫助我們把做什么(目的)和何時(時機)做分解開。
    在單線程應(yīng)用中,目的與時機緊密耦合艇搀。
    而解耦目的與時機能明顯地改進應(yīng)用程序的吞吐量和結(jié)構(gòu)尿扯。
    從結(jié)構(gòu)的角度看,應(yīng)用程序看起來更像是許多臺協(xié)同工作的計算機焰雕,而不是一個大循環(huán)衷笋。
    單線程程序許多時間花在等待Web套接字I/O結(jié)束上面。

  2. 迷思與誤解

  • 并發(fā)總能改進性能:并發(fā)有時能改進性能矩屁,但只在多個線程或處理器之間能分享大量等待時間的時候管用辟宗。

  • 并發(fā)編程無需修改設(shè)計:并發(fā)算法的設(shè)計可能與單線程系統(tǒng)的設(shè)計極不相同,目的與時機的解耦往往對系統(tǒng)結(jié)構(gòu)產(chǎn)生巨大影響吝秕。

  • 在采用Web和EJB容器時泊脐,理解并發(fā)問題不重要:最好了解容器在做什么,如何應(yīng)付并發(fā)更新烁峭、死鎖等問題容客。

  • 并發(fā)會在性能和編寫額外代碼上增加一些開銷

  • 正確的并發(fā)是復(fù)雜的则剃,即使對于簡單的問題也是如此耘柱。

  • 并發(fā)缺陷并非總能重現(xiàn),所以常被看做偶發(fā)事件而忽略棍现,而未被當做真的缺陷看待调煎。

  • 并發(fā)常常需要對設(shè)計策略的根本性修改

平時工作中并發(fā)編程涉及得很少己肮,讀起來體會不深士袄,轉(zhuǎn)載一篇java并發(fā)編程相關(guān)的文章,以后繼續(xù)學習
關(guān)于Java并發(fā)編程的總結(jié)和思考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谎僻,一起剝皮案震驚了整個濱河市娄柳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌艘绍,老刑警劉巖赤拒,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異诱鞠,居然都是意外死亡挎挖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門航夺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蕉朵,“玉大人,你說我怎么就攤上這事阳掐∈夹疲” “怎么了冷蚂?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長汛闸。 經(jīng)常有香客問我蝙茶,道長,這世上最難降的妖魔是什么蛉拙? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任尸闸,我火速辦了婚禮,結(jié)果婚禮上孕锄,老公的妹妹穿的比我還像新娘。我一直安慰自己苞尝,他們只是感情好畸肆,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宙址,像睡著了一般轴脐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抡砂,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天大咱,我揣著相機與錄音,去河邊找鬼注益。 笑死碴巾,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的丑搔。 我是一名探鬼主播厦瓢,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼啤月!你這毒婦竟也來了煮仇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤谎仲,失蹤者是張志新(化名)和其女友劉穎浙垫,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體郑诺,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡夹姥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了间景。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佃声。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖倘要,靈堂內(nèi)的尸體忽然破棺而出圾亏,到底是詐尸還是另有隱情十拣,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布志鹃,位于F島的核電站夭问,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏曹铃。R本人自食惡果不足惜缰趋,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望陕见。 院中可真熱鬧秘血,春花似錦、人聲如沸评甜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忍坷。三九已至粘舟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間佩研,已是汗流浹背柑肴。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留旬薯,地道東北人晰骑。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像袍暴,于是被迫代替她去往敵國和親些侍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容