1. 程式人生 > >如何寫程式碼--編碼內功心法

如何寫程式碼--編碼內功心法

寫程式碼就是學一門語言然後開始擼程式碼嗎?看完了我的《GoF設計模式》系列文章的同學或者本身已經就是老鳥的同學顯然不會這麼認為。程式設計是一項非常嚴謹的工作!雖然我們自嘲為碼農,但是這工作畢竟不是真正的搬磚,我們是軟體工程師。程式設計需要關注的問題太多,不僅僅有語言,還有演算法、資料結構、程式設計技巧、編碼風格、設計、架構、工程化、開發工具、團隊協作等方方面面,涉及到很多層面的問題。本文將分享一下根據我這幾年來的程式設計經驗總結出的一些關於如何寫程式碼的個人見解。

由於“跟我混”的一些小夥伴程式設計功底相對來說比較薄弱,所以在此總結一篇“程式設計內功心法”幫助他們渡過職業生涯的第一個瓶頸期。順便,也造福一下路過的有緣的同學!於是有了此文。

前言

首先,思考一個問題,何謂程式設計?程式設計就是寫程式碼嗎?

所謂的程式設計,其實就是不斷的對這個現實世界中的問題建立模型並將其固化為程式碼自動化執行的過程。
Bug輝 《GoF設計模式 - 直譯器模式

在對問題建立模型的過程中,我們會遇到非常多不同層面的問題,所以我們需要很多領域的知識去解決這些問題。

  • 我們需要管理被操作的資料,因為資料與資料之前是相互有關聯的。將資料結構化,通常是程式設計的第一步。關於結構化資料的相關理論以及實踐,需要有一個專門的學科分支或者說課題去研究——資料結構
  • 我們需要解決一個具體的問題,這個具體的問題如何一步步去解決,過程是怎麼樣子的——演算法
  • 我們需要將解決方案進行自動化,並以程式碼的形式進行交付——程式語言
  • 如果將一個抽象的模型進行編碼實現,如何實現“這個功能”,如何實現“那個功能”——程式設計技巧
  • 問題的規模大了,眾多程式碼糅合在一起,連程式設計師自己都看不懂了!怎麼來拆分、模組化這些程式碼——設計
  • 程式碼量已經到了一個人無法完成的地步了,需要團隊分工合作才能完成了——工程化
  • 你寫的程式碼我看不懂,沒法呼叫或者很難呼叫,我寫的程式碼你也看不懂,或者很難看懂。還怎麼愉快的玩耍——編碼風格/編碼規範
  • 問題的規模繼續擴大,到了系統工程的規模了,之前學的套路已經不管用了!怎麼來構建這個系統才能實現正確、安全、高效能、高可用——架構

然而這些也只是一個系統工程中的冰山一角!這是一個龐大的體系。也正是因為軟體開發需要考慮到的問題太多且團隊成員水品參差不齊,所以團隊開發中並不是每個程式設計師做的事情都是一樣的。每個人都有自己的角色、初級工程師、中級工程師、高階工程師、架構師、CTO。。。

所以程式設計不僅僅只是堆砌程式碼!

說到這裡,我想起來了一件事情——為啥業界普遍鄙視培訓出來半道出家的新人?人與人的區別是很大的!我見過培訓出來也很牛的。其實,說到底,被鄙視的並不是所有人。而是那些培訓了幾個月之後發現隨便找個工作也能拿“高薪”然後還自認為程式設計很簡單的新人。因為這種經歷給了他們一種錯覺——程式設計如此簡單,我培訓幾個月也會嘛!有點像剛學會開車的新司機,很囂張的對老司機說“開車很簡單嘛!你看我也會啊!”。語言和開發工具只是招式,這是外功。而程式設計思想、經驗是內功。這些內功並不是靠短短几個月的培訓能夠掌握的,這一點有點像中國製造業和日本製造業的區別。動不動趕英超美可不好。。。

程式設計並不簡單!這是一件很嚴肅的事情。不過今天,我沒有辦法介紹完所有的方面!或者說,到今天為止,我也並沒能掌握所有領域的知識。所以今天我只是分享一些關於編碼本身的一些經驗。

另外,本文主要分享如何寫程式碼,並不是如何用Java寫程式碼。所以文章中各種語言都有可能出現。

編碼風格

先來一個圈內的段子。
大部分程式設計師在工作中都很討厭這四件事情:

  1. 寫註釋
  2. 寫文件
  3. 別人不寫註釋
  4. 別人不寫文件

o(∩_∩)o 哈哈。。中槍了沒!

這個段子其實反映出來一個問題,即大部分程式碼都需要通過大量註釋和文件來說明才能將意圖傳達給維護這些程式碼的程式設計師!然而,就像上面的段子說的那樣,寫大量的註釋和文件其實是一件很麻煩的事情。所以很多時候,由於嫌麻煩,註釋和文件就沒寫,導致維護程式碼的人相當的痛苦。這個苦同學們肯定都是體會過的!相當於給你個精密儀器要你維護還不給說明書。

其實,打破上面那個段子描述的那個怪圈的一個很有效的手段就是統一編碼風格。優秀的程式碼可以實現程式碼即註釋,程式碼本身就可以非常清晰的體現出它的意圖來,讓別人可以很容易讀懂。這就是所謂的可讀性!

命名

電腦科學領域中最難的兩件事是命名和快取失效!命名並不簡單,很複雜。好的名字可以見名知意,非常容易理解。之所以說命名難是因為命名的過程同時也是概念提取的過程!對問題建立模型,需要提取概念並賦予其“術語”。這個過程其實是“萬里長征”中最難的一步。畢竟,設計也好,架構也罷,都有成熟的套路可以參考。唯獨這個過程,是需要程式設計者自己進行充分的思考的創造性工作!

以下是總結出來的一些命名經驗:

  • 一個類是某物、某事、某人的抽象,是資料與行為的集合體。這恰好符合名詞的定義,因此 類名 是一個名詞!
  • 方法名 或者說 函式名 是某操作或者某過程的抽象,是一個動作。這恰好符合動詞的定義,因此函式名通常是一個動詞。
  • 變數名寧可長一些說明清楚用途也不要用abc之類的無意義的名稱,除非是迴圈計數器中用ijk等約定俗成的一些變數名。比如pageIndexpageSize就要比取名成is好!取成這種和用混淆器混淆過後的程式碼一樣的名稱沒有什麼好處,如果演算法比較複雜的話,過一段時間恐怕自己都會看不懂。
  • 變數名最好包含變數本身的業務含義。比如List<Student> studentList = new ArrayList<>();就比List<Student> list = new ArrayList<>();好很多。如果同一段程式碼裡再出現一個List<Teacher>的話,這樣就可以很方便的取名為teacherList或者teachers而不是list1list2這樣的毫無意義的名稱!

英文不好怎麼辦

這個問題怎麼說呢。。
作為一名程式設計師吧,基礎的英文還是要懂的。要不然發展也容易遇到天花板,學不好程式設計的。畢竟,最新的技術、解決方案、工具都是從國外傳過來的。如果是解決一些基礎性的問題,每天只做做CRUD,好像英文確實不怎麼用得上。但是一旦遇到一些實質性問題,恐怕只能到英文網站上找嘍!ㄟ(▔ ,▔)ㄏ 不要跟我說你程式設計可以不需要Stack Overflowcopying and pasting from stackoverflow 可是終極程式設計大法!o(∩_∩)o 這句話可是程式設計的真諦啊!(如果你看不懂這個梗那你有可能是偽程式設計師)

其實,話說回來,實在不方便用英文的時候,我認為也可以用拼音命名。這個問題上可以務實一點,量力而行。但是,拼音和英語混用的做法就不太好了。最好別這樣!逼格不高。

註釋

怎麼新增程式碼註釋

關於註釋,我們需要解決的第一個問題是如何新增程式碼註釋。

對於Java、C#之類的語言,有專用的文件註釋語法,很好處理。對於C/C++,則按約定的格式說明一下類和函式、程式碼片段的作用和意圖即可,至少編譯器會進行靜態檢查。在Python中,有更牛逼的文件字串這樣的語言級特性支援,看註釋用help()很方便。不過對於Lua這樣的弱型別解釋型語言,註釋就比較難處理了。這裡以Lua為例給出一種註釋的解決方案。

借用Java語言文件註釋的風格。

檔案註釋,或者說類/模組註釋。

--[[    Object-oriented helper functions for Lua@author: Elvin Zeng@date:2017-8-21--]]

函式註釋

--[[    create a class with specified super class.    if number of parameters is zero, derived class will extends from {}.@paramsuperClass super class of target class@return derived class--]]
local function createClass(superClass)
    local derivedClass = {}

    --  省略一堆程式碼

    return derivedClass
end
--[[    register a new account@paramuser      {        username = "username",        password = "password"      }@return registered user--]]
local function register(user)

end

tips: Lua中可以通過metatable機制實現類和繼承,這一點與Javascript通過原型機制來實現類和繼承有點類似。

註釋裡該寫些什麼

我們首先來看個反例。

/** * 查詢 */
public List<Article> queryPage(int pageSize, int pageIndex) throws PageIndexOutOfBoundsException {
    //  定義一個整型變數
    int offset;

    //  省略一堆程式碼
}

首先這個方法名本身就取得不好,這個暫且不說,先說註釋問題。這裡的註釋犯了幾個錯:

  1. 方法註釋為“查詢”,這簡直就是廢話!方法名已經告訴別人這是查詢方法了,還在這個註釋裡寫這兩個字有什麼意義呢?而且到底查詢些什麼這裡也沒說!
  2. 引數沒有註釋。沒有描述每一個引數的意義以及取值範圍等!
  3. 什麼情況下會丟擲PageIndexOutOfBoundsException沒有描述清楚。
  4. “定義一個整型變數”這種垃圾註釋就不要寫了,這麼簡單的語句誰看不懂啊!如果要註釋,也是寫上這個變數的含義。

這裡我們先不考慮設計問題(分頁索引號最好做成可以自己調整成合理值),下面再來看改善註釋之後的程式碼。

/** * 列出指定分頁的文章 * @param pageSize 分頁大小。如果等於0則表示查詢出所有文章。 * @param pageIndex 分頁索引號。必須為一個大於0的整數,第一頁索引為1。 * @return 指定分頁的文章列表 * @throws PageIndexOutOfBoundsException 當分頁索引號超出正常範圍時丟擲,即pageIndex小於0或大於最大頁索引時。 */
public List<Article> listArticle(int pageSize, int pageIndex) throws PageIndexOutOfBoundsException{
    //  第一條文章記錄在MySql資料庫中的偏移量
    int offset;

    //  省略一堆程式碼
}

改完之後的註釋有沒有感覺資訊更全很多!雖然說程式碼本身就是最好的註釋,但是必要的註釋還是得寫上去,畢竟呼叫的時候別人沒法猜測你的索引號到底從0還是從1開始。另外,如果函式內演算法比較複雜,可以在程式碼塊內註釋,也可以在函式註釋上直接寫清楚這個函式內部的大概演算法/邏輯。程式碼寫出來就是給別人呼叫的,如果沒有基本的註釋資訊,那麼每次呼叫你的程式碼的時候,都得去看一下你的函式內具體邏輯才能知道怎麼呼叫。這顯然是非常低效的!

命名與註釋這兩個基本方面沒做好的話,會影響到整個團隊的運作。也就是說,你封裝的東西並沒有給隊友節省什麼時間,別人用到你的程式碼的時候,又需要花上一些時間去讀你的程式碼。如果團隊裡每個人都這樣,那整個團隊都會極其低效。我個人是非常不願意與這種程式碼風格惡劣的人合作的。

參考規範

關於編碼風格的問題,本文只說命名和註釋這兩個方面。關於縮排、空格、斷行、空行等其他方面的問題,可以參考本節給出的參考規範。

不同的企業會有不同的編碼規範,所以這裡沒有辦法給出一個符合所有公司的規範。不過制定自己團隊的規範的時候,可以參考一些大企業的做法。以下是世界上最大的網際網路公司谷歌的編碼規範,同學們可以參考這個。

異常處理

異常與返回值有什麼不同

在C語言中,我們的函式通常會返回一個整型值作為狀態碼用於通知客戶端呼叫的結果。比如0表示成功,非0表示失敗。並且可以通過不同的數值來表示不同原因導致的失敗。然而在Java、C#、C++一類面嚮物件語言中,一般不會用返回值來表示狀態。返回值一般用於表示返回的業務值,而異常用於通知客戶端程式執行狀態改變了。

什麼時候需要丟擲異常

關於這個問題,我想到了一句極其精煉的話:當函式無法完成宣稱的任務的時候丟擲異常!
比如上面的那個日子,當listArticle方法由於種種原因無法查詢出文章列表的時候,則丟擲異常。

丟擲異常在這種場景下是非常有必要的,因為這樣其他人呼叫你的程式碼時可以非常放心的去呼叫,只要呼叫了你的方法,就會返回文章列表。如果無法返回文章列表,則會丟擲異常。完全不用在呼叫這個函式的時候去懷疑是否執行成功了。

再來一句至理名言:

寧願終止程式也不要帶錯執行下去。

也就是說,遇到錯誤的時候,寧願丟擲異常終止程式,也不要帶著錯執行下去。這是在掩耳盜鈴!

異常需要攜帶什麼資訊

首先,異常的型別本身會帶有異常種類資訊。其次,異常的message屬性可以帶上更詳細一些的資訊。這裡需要注意,千萬不要像下面這麼做。

throw new PageIndexOutOfBoundsException("失敗!");

丟擲異常了肯定是執行失敗了呀!帶上這種資訊有什麼用,不是帶了一句廢話嘛!
應該是下面這樣

throw new PageIndexOutOfBoundsException("引數分頁索引號pageIndex不能大於分頁總數");

此外,異常堆疊也會攜帶很多資訊。

日誌

談到日誌,首先要搞清楚一個問題,日誌是幹嘛用的?
用來記錄執行時的錯誤資訊啊!
是啊。好像大家都知道日誌是幹什麼用的,但是為什麼寫起程式碼來就會忘記初衷呢!
來看看程式碼:

/** * 非同步傳送通知郵件。 * @param templateFile 郵件模板檔案路徑,相對於classpath。 * @param modelMap 模型物件 */
publicvoidsendEmail(String templateFile, Map<String, String> modelMap){
    //  這裡省略一些程式碼
    System.out.println("1");
    //  這裡省略一些程式碼
    System.out.println("2");
    //  這裡省略一些程式碼
}

這裡的程式碼是什麼意思呢?程式設計師們應該都能明白的!很顯然,這位程式設計師是想借助這些標記來除錯,想知道程式碼到底執行到哪一行了。但是,這裡很明顯地犯了兩個錯。

  1. 為什麼是System.out.println("");而不是logger.debug("");?
  2. 為什麼是12而不是一些更明確的文字資訊呢?

在這裡,合理的方式是下面這樣。

/** * 非同步傳送通知郵件。 * @param templateFile 郵件模板檔案路徑,相對於classpath。 * @param modelMap 模型物件 * @throws ServiceException 當郵件模板檔案不存在或者modelMap中缺少必須的欄位。 */
 publicvoidsendEmail(String templateFile, Map<String, String> modelMap) throws ServiceException{
     //  這裡省略一些程式碼
     if (isTemplateExists){
         logger.debug("模板檔案存在");
         //  這裡省略一些程式碼
         logger.debug("郵件傳送任務成功入隊。任務id:" + taskId);
         //  這裡省略一些程式碼
     }else{
         logger.error("指定的模板檔案[" + templateFile + "]不存在,郵件傳送失敗。");
         //  丟擲異常
     }
 }

我想給正在犯上面的錯的同學提個醒:

  1. 使用日誌框架,並用合適的級別輸出日誌非常重要。
    好多程式設計師從來不負責也不參與運維相關的工作,甚至是做了好幾年的Web都從來沒有自己釋出過網站。所以壓根沒有後期維護的意識!
    如果沒有這些日誌,當專案上線之後,運維的背鍋俠兄弟發現網站掛了之後只能直接重啟,然後當作什麼也沒看到。因為沒有排錯的線索。

  2. 輸出有效資訊。
    不要去輸出一些像123成功失敗hello這樣的毫無意義的日誌,要輸出logger.debug("郵件傳送任務成功入隊。任務id:" + taskId);這樣的有效資訊。
    也許當時你除錯的時候,在你看來這些奇怪的字串是有意義的,但是在其他人看來,這些就是天書。運維的背鍋俠會提刀過來砍你的!另外像"-------開始執行--------"這種對執行期間定位問題沒有半點好處的日誌就不要輸出了!自己用可以,提交程式碼前一定要刪掉。

  3. 日誌中帶上上下文資訊。
    孤立的一句錯誤日誌通常沒有什麼實際作用。比如上面的例子中,如果在找不到指定的模板檔案的時候未將傳送郵件時指定的模板檔名輸出,那麼排錯的時候無法知道到底是少了哪個模板檔案。

  4. 不要在日誌中輸出使用者的敏感資訊。
    千萬不要在日誌中輸出像使用者密碼、郵件內容之類的涉及使用者隱私的敏感資訊,也不要去輸出像驗證碼的值之類的敏感資訊。

引數校驗

在你對外公開的方法前先插入一些檢查引數的程式碼,以確保方法被“正確的姿勢”呼叫。比如:

/** * 列出指定分頁的文章 * @param pageSize 分頁大小。如果等於0則表示查詢出所有文章。 * @param pageIndex 分頁索引號。必須為一個大於0的整數,第一頁索引為1。 * @return 指定分頁的文章列表 * @throws PageIndexOutOfBoundsException 當分頁索引號超出正常範圍時丟擲,即pageIndex小於0或大於最大頁索引時。 */
public List<Article> listArticle(int pageSize, int pageIndex) throws PageIndexOutOfBoundsException{
    if (pageSize < 0){
        throw new IllegalArgumentException("pageSize不能小於0");
    }
    if (pageIndex < 1){
        throw new IllegalArgumentException("pageIndex不能小於1");
    }

    //  第一條文章記錄在MySql資料庫中的偏移量
    int offset;

    throw new PageIndexOutOfBoundsException("");

    //  省略一堆程式碼
}

引數校驗的作用

如果在對外公開的重要方法開始的位置不插入校驗引數的程式碼,有時恐怕方法需要執行到方法內部比較深的位置才會丟擲一個異常來。而且那種情況下,丟擲的異常可能就會有各種各樣的了。比如空指標、除零異常等。
這種情況下,很難一眼看出引發這個異常的根源是引數傳錯了。需要對你的程式碼進行一番除錯才行!如果一開始就在程式碼的入口插入了校驗引數的程式碼,那麼呼叫的時候,一眼就能看出來是引數傳錯了導致了一個異常。這樣其他程式設計師看到這個異常之後就會去看一下你的方法註釋。他一看,哦!原來分頁索引號是從1開始計數的,那麼這個問題就會就此打住,給團隊節省了時間。

引數校驗問題是會影響團隊執行效率的一個很關鍵的因素。所以,請同學們重視起這個問題來。我們都是工程師,團隊作戰的,自己寫程式碼快不叫快,整個團隊快起來才叫真的快!用好斷言,可以讓你的程式碼更健壯。

tips: Java中預設斷言是不開啟的,所以建議無視Java語言的斷言,自己處理。

什麼時候需要進行引數校驗

我認為一個方法或者函式在滿足以下條件時有必要進行引數校驗:

  1. 方法或者函式是對外公開的,不是私有的。
  2. 引數有可能為空指標的時候。
  3. 引數的合理值無法通過方法名、引數名、引數型別一眼看出來的時候!比如上面那個pageIndex是從1開始計數的,但別人並不知道你是從1開始計數的。

如果對每一方法都進行校驗的話,其實挺麻煩的。程式設計師的時間是很寶貴的,沒這麼多閒工夫。不過在滿足上面條件的情況下,最好還是校驗一下。因為做了這個校驗,你自己是會稍微浪費幾分鐘的時間,不過從團隊整體來看,總的除錯損耗的時間卻降下來了。要記住方法/函式寫出來就是給別人呼叫的!

引數校驗需要做到什麼程度

我有一個標準,就是把自己當成呼叫這些程式碼的那個人,把自己想象成有可能以任何“姿勢”呼叫的菜鳥(實際上也有可能是不瞭解你的程式碼的大牛)。如果這個時候自己也有可能會犯某些錯(比如沒注意邊界值,沒注意是否可空),那麼這個時候是必須要做校驗的。對於一些已經在其他層做過處理不太可能有錯誤的值的情況,可以不做校驗。比如你的UserService中有一個簽名為public void register(User user)的方法,用於註冊一個使用者。這種情況下,可以只校驗一下user引數是否為空,而不用對userusernamepassword屬性進行校驗(使用者名稱密碼長度是否合法等)。因為你在上一層控制器層模型繫結的時候已經做過非常嚴謹的校驗了。當然,這裡如果你有充足的時間,也可以校驗一下。具體做到什麼程度,還需要你根據情況去自己把握。

後記

編碼規範就是用來約束別人的!
o(∩_∩)o 哈哈!開玩笑的啦!
其實很多時候,出於各種原因,如“專案週期緊”、“專案還在探索階段可行性未知,先實現了再說”、“專案中其他程式碼已經這樣了,破罐子破摔”等,最終導致的結果可能就是我們這些自稱“有經驗”的程式設計師自己也不一定能寫出完全符合這些理念的程式碼來。或許是吧!
ㄟ(▔ ,▔)ㄏ
我承認,我也寫過奇葩程式碼。
但是,這好像並不是你這個作為未來優秀程式設計師的人不思進取的理由。

小時候,老師教我們要誠實,但是老師自己也不見得能完全做到。我們可以因為這個鄙視他。
長大後,體驗過了生活中會有很多的無奈,不再鄙視“不誠實”的老師。甚至低下了高貴的頭,自己也變得那般模樣。
未來,你還會教育你的後代“要誠實”嗎?
恐怕會!
因為,優秀的理念,不管結局如何,都應該去提倡!

本文的觀點僅代表現在的我,人是會成長的,明天的我或許又會有新的見解! 如果你不認同部分觀點或者還有其他的優秀理念,可以給我留言。我們一起成長!

作者:Bug輝
本文是我的原創文章。獨立部落格連結:https://www.bughui.com/2017/08/21/how-to-write-code/
版權宣告:《如何寫程式碼 —— 程式設計內功心法》 由 Bug輝 採用 知識共享 署名-非商業性使用-禁止演繹 4.0 國際 許可協議 進行許可。轉載或引用文章時請註明原作者並帶上原文連結。

相關推薦

如何程式碼--編碼內功

寫程式碼就是學一門語言然後開始擼程式碼嗎?看完了我的《GoF設計模式》系列文章的同學或者本身已經就是老鳥的同學顯然不會這麼認為。程式設計是一項非常嚴謹的工作!雖然我們自嘲為碼農,但是這工作畢竟不是真正的搬磚,我們是軟體工程師。程式設計需要關注的問題太多,不僅僅有語言,還有演算法、資料結構、程式設計技巧、編碼

如何程式碼 —— 程式設計內功

寫程式碼就是學一門語言然後開始擼程式碼嗎?看完了我的[《GoF設計模式》](https://www.bughui.com/2017/06/10/gof-design-pattern-overview/)系列文章的同學或者本身已經就是老鳥的同學顯然不會這麼認為。程式設計是一項非常嚴謹的工作!雖然我們自

CMDB內功,助我登上運維之巔

cmdb 配置管理庫 數據中心很多70、80後甚至90後都在金庸、古龍、梁羽生先生等武林大家熏陶下成長的,這麽多年過去了,我的武俠夢依然不曾散去。曾幾何,夢想有一天練就一身絕學,摟著小師妹花前月下,仗劍走天涯,快意人生。可每次的酣睡美夢都被班主任大書板子給抽醒,在他們的鞭策之下,渾渾噩噩的成了一位IT騷年。我

編程內功

uid com amp .cn .com space hub ace pic http://pic.cnhubei.com/space.php?uid=1774&do=album&id=1436925http://pic.cnhubei.com/space.

GOF-內功

gof 出現 需要 com composite 依賴倒轉原則 lose 編程 ati 2018-1-17 by Atlas 設計模式的原則 開閉原則(Open Close Principle) 開閉原則就是說對拓展開放,對修改關閉。在程序需要進行拓展的時候,不能去修

Sql語句內功

CREATE SCHEMA <模式名> AUTHORIZATION <使用者名稱> 定義模式實際上定義了一個名稱空間,在這個空間可以進一步定義該模式包含的資料庫物件,例如基本表,檢視,索引   DROP SCHEMA <模式名>  <CASC

面向物件的內功

這裡分為兩個部分,內建方法和內建函式。當然,內建方法是特別的多的,這裡只是冰山一角,但一定都是最最能用的到的。這的內建函式也會講解一些特殊用法,都是減少程式碼的,提升程式碼質量。 從python深處說,應該先聊聊內建方法: __new__(cls,*args,**kwd)  構造方法, 可以開闢處一

面向對象的內功

int eth method 設置 @property 自己的 比較 反射 @class 這裏分為兩個部分,內置方法和內置函數。當然,內置方法是特別的多的,這裏只是冰山一角,但一定都是最最能用的到的。這的內置函數也會講解一些特殊用法,都是減少代碼的,提升代碼質量。 從pyt

內功

資料結構 和 演算法 設計模式   計算機組成原理 作業系統 計算機網路   以上這幾門是需要不斷去領會的東西,就像打基礎一樣,領會的越深,越能融匯貫通,到最後,無招勝有招,萬物皆可為武器!!!      

軟體設計六大內功

  我一直以為,世間萬事萬物,都存在著某種規律性的東西,只不過,有的已經被發現,有的還在人們的探索過程中,等待被發現,軟體設計亦然。其實,生活中的很多東西,是可以相通的(比如心和心)。   不是嗎?那本很有名的書《建築的永恆之道》,正是歸納出了長久以來,在人們漫長的經歷中摸索

spring原始碼分析,重新認識spring五(內功 從思想上說明 spring 常用的幾種設計模式,漫談)

動態代理:關注過程,關注的是整體的區域性,面向的切面思想。 抽象工廠:關注的是結果,隱藏實現 單例模式:整個環境內只有一個類,有餓漢和懶漢,餓漢即 類載入直接new 物件,懶漢 即使用的時候才new物件,比較有名的有 雙檢索 單例,因為直接用同步限制會導致每次取物件都是同步

快取內功:快取基礎整理

快取雪崩 快取雪崩是由於原有快取失效(過期),新快取未到期間。所有請求都去查詢資料庫,而對資料庫CPU和記憶體造成巨大壓力,嚴

兩萬字長文50+張趣圖帶你領悟網路程式設計的內功

# 前言 我大學是學網路工程專業,也就是那種拉網線,面向網線程式設計的。依稀記得學習計算機網路這門課程的時候搭建的`IT宅 itzhai.com`個人網站。 算一下,學這門課程也已經快十年了。 ![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b

02. 程式設計核心內功之泛型

# 泛型 ```java public static void main(String[] args) { //List list = new ArrayList(); //指定能夠存放的資料型別,統一型別防止出現 型別轉換異常 List list = new ArrayList()

【計算機內功】八:函式執行時在記憶體中是什麼樣子?

在開始本篇的內容前,我們先來思考幾個問題。 我們先來看一段簡單的程式碼: void func(int a) {    if (a > 100000000) return; &nbs

【計算機內功】六:10張圖讓你徹底理解回撥函式

不知你是不是也有這樣的疑惑,我們為什麼需要回調函式這個概念呢?直接呼叫函式不就可以了?回撥函式到底有什麼作用?程式設計師到底該如何理解回撥函式? 這篇文章就來為你解答這些問題,讀完這篇文章後你的武器庫將新增一件功能強大的利器。 一切要從這樣的需求說起 假設你們公司要開發下一代國民App“明日油條”,一款主打

【計算機內功】五:從小白到高手,你需要理解同步與非同步

在這篇文章中我們來討論一下到底什麼是同步,什麼是非同步,以及在程式設計中這兩個概念到底意味著什麼,這些是進一步掌握高效能、高併發技術的基礎,因此非常關鍵。 相信很多同學遇到同步非同步這兩個詞的時候大腦瞬間就像紅綠燈失靈的十字路口一樣陷入一片懵逼的狀態: mengbi 是的,這兩個看上去很像實際上也很像的詞彙

三萬長文50+趣圖帶你領悟web程式設計的內功:一文帶你深入解讀HTTP的發展史

看到題目,大家是不是認為根據上一篇([兩萬字長文50+張趣圖帶你領悟網路程式設計的內功心法](https://www.itzhai.com/articles/comprehend-the-underlying-principles-of-network-programming.html))一樣,其實不然,我們

【計算機內功】九:程式設計師應如何理解協程

作為程式設計師,想必你多多少少聽過協程這個詞,這項技術近年來越來越多的出現在程式設計師的視野當中,尤其高效能高併發領域。當你的同學、同事提到協程時如果你的大腦一片空白,對其毫無概念。。。 as-seen-on-tv-celebutard-emoticons-irl-reaction-guys-sham-wo

【計算機內功】十:執行緒間到底共享了哪些程序資源

程序和執行緒這兩個話題是程式設計師繞不開的,作業系統提供的這兩個抽象概念實在是太重要了。 關於程序和執行緒有一個極其經典的問題,那就是程序和執行緒的區別是什麼?相信很多同學對答案似懂非懂。 記住了不一定真懂 有的同學可能已經“背得”滾瓜爛熟了:“程序是作業系統分配資源的單位,執行緒是排程的基本單位,執行緒之