有一句話說的很經典,好的程式不是給機器來讀的,能被機器讀懂的程式充其量算是正确的程式,而能被人讀懂的程式才算是好程式。那怎麼樣的程式才算是人能讀懂的程式呢,小弟不才雖沒寫過幾句代碼,但是還是想說說個人的看法。
個人認為寫好程式大概分為幾個步驟:
1.寫正确的程式,如果一個程式邏輯不對不能實作該有的功能,那麼哪怕你寫的再漂亮,用了再多的進階的程式設計技巧和算法,那也絕得不算是一個好的程式,隻能算是一個失敗的程式。
2.寫自己看得懂的程式。或許有人會說我寫的程式很好,很巧妙,用到了某種語言當中的非常巧妙的技巧,執行效率很高,占用資源很少,但是代碼隻有他一個人能看懂。或許如果過了一段時間之後它自己 再看當初自己寫的代碼也看不懂了。這種程式我們認為它不算是好程式。
3.寫别人看得懂的程式。如果你寫的程式給你的隊友來讀,他不不懂的話,那麼你寫的程式就不能算是好程式,真正的好的程式是随便把程式給誰來讀,他們都能很快的并且準确的讀懂你想寫什麼,就像是讀一本小說,别人能夠陶醉其中,而不是各種抱怨,各種讀不懂,各種挑刺。
那麼怎麼才能寫好的程式呢?小弟随沒寫很多的代碼,但是還算是讀過不少,下面來給自己做一個總結,就以UEFI的代碼作為執行個體:
一.合理的安排架構你的源碼,把相關性最強的部分組合在一起,盡量做到子產品内的内聚性,減少子產品間的耦合性。
把功能相關的内容放在一起,比如你有一個OEM相關的功能,需要在SEC,PEI,dxe三個階段都需要做一些特别的事情,那麼你就可以建立一個子產品,可以命名為OEMModule,它包含以下幾個檔案:OemSec.asm,OemPei.c,OemDxe.c,
Oemmake.mak,OemXxx.xxx等,在每一個檔案裡面實作相應階段但功能類似的功能。
二.合理的利用開發語言中的一些封裝的工具。
UEFI主要是用C語言開發的,那麼我們就可以使用C語言當中的一些好的功能,列舉如下:
1.在頭檔案裡面使用#ifndef #endif來保證頭檔案隻會被編譯一次,加快編譯速度和減少子產品間的幹擾。
2.使用#define來定義一些常量,比如數組長度,TURE FAILSE
3.使用#typedef來給我們自定義的變量重新取别名。如:
#typedef UINT64 EFI_PHYSICAL_ADDRESS;
#define EFI_SUCCESS RETURN_SUCCESS
4.使用#define來定義宏,把一些常見的語句封裝成代碼塊,雖然這樣會增加總代碼量,但是可以使代碼讀起來更簡潔。如:
#define EFI_SIZE_TO_PAGES(Size) (((Size) >> EFI_PAGE_SHIFT) + (((Size) & EFI_PAGE_MASK) ? 1 : 0))
5.使用#if等宏編譯指令來控制編譯順序,友善對項目進行配置。類似于支援的處理器架構,是否打開編譯優化選項,是否打開調試模式等,讓同一個方法能支援多種功能。如:
#if defined (MDE_CPU_IA32) #if defined DEBUG
6.合理的使用ASSERT()printf()CR()等工具,當出現issue的時候可以通過相應的工具把異常抛出來,友善調試。
7.合理的利用C語言中的結構體,共同體,位域,指針等來構造複雜的資料結構,并用其來服務我們要實作的功能。
8.合理的資料封裝與隐藏:類似該函數裡面的IN關鍵詞标示出了,該函數的參數是輸入的,EFI_HANDLEs是一個自定義變量,它展示給調用者是一個簡單的Void *類型,隻在其核心部分使用其真正的類型,通過Void *這個萬能的指指針,很好的實作了資料的封裝和實作的隐藏:CoreValidateHandle (
IN
EFI_HANDLE
UserHandle )
三.選擇并形成一套自己的程式設計習慣,如命名規則等
選擇自己的變量函數命名規則,并長期堅持形成習慣。如:UEFI當中常用的幾種習慣:
1.全局變量:LIST_ENTRY gHandleList
2.結構内部變量:
LIST_ENTRY mProtocolDatabase
3.類似駝峰命名法和匈牙利命名法的合體的命名規則:
EFI_LOCK gProtocolDatabaseLock
四.要寫好的注釋,而不僅僅是寫注釋。
寫好注釋,而不是寫注釋,寫錯誤的注釋往往比沒寫注釋更可怕。
PROTOCOL_INTERFACE *
CoreGetProtocolInterface (
IN EFI_HANDLE UserHandle,
IN EFI_GUID *Protocol
)
{
EFI_STATUS Status;
PROTOCOL_ENTRY *ProtEntry;
PROTOCOL_INTERFACE *Prot;
IHANDLE *Handle;
LIST_ENTRY *Link;
Status = CoreValidateHandle (UserHandle);
if (EFI_ERROR (Status)) {
return NULL;
}
Handle = (IHANDLE *)UserHandle;
//
// Look at each protocol interface for a match
//
for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
ProtEntry = Prot->Protocol;
if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
return Prot;
}
}
return NULL;
}
五.先到這裡,下次再總結。
轉載請注明出處
[email protected] // http://blog.csdn.net/CStyle_0x007