??? 下面是昨天和同事討論一個函數了的實現時的對話。(為了簡化,減去了其中我由于‘著急上火’而導致‘高音’部分的言語...)?
??
??? C(同事):現在需要由你提供一個Sample()函數。
??? J(我):OK,功能是否是為了完成必要的數據采集工作?
??? C: 是的,最終數據要放到文件中。?
??? J: 放到文件中?那是當然。但你的意思是整個Sample()都要我這邊的代碼實現嗎?
??? C: 當然,你應該會寫文件吧??
??? J: 等等,不是會不會寫的問題,而是文件要我來寫嗎?現在的分工上是否是我負責數據處理,你完成流程調度?
??? C: 有什么數據、流程之分嗎,我們寫的是一個程序啊。如果你非要區分一下,那應該是這樣的。
??? J: 那你看文件存儲和數據處理有什么關系嗎?
??? C: 數據最終不是要放到文件中嗎?你數據獲取后,保存到文件中,這有什么不對嗎?
??? J: 你沒有發現有什么沒考慮的問題嗎?像是要保存的文件名稱我這邊怎么知道?具體數據該如何存儲?
??? C: 文件名稱在調用是我會傳給你的,需要什么都會傳給你的了;至于存儲,按照現在的規范,字符串格式!
??? J: 都傳過來?你確信以后不會被改成二進制方式存儲嗎?好吧,先說說你想Sample()該如何實現吧?
??? C: 不用考慮二進制了,再說如果改了,我們到時跟著改就是了。好,你看,我想應該這樣做,先Open個文件,然后獲取數據的結果,變成字符串保存到文件中,然后Cose。很清晰的過程,是吧??
????int?Sample(
)

????
{
????????OpenFile();
????????
????????str?=?GetResult(
);
????????Save(str);
????????
????????CloseFile();????????
????}??? J: OK, 你看這些代碼跟我現在實現的數據部分有多少關系?而且我們的‘數據’的Result并不都是string類型,而且已經為不同的Result都定義了相應類型了,難道這里你要GetResult都轉換為string嗎?要是那天存儲改為二進制了,我們來改GetResult()嗎?而且這個Save()接口參數也要改,是吧?
??? C: 如果需要改,我們跟著改就是了,這不是問題。
??? J: 是的,改不是問題,但改多改少,和改動的影響的大小應該是問題吧?最主要的一個問題是,這樣的過程將數據和存儲緊緊耦合在一起了。這種做法對于分解工作很不利的。
??? C: 我并沒有覺得有什么不妥,你打算如何做?
??? J: 首選我們看一下,你需要的是File,Result(數據)和Save三個部分代碼,是吧?我們能看出Result是數據部分的操作,而File,Save兩部分是流程上的操作,把這樣的代碼都加到‘數據’部分去,是不是有些亂?要不把GetResult()加到‘流程’部分?
??? J: 其次,簡單地舉個列子說,如果有需求要我們獲得Result后,不保存到文件,而只是顯示在屏幕上,那么對于這種需要,我們要再寫個GetResult()函數吧?
??? J: 你看,如果涉及Sample()的修改,我們需要修改的地方涉及太多功能塊了。所以根據功能的不同,分離這些函數是必要的。Sample()不應該能過作為一個‘原子’操作,提供出去,應該把它分解開。 在分解功能時,或者設計函數時,應該是功能該是什么樣子的,就按照什么樣子去做,做自己能做的和該做的,而不是為了問了迎合另一個功能的需求而改變自己;功能間的連接我們可以通過傳遞結果或者添加‘適配器’等等方法。
????int?Sample(
)

????
{
????????Result?=?GetResult(
);
????????
????????ResultProc(Result);????
????}
????
????int?ResultProc(filename,?result)

????
{
????????str?=?ResultToStr(result);
????????OpenFile(filename);
????????Save(str);
????????CloseFile();
????}??? J: 因此,look,Sample()不是我們需要的,我們需要的是GetResult()和ResuoltToStr(), 而Sample()只是對它們的再封裝而已。如果發生前面說到的更改需求,GetResult()就不用動了。所以,數據處理是我這邊要做的,而寫文件。。。。是吧?
<----- 吐血的分割線 ---->
?
??? C: 寫到了再說。。。