溝通是雙向的,擁抱變化不是一昧地接受客戶要求

同人在《Time-Boxing 於軟體反覆演進的必要性》之中所說的情形,我也有碰過。

有時,客戶提出的需求變化其實並不是個好方法。在這種時候,我會示範或舉個例子,告訴客戶一個更好的方式。如果有示範品的話,客戶通常會很快接受。接著,我會告訴客戶這些實作方式是不是現有的。如果沒有,大約需要多少工時,並評估其重要性及時程。換言之,要評估這樣的需求變化要不要立即處理。就算客戶不能當天看到修正結果,也要在溝通的過程中,讓客戶了解前因後果以及處理時程。畢竟,「溝通」是雙向的,而不是盲目地接受客戶的要求。開發團隊單純地接收客戶指令,算不上溝通。

當然,這些內容在敏捷方法的書中都有提到,我就不再多說。我接著要提我個人的所見所聞,是上述內容在國內實行時的困境。

foreach 時使用 reference 的陷阱

前幾天在重構一段 PHP 程式碼時,不小心踩到 foreach 使用「參照(reference)」的陷阱。上網查了一下,似乎踩到的人還不少。我想了一下,把原因換成另一段程式碼形式說明,再說明解法。基本上,這是個 trick ,而不是 bug 。

反覆週期的長短只是結果,關鍵是使用者參與程度

同人針對我的《敏捷方法實務研討會會後筆記3》寫了篇評論。確實,週期的長短並不是關鍵。因為以「日」為單位的反覆週期,是敏捷方法重視使用者參與,將使用者拉進開發工作之後,自然而然就會發生的必然結果。敏捷方法則透過密集的溝通行為,一舉將反覆式開發的週期縮短到以「工作天」為單位 (敏捷方法實務研討會會後筆記3)。

PHPUnit3 和 Makefile

在測試驅動開發的方式下,一個源碼 .php 搭一個測試案例碼 Test.php 的情形愈來愈常見了。而隨著軟體規模的擴大,源碼及對應的測試碼數量也愈來愈多。如果每次 commit 前都要一個不漏地跑完每個單元測試,未免太浪費時間了。畢竟沒有修改過的源碼,並不需要再跑一次單元測試。這時候就要藉助自動建置工具來幫我們簡化測試動作和時間。

本文利用 Make 這個傳統的軟體建置工具,提供一個簡單的 Makefile ,用於自動測試專案中相關項目。搭配的單元測試工具是 PHPUnit3

公司又被罰款了,這次的罰則是化妝品衛生管理條例

在下任職的公司(百貨流通零售業),這星期被政府罰款了。這次的罰則是「化妝品衛生管理條例」。理由是行銷人員製作的文宣中,含有必須取得許可字號才能刊登的內容。上次被罰款的罰則是「健康食品管理法」,再上上次的罰則是「環境用藥管理法」。這年頭做生意還真不容易啊,特別是什麼都賣的百貨流通零售業。

幾個月前,我畢業的企管研究所寄了份問卷給歷屆校友,其中一項就在問研究所應該開設哪些實務性的選修課程。我那時毫不遲疑,第一格就填「企業法律」,那實是有感而發。在下服務的公司,產品項有上萬筆,隨時在通路上流通的也有三千多項,還會開發自有品牌。商品內容包羅萬象,一個不小心,其中一項就觸法了,而且還是很少人聽過的法令。企業法律的內容,不再只有稅務、會計、商標、營業秘密。連環保署、衛生署都來插一腳。企業人,包括員工在內,實在需要多多充實法律知識。

舊程式碼中的 void* 轉型

前一陣子,為了說明《程式語言中的介面》,我把大約八、九年前寫的 C 語言程式碼翻了出來。編譯的時候出現錯誤訊息,顯示我用了不被允許的轉型動作,即 (void*)。雖然心裡嘀咕了一下,不過還是很快地改成完整的轉型語法 (也更冗長),將之用於文章範例。

這幾天抽空檢視了一下那些舊程式碼,才發現不是程式碼的問題,而是我用錯編譯器了。我的編輯器 PSPad 設定 C/C++ 文件呼叫的編譯器是 g++ (C++ compiler) ,而不是 gcc (C compiler)。而 C++ 不允許將 void* 轉型為其他型態指標。這點與 C 不同。我又測了一下舊有程式碼的 C/C++ 規範相容性。

C++ Template 筆記

C++ 的 Template 是種將資料型態參數化的功能。將資料型態資訊自程式碼中抽離,代之以簡化的符號 (T, T1, T2, ...)。再由編譯器透過類似巨集代換的方式,根據樣板內容產生實際的程式碼。

  • Function Template (函數樣板)
  • Class Template (類別樣板)。含部份特殊化。

非資訊科班的程序員?

hoamon 說他還沒看過非資訊科系出身的傑出程式設計師 (到底誰會寫程式?)。雖說他也覺得應該有這種人。其實在國內,這種人應該不少,我就碰過幾個。全世界最有名的非資訊科系出身的傑出程式設計師,應該是Microsoft 的 Bill Gates 吧 (在他還是個 BASIC 開發者時)。他是哈佛大學法學系肆業。

我不敢說自己是傑出程式設計師,只說是個程序員、 programmer 。但有一點很重要,我不是資訊科系出身的。我大學唸國際貿易,研究所修企業管理,是一個血統純正的商學科班生。至於我的編程能力,我想剛好及格。應該沒有人認為我需要當掉重修 (也沒啥可當,因為我沒修過這類學分 XD)。

我一向不認為性別、科系,與程式設計能力有關。因為程式設計是種容易接觸與實證的知識。只要有一顆能思考的頭腦,加上一隻筆和一張紙,就可以寫程式。只要有台電腦,就可以實證。日起有功,不必妄自菲薄。

喔,應該還要加上一雙手。我想到日前看了電影「荒野大飆客(Wild Hogs)」中,杜德利 被人綁起時的劇情。對方要脅說不付錢,就打斷腳。結果杜德利對朋友說「不! 不要付錢,我是電腦工程師,不需要腳!」 對方一聽,於是改口說不付錢就打斷手。杜德利一聽馬上大叫「快! 快付錢!」 全場笑翻 XD

只要觀念不改,CMMI就是做表面文章,搞假的

說到 CMMI ,可是現在國內軟體公司之間的熱門話題。好像沒通過 CMMI 認證,接洽案子時就矮人家一截。我之前也待過一間通過 CMMI level 2 的軟體公司。可惜的是,我完全看不出取得 CMMI 認證的公司,他們的軟體開發品質以及程序員工作效率與以往有何不同 。雖然如此,現在台灣官方 (經濟部、資策會等) 就是相信 CMMI 那一套。我並不是說 CMMI 沒用,只是在缺乏穩固基礎的條件下, CMMI 認證只是表面文章。

「穩固基礎」是指什麼? 就是夠多的 senior programmer 、正確的程式設計觀念等等基本功夫。舉例來說,如果有一間軟體公司幾乎所有程序員都有7年以上的資深實務經驗,那不論是 CMMI, CMMV 還是 CMMX 認證 (喔,當然沒有 CMMV, CMMX ,我只是在玩羅馬數字遊戲),他們推起來都一定順暢無比。因為他們的觀念及實務作法早就到位了,就差套個標準流程的形式而已。

程式語言中的介面,在個體之間協議互動行為的多種形式

racklin 說: 我的重點還是只放在 "關注類別是否有實作方法" 也就是 "介面" 的這個概念, 因為原文是討論這個議題. 嗯,我大概是跳太快了。我清楚 interface 是什麼。所以我的回應是在說明「個體之間如何協議互動行為」亦即「軟體合約」的形式。

以C/C++為例,在早期,程序員學了 C++ 可是還是要寫 C 程式的時代,我們會自己用 C 語言實作類別繼承、動態連結等觀念。但我們用的是 C compiler 而非 C++ compiler ,所以很多事我們必須自己處理。其中一點就是個體行為的協議。方法一、在函數文件上說明傳入的個體需擁有哪些行為,我在函數中會檢查此個體是否擁有此行為(函數指標是否為給定了)。方法二、限定一個 struct (只有純函數指標宣告),呼叫者要自己填一張函數指標表傳入,這其實就是 interface 的概念。

Block and Proc

Ruby 可以將程式碼參數化,Ruby 稱被參數化的程式碼為 block 。Ruby 語法以 {||} 表示一個 block ,其中的 || 為參數列宣告,若無參數則可省略。

Ruby 的 Proc 類似 ECMAScript 的 Function。在 ECMAScript 中使用關鍵字 function 即可配置一個 Function 實例。 Ruby 則使用 Kernel::procKernel::lambda 方法 (兩者相同) 或是直接建構一個 Proc 實例(Proc.new),需提供一個 block 作為引數。

Ruby: proc { |arguments| codes }
ECMAScript: function(arguments) { codes }

Stack - Example for Operators of Array Overload

實作一個 Stack 。具備下列特性:

  1. 後進先出。
  2. 順序走訪時,同樣按後進先出原則走訪。亦即由後往前走訪。
  3. 可用索引運算子[]窺探 Stack 的內容。
  4. 不允許用索引運算子改變 Stack 的內容。

本文之示範直接實作 Iterator, ArrayAccess, Countable 三個介面,而不繼承 ArrayIterator 等類別。ArrayIterator 類具有 sort() 等方法,但我並不打算對 Stack 進行排序,故我不繼承。若我繼承 ArrayIterator ,則我必須覆寫 sort 等方法,無此必要。

SPL~Use ArrayObject and ArrayIterator to Overload Operators of Array

If you want to design a class and make it's behavior as an array, you may extend ArrayObject. Also this new class probably need to use an instance of class which extends ArrayIterator (Note: ArrayIterator is a class, not an interface).

This feature requires PHP 5.

Darker Than Black 11~12話 -「門」裡的世界

Darker Than Black 第11-12話「壁の中、なくしたものを取り戻すとき…」,著實玩了一把物理學的非常識觀念。到底在「門」內能不能取回失去的東西?或者說,「門」裡的世界究竟是個什麼世界?

在科學哲學中,自然科學所研究的世界,是客觀世界,或者稱實在界。另一方面,也有一派認識論者主張感覺世界。「存在就是被知覺」即此派的代表性主張。 Karl Popper 在《客觀知識》一書中尚且主張知識存在於另一世界,亦稱第三世界。這第三世界就暫且不談了。 Darker Than Black 中,門外的世界是我們所熟知的客觀世界;門內的世界,則是與客觀世界之物理規律不同的世界,到處充滿了客觀世界之常識所不能理解的現象。

根據 Darker Than Black 第11話 Nick 博士的說法,在門內,只要你相信心中所想,那麼你就能看到你所想的事物。亦即,能為心智所知覺者就能存在。似乎,門裡的世界就是感覺的世界。再者,這又可透過量子物理學說明。門裡的世界,所有量子狀態皆呈疊合態。當觀察者觀測時,觀測資訊就會介入使世界的疊合態塌縮。如果觀察者相信心中想法,亦即思考的量子資訊狀態非常穩固,那麼外界的量子將巧合地朝觀察者心智資訊所設定的狀態塌縮。觀察者所想的資訊就會被觀察者所知覺,亦即存在。

在門內, Nick 博士和小李都相信星空,於是兩人都看到了。Nick 又相信他可以和妹妹一起實現小時候搭乘太空梭進入太空的想法。於是 Nick 的狀態變成小孩的狀態,奔向小時候想像的太空梭和妹妹一起飛向太空。還回頭謝謝同時介入場中的小李也相信他,使得 Nick 所設想的狀態能夠穩固、能存在。至於小李,也許他還在迷惘。但可確定的是,銀的觀測行為使得他的狀態按銀所設想的狀態確立,因而繼續保持著與客觀世界的聯繫。

最後嘛,要唸唸小李。銀幫了你那麼多事,還那麼關心你,你竟然只送了她一顆糖。嘛,至少小李不忘說聲ありがとうな。預告中,小時候的銀真活潑啊。三無少女真正的萌點,就是在她笑的那一瞬間。等好久了!

為什麼還不升級PHP5

jaceju 於《PHP5 將滿 4 歲》一文中說了一些他碰到的原因。

我的經驗,應用軟體的問題還好,大部份 PHP4 的軟體在 PHP5 的環境上一樣可以跑,只是語法 notice 多了點。再者,在 PHP4 的軟體中混雜 PHP5 的語法也不會影嚮程式運作。

敏捷方法實務研討會會後筆記5 - 資料結構與虛擬碼

資料結構與演算法

喔,各位沒看錯,陳教授確實把資料結構與演算法列入他規劃的敏捷方法 (myAgile) 條目中。我看到這一點是非常 Orz

陳教授有提到理由,台灣的程式設計教育重視計算與解題,而不重視思考與建構。所以程序員常常學了資料結構與演算法之後,卻不會運用在實際的編程工作上。故此他特別把這一點列入 myAgile 條目中。

如何區分動態語言和靜態語言

雖然我們總是說著動態語言(dynamic language)、靜態語言(static language),但區分方式並不是語法,而是運行環境。

如果程式影像在載入前便確立並儲存,那麼是靜態語言[If the image of program which including op code and data is static in disk before loaded, we call it 'static language'.]。這句話對學過作業系統概論或組合語言的人比較容易理解。因為在組合語言中,要求程序員設置 code 節區, data 節區等內容載入記憶體的位置。所以我們很容易聯想記憶體中的程式影像儲存在檔案系統中的情形。與之相對的是,若程式影像在載入後才建立,則是動態語言。