探索系統架構的第一步,就是找到程式的入口點。找到入口點後,多半採取由上而下(Top-Down)的方式,由最外層的結構,一層一層逐漸探索越來越多的細節。
我們的開發團隊曾針對Winamp的iPod plug-in進行閱讀及探索,不僅找到入口點,也找出、並理解它最根本的基礎架構。從這個入口點,可以往下再展開一層,分別找到三個重要的組成及其意義:
● init():
初始化動作
● quit():
終止化動作
● PluginMessageProc():
以訊息的方式處理程式所必須處理的各種事件
展開的同時,隨手記錄樹狀結構
當我們從一個入口點找到三個分支後,可以順著每個分支再展開一層,所以分別繼續閱讀init、quit、以及PluginMessageProc的內容,並試著再展開一層。閱讀的同時,你可以在文件中試著記錄展開的樹狀結構。
● init():
初始化動作
● itunesdb_init_cc():
建立存取iTunes database的同步物件
● 初始化資料結構
● 初始化GUI元素
● 載入設定
● 建立log檔
● autoDetectIpod():
偵測iPod插入的執行緒
● quit():
終止化動作
● itunesdb_del_cc():
終止存取iTunes database的同步物件
● 關閉log檔
● 終止化GUI元素
● PluginMessageProc():
以訊息的方式處理程式所必須面臨的各種事件
● 執行所連接之iPod的MessageProc()
這部分必須要留意幾個重點。首先,應該一邊閱讀,一邊記錄文件。因為人的記憶力通常有限,對於陌生的事物更是容易遺忘,因此邊閱讀邊記錄,是很好的輔助。
再者,因為我們採取由上而下的方式,從一個點再分支出去成為多個點,因此,通常也會以樹狀的方式記錄。除此之外,每次只試著往下探索一層。從init()來看你便會明白。以下試著摘要init()的內容:
int init() {
itunesdb_init_cc();
currentiPod=NULL;
iPods = new C_ItemList;
…略
conf_file=(char*)SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_GETINIFILE);
m_treeview = GetDlgItem(plugin.hwnd LibraryParent,0x3fd);
//this number is actually magic :)
…略
g_detectAll = GetPrivateProfileInt("ml_ipod", "detectAll",0,conf_file)!=0;
…略
g_log=GetPrivateProfileInt("ml_ipod","log",0,conf_file)!=0;
…略
g_logfile=fopen(g_logfilepath,"a");
…略
autoDetectIpod();
return 0;
}
因為我們只試著多探索一層,而目的是希望發掘出下一層的子動作。所以在init()中看到像「itunesdb_init_cc();」這樣的函式呼叫動作時,我們知道它是在init()之下的一個獨立子動作,所以可以直接將它列入。但是當看到如下的程式行:
currentiPod=NULL;
iPods = new C_ItemList;
我們並不會將它視為init()下的一個獨立的子動作。因為好幾行程式,才構成一個具有獨立抽象意義的子動作。例如以上這兩行構成了一個獨立的抽象意義,也就是初始化所需的資料結構。
理論上,原來的程式撰寫者,有可能撰寫一個叫做init_data_structure()的函式,包含這兩行程式碼。這樣做可讀性更高,然而基於種種理
由,原作者並沒有這麼做。身為閱讀者,必須自行解讀,將這幾行合併成單一個子動作,並賦予它一個獨立的意義──初始化資料結構。
無法望文生義的函式,先試著預看一層
對於某些不明作用的函式叫用,不是望其文便能生其義的。當我們看到「itunesdb_init_cc()」這個名稱時,我們或許能從
「itunesdb_init」的字眼意識到這個函式和iPod所採用的iTunes
database的初始化有關,但「cc」卻實在令人費解。為了理解這一層某個子動作的真實意義,有時免不了要往前多看一層。
原來它是用來初始化同步化機制用的物件。作用在於這程式一定是用了某個內部的資料結構來儲存iTunes database,而這資料結構有可能被多執行緒存取,所以必須以同步物件(此處是Windows的Critical Section)加以保護。
所以說,當我們試著以樹狀的方式,逐一展開每個動作的子動作時,有時必須多看一層,才能真正了解子動作的意義。因為有了這樣的動作,我們可以在展
開樹狀結構中,為itunesdb_init_cc()附上補充說明:建立存取itunes
database的同步物件。這麼一來,當我們在檢視自己所寫下的樹狀結構時,就能輕易一目了然的理解每個子動作的真正作用。
根據需要了解的粒度,決定展開的層數
我們究竟需要展開多少層呢?這個問題和閱讀程式碼時所需的「粒度(Granularity)」有關。如果我們只是需要概括性的了解,那麼也許展開兩層或三層,就能夠對程式有基礎的認識。倘若需要更深入的了解,就會需要展開更多的層次才行。
有時候,你並不是一視同仁地針對每個動作,都展開到相同深度的層次。也許,你會基於特殊的需求,專門針對特定的動作展開至深層。例如,我們閱讀
Winamp iPod plug-in的程式目錄,其實是想從中了解究竟應該如何存取iPod上的iTunes
DB,使我們能夠將MP3歌曲或播放清單加至此DB中,並於iPod中播放。
當我們層層探索與分解之後,找到了parseIpodDb(),從函式名稱判斷它是我們想要的。因為它代表的正是parse iPod DB,正是我們此次閱讀的重點,也就達成閱讀這程式碼的目的。
我們強調一種不同的做法:在閱讀程式碼時,多半採取由上而下的方式;而本文建議了一種記錄閱讀的方式,就是試著記錄探索追蹤時層層展開的樹狀結構。你可以視自己需要,了解的深入程度,再決定要展開的層數。你更可以依據特殊的需要,只展開某個特定的節點,以探索特定的細目。
適度地忽略不需要了解的細節,是一個很重要的態度,因為你不會一次就需要所有的細節,閱讀都是有目的的。每次的閱讀也許都在探索程式中不同的區域;而每次探索時,你都可以增補樹狀結構中的某個子結構。漸漸地,你就會對這個程式更加的了解。
|
相关推荐
( 1 )读懂程式码,使心法皆为我所用。 ( 2 )摸清架构,便可轻松掌握全貌。 ( 3 )优质工具在手,读懂程式非难事。...( 5 )找到程式入口,再由上而下抽丝剥茧。 ( 6 )阅读的乐趣,透过程式码认识作者。
1.读懂程序码、使心法皆为我所用 2.摸清架构、便可轻松掌握全貌 3.找到程序入口、由上而下抽丝剥茧
20210222-中金公司-教育行业在线教育系列之二:抽丝剥茧,详解在线K~12教培经济模型.pdf
教育行业在线教育系列之二:抽丝剥茧,详解在线K_12教培经济模型
调味品行业深度报告:抽丝剥茧,社区团购对调味品影响下的得与失.pdf
20210728-华西证券-调味品行业深度报告:抽丝剥茧,社区团购影响下的得与失.pdf
新零售深度报告:抽丝剥茧看盒马.pdf
混合式app开发只需要要求开发者会使用css和js前端代码就可以实现手机app应用的开发,而不需要再去学习安卓或苹果开发,降低了app开发的门槛。混合式开发做出的手机应用无论在性能还是易用性方面都很接近原生app应用...
抽丝剥茧剖析2022台湾建筑奖首奖知识.pdf
调味品行业深度报告:抽丝剥茧,社区团购对调味品影响下的得与失(2021)(24页).pdf
Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑...从框架入口开始抽丝剥茧,理解其每一个核心概念以及作用,并将这些核心技术点融汇起来 探究每一个核心的实现细节(UML图、跑单元测试用例、DEBUG,体悟)
抽丝剥茧App混合开发进阶课【视频课程】下载整理.zip含下载地址可存云盘
翻遍网络抽丝剥茧:怎堪高空“艳遇”人间蒸发
抽丝剥茧的学前端之React篇。 一点一滴的把我所有学到的和react项目搭建的知识都总结在了这里。也算是我的一次心路历程吧……
新零售深度报告:抽丝剥茧看盒马,写在马云巡店之后.pdf
光大证券_0607_技术形态选股系列报告之三:抽丝剥茧解缠论.pdf
食品饮料行业研究周报:白酒回调需抽丝剥茧,长期逻辑值得坚守.pdf
教育行业新机遇系列之四:抽丝剥茧,探寻民办学校成长真谛-180306.pdf
就业报告系列之一:抽丝剥茧,就业压力并不大-0226-光大证券-19页.pdf