1、公司市場人員與客戶交流,了解客戶、引導客戶使用公司最優資源并產出一份市場需求文檔
2、公司需求人員(BA)與客戶交流,了解客戶需求并產出一個軟件需求文檔
3、項目經理、開發小組成員、需求人員(BA)一起開一個需求評審會議,對不合理的地方,
打回給BA,再由BA與客戶溝通
4、程序員接到和充分了解軟件需求文檔后產生軟件設計文檔(包括概要設計文檔和詳細設計文檔,
涉及到數據庫的還需要進行數據庫的設計)
5、程序員根據設計文檔進行編碼、調試、打包發布。如果編寫的函數庫,還可能編寫一份接口使用文檔,
如果程序是直接運行的軟件,還需要編寫一份用戶使用手冊,包括各種操作步驟和配置參數說明
6、軟件發布后,客戶可能進行一段時間的測試、或者將其投入運營。這期間會發現一些問題,還需要
程序員進行修復,這已經進行維護階段了,這個階段的周期很長,可能5年,也可能10年,或者更長
之所以寫了軟件項目的流程,只是想強調,軟件最花費時間的是維護階段。這個階段,維護人員可能是
原來的開發人員,但更可能是非原開發人員來維護的。在中國,IT從業人員流動性太大,一個項目的維護
更可能是之前沒接觸過這個項目的程序員。如果這個時候,文檔不齊全,將是一件很蛋疼的事情。
對一個程序員來說,這還不是一個最悲劇的事情。程序員要維護項目,最終還是要閱讀項目源代碼,
此時如果項目架構設計得很糟糕和代碼寫得亂七八糟的,想必維護人員在修改項目代碼時肯定會咒罵
原來的架構師和開發人員,正因為架構師的低水平設計,業務代碼、數據庫代碼、控制代碼深深耦合在
一起,改動一處總害得別人擔驚受怕,這因為開發人員沒有添加該有的注釋,命名的變量不能讓人見命思意,
編寫的代碼過渡冗余,重復的代碼多處使用,讓維護程序員改了這個地方卻不知道還有一個地方有相同的代碼
沒有修改,此時難保證維護程序員不砸了他的電腦。
每個公司都有自己的一套項目流程,自己的編程命名規范,
漸漸的,慢慢也形成了自己的編碼風格和命名風格。在此總結一下。這里主要總結C語言的,
因為java在這方面較C、C++做得相對夠好,就不啰嗦了,不過都有參考價值。
1、盡量不用全局變量
全局很容易破壞軟件的結構,增加代碼的耦合度,將模糊業務代碼、數據庫代碼、控制代碼的界限,
害得維護人員在閱讀代碼時,第一要務就是要追蹤全局變量在哪里,由于設計得不好,基本項目的
所有源代碼文件都涉及修改了全局變量,這一追蹤下來,不是一天半會能夠摸索清楚你要了解的某個
功能,盡管這個功能很小,你還是要看完這整個項目,太浪費時間了,不值得啊。
2、少用全局變量
有些項目由于硬件資源的限制,比如嵌入式開發,你不得不使用全局變量。在這種不可避免的情況下,
我們只能盡量減少使用全局變量。
3、別忘記加上static
如果你使用到的全局變量僅僅是某個源文件(模塊)使用到,別忘記給這個全局變量加上static。
4、別忘記加上const
如果你設計的接口(函數)有入參,而你不想修改這個入參,別忘記加上const。
5、明確哪些結構體、枚舉、聯合體、宏、常量需要全局使用,哪些需要全局使用
如果有的結構體、枚舉、聯合體、宏、常量僅僅是某個模塊需要使用,就沒必要放置在公共的頭文件中
如果結構體、枚舉、聯合體是需要公用的,就要考慮是否需要僅僅在公用頭文件中聲明,在某個源文件中
實現,這樣可以避免某些類型重復定義的錯誤。
6、讓C代碼帶上面向對象的思想
不像C++這樣即面向過程又面向對象的語言,更不像Java、C#這樣完全面向對象的語言,C語言僅僅是面向
過程的,但是我們可以為C語言設計的項目插上面向對象的翅膀。
1、面向對象的命名
如我們在開發一個GUI庫,設計到GUI的初始化、加載字體、設置背景色、設置前景色等等操作,
如果是沒有代碼面向對象的命名,可以這樣:
Init、LoadFont、SetBgColor、SetFgColor
如果是帶上面向對象的命名,則可以這樣:
Gui_init、Gui_LoadFont、Gui_SetBgColor、Gui_SetFgColor
這樣命名有個很好的好處,便于程序員記憶,我們在想到需要用到GUI的接口時,只需要打上Gui,
好的集成開發環境就能快速提示所有的GUI庫函數,這無論對新接觸GUI這個庫,還是熟悉GUI庫的
老牛們大大的提高效率。
2、為僅在一個模塊內使用的全局變量加上static
配合【1】的命名、Gui_Init、Gui_LoadFont、Gui_SetBgColor、Gui_SetFgColor等函數操作這個模塊內的全局變量,
這個時候,GUI猶如一個類,模塊內的全局變量猶如C++、Java、C#等面向對象語言的GUI類的成員變量,Gui_Init等GUI庫函數
猶如GUI類的成員函數。
3、設計純潔的接口
如代碼:
void func(int *iResult)
{
*iResult = g_Val*10000 + 1000; // 使用了全局變量參數復雜運行的代碼
}
以上的代碼就需要以來g_Val這個全局變量,這種寫法已經污染了這個接口
如果是純潔的接口,應當
void func(int *iResult, const int iVal)
{
*iResult = iVal*10000 + 1000;
}
調用時:
int iResult,g_val;
func(&iResult, g_Val);
這樣這個函數就不至于嚴重以來全局變量,你可以傳全局變量進來,也可以傳局部變量進來,
純潔的接口并不關心這個。
7、命名規范
1、全局變量加前綴g_,如定義一個全局變量int g_iVal;
2、static變量加前綴s_,如定義一個模塊全局變量static int s_iVal;
3、結構體變量加前綴st_,如COMM_PARA是一個已經定義好的結構體,則COMM_PARA stCommPara;
4、枚舉變量加前綴e,如ENUM_SEX是一個已經定義好的枚舉,則ENUM_SEX eSex;
5、int類型變量加前綴i,如int iRet;
6、unsinged int類型加前綴ui,如unsigned int uiRetCode;
7、float類型變量加前綴f,如float fVal;
其實有了double類型,可以不用float,就盡量使用double。
8、unsinged float類型變量加前綴uf,如unsinged float ufVal;
9、double類型變量加前綴d,如double dVal;
10、unsinged double類型變量加前綴ud,如unsinged double udVal;
11、short int類型變量加前綴si,如short siVal;
12、unsinged short類型變量加前綴usi,如unsinged short usiVal;
13、如果定義一個bool類型的變量加前綴b,如int bFlag;char bFlag;
14、如果定義的是一個字符串類型char[],
如果字符串是需要以0結束符的字符串,則char szCountry[11+1];
這種情況下的字符數組的大小寫法是字符個數+1的
如果字符串不需要以0結束符的,則char sCountry[11];
15、如果定義的是一個字符串類型char *,
如果字符串是需要以0結束符的字符串,則char pszCountry[11+1];
這種情況下的字符數組的大小寫法是字符個數+1的
如果字符串不需要以0結束符的,則char psCountry[11];
16、如果是一個指針類型,
如果指針變量是通過malloc動態獲取內存的,則int * piValPtx;
Ptx代表這個變量是需要動態釋放內存
如果指針變來那個不是動態獲取內存的,則int piValPtr;
如果帶上了Ptr或者Ptx的后綴,則前綴的p可省略
17、項目的命名
在公司內唯一
18、文件的命名
如果某些文件是項目唯一使用的,文件名稱加上“項目名稱簡寫”+ “_“作為前綴
19、接口函數命名
如果寫的是庫,則庫接口則應該是庫名稱加上“項目名稱簡寫”+ “_“作為前綴
20、防止頭文件重復使用宏命名
項目名稱簡寫”+ “_“ + “文件名" + “_“ + “H"新聞熱點
疑難解答