不想學習的矛盾
技術日新月異,想要趕快趕上並不是不能理解
然而,很多人只覺得,使用最新最潮的套件,就是跟上時代
使用最新最潮的做事邏輯,就是跟上潮流
有空再開一篇scrum陰謀論,以及不要怕調整框架來談這兩件事情,但因為跟這篇沒什麼關係,姑且先只點一下
現在很多所謂最新最潮的名詞,都是
“我不想XXX,所以YYY”
“簡潔的XXX”
話要說在前面,這個思維並沒有錯
錯的是中毒的人,以及不願意去思考差別的人
這些名詞,不外乎都是
標新立異
你沒有看錯,這還是比較保守的說法
為了讓自己出名,也確實為了改善一點問題讓自己更方便
設計了只屬於自己的語言和做法,要求大家配合,這就是現在的所謂框架和套件
然而,這些並不是沒有缺點的,也不是沒有限制的
就連最強大的jquery,也是有相當限制
現在的狀況比幾年前的狀況還嚴重一點
很多人只要脫離框架就束手無策,很多人沒有套件就寸步難行
結果他們變成
拼命鼓吹套件的優點,並且將自己大部分時間
拿來解決套件造成的問題,拿來繞過套件的限制,拿來溝通放棄用了套件就做不到的事情
的死人
這是中毒,換個說法就是
套件意圖讓你放棄學習原本的事情,想讓你改為學習套件
現在的套件亂象也是一樣的
有些東西用原生的寫法完全是比較快的狀況
然而一拿出來,第一句就是
“還行啦,但怎麼不試著用XX套件來寫呢?”
中文有一句成語叫做
削足適履
就是在說這樣的事情
很多人沒有鞋子就拒絕走路,就是現在的現實狀況
當然,在很粗糙的地面,有鞋子,且有正確的鞋子是好事
然而,鞋子需要因為每個個人量身定做與設計
而且最重要的是
在室內根本沒有穿鞋子的必要
在泳池也根本不需要穿運動鞋
最根本的原因
是鞋子中毒者根本沒有辦法考慮不穿鞋的狀況
以至於他們沒有辦法考慮穿與不穿的差別
“我覺得光著腳好像也還行啦,但怎麼不試試穿著運動鞋在泳池旁走路呢?”
GtkScrollbar Warning
這個警告訊息,通常是Gtk overlay-scrollbar有被動過導致的
訊息類似於:
(gedit:8544): Gtk-WARNING **: GtkScrolledWindow 0x1e526c0 is mapped but visible child GtkScrollbar 0x1e5a760 is not mapped
直接重新安裝就能排除不斷出現的大量錯誤
sudo apt-get --reinstall install overlay-scrollbar
ubuntu 14.04 chrome安裝問題
64bit官方下載的預設包是有問題的,會載到i386
要安裝成功的話,要載amd64的版本
而且中間會有相依套件安裝錯誤的問題,需要額外安裝修正
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb
sudo apt-get -f install
當然如果網頁下載直接使用就能成功大概不會有這個問題
ubuntu note - 版本,虛擬機,JRE相關
浪費一堆時間,把紀錄整理一下,免得之後要再浪費一次
1.ubuntu 14.04.1 剛安裝完字型有問題,有插入光碟機(至少用VM)Error的問題
2.Virtual Box 4.1的Guest Additional 插入14.04.3安裝會噴錯
1和2基本上隨著版本已經有修正
只要用ubuntu14.04.3 + virtualbox4.3 就不會有問題
3.JRE的字型issue導致的中文問題
(通常會在sudo gedit /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/fontconfig.properties)
看一堆google到的中文顯示設定修正,亂抄的居多,導致解法怪異
jre lib的設定檔裡面
x11預設的中文部分是/usr/share/fonts/truetype/wqy
然而這玩意不是預設安裝
因此解法很明顯了:
sudo apt-get install ttf-wqy-microhei ttf-wqy-zenhei
動sequense順序不是不對,但你也得把東西裝完才找的到
Useful Unit Test
先不說要交出去的
這篇探討的是"怎麼用Unit Test"幫到自己
因此什麼理論什麼合理性,什麼覆蓋率請直接丟掉,至少對成品沒有直接幫助
以下以phpunit vs php開發為基準,java可能另有狀況,請勿直接當同一種
<請點選連結查看全文>
一分鐘懂MockObject
function 外部Class A 裡面有function FA()可以拿到對應值
function 外部Class B 裡面有function FB()可以拿到對應值
我寫的class:
class Example(){
function getA(){
return new A->FA();
}
function getB(){
return new B->FB();
}
function mixData(){
$dataA = getA();
$dataB = getB();
return $dataA + $dataB
}
}
好了,假設這些ClassA ClassB是外部函數,也就是其他人開發的
那我們該怎測試才能確保自己的unit有正常運作呢?
class test_Example(){
funciton test_mixData(){
$mock = $this->getMock('Example');
$mock->method('getA')->willReturn('1');
$mock->method('getB')->willReturn('2');
$this->assertEquals(3, $mock->mixData());
}
}
一分鐘了,應該看懂在寫什麼了吧
看懂以後再看下面
在這樣的具體個案中,如果要確認Unit有沒有"正常運作"
最該care的是取得資料以後, "+ 有沒有執行,有沒有return"
而不該是"AB資料取得的值是否正確"
因此"對這個unit而言",我們不應該做類似以下事情:
"FA可能沒取到值,我們應該assert確認一下"
"FA是否是字串根本不能相加,我們要確定一下是否為浮點數"
這裡要鄭重說明一下,我們的目的終究是要確認這個unit有沒有正常運作
所以,如果你做了外來資料的過度判斷,而到時候又真的出錯了自己不在現場
如果是外來資料有問題,結果unit test檢測被其他人看到,恩經判斷期望結果不符
非常有可能會以為這是你的程式出了問題,結果查好久才查到原來根本是外部程式導致
這會造成大家的麻煩,請務必別做這樣的事情
再來,為什麼這種函數都很少去用各種condition來assert結果
因為:出問題你很難判斷是外在資料錯誤,還是你計算錯(原因可以無限上綱,不要懷疑)[註1]
與其花費大量時間寫各種判斷式來嘗試抓冰山一角
更好的方式就是不要在unit test幹這種事情(不是不測,而是別在這階段做)
(假使要做這件事情,除非程式本身就帶Exception,那我們可以做另一個測試時,帶入不合法的值來確認是否真的會觸發Exception)
Mock Object的作用就是在此,我們應該準確地確認這個unit是否真的有運作
不應該被其他外在函數的特例狀況影響到
這也是單元測試好用的地方,我們即使程式還沒完成或上線前接不到資料
也可以假設某函數資料正確來直接測試,這是Unit Test Framework最強的地方
這樣也不需要在主程式改一些測試專用Code,然後可能上線前還忘記砍掉之類
老話一句,如果想用unit test,
請絕對不要迎合unit test去多做一堆沒用判斷,然後說什麼這樣可能很難測試,我要為了unit test方便而忍痛改變現有架構之類的蠢事
請去用他對你來說真正受益,可以減少程式錯誤,增進開發效率的地方,這樣才能發揮價值
註1:
因為用少數結果絕對無法檢驗程式邏輯有沒有錯
要舉一些極端例子的話,
1.如果你assert 3應該回傳5,我程式如果為了測試,最後一行真的是寫return 5,assert下去絕對有過,但這樣的結果明顯只是鬼打牆(而且這個實際真的有人發生,因為為了寫unit test最後的return還真的忘了拿掉)
2.如果你做了兩個,assert 3應該回傳5 assert 4應該回傳 6 是否裡面剛好程式搞砸了,最後變成 input+2 ,結果assert還是有過
3.然後開始上綱,你的unit判斷式寫太複雜其實有藏了幾個BUG,結果要測目標程式測不到
PHP的個人整合應用分享
感覺抱怨文發有點多,發一篇來洗掉(雖然沒什麼意義)
以下請勿沒看狀況照搬,也請自己先弄懂並確認運作流程
假設有狀況需要執行A方針的流程1和流程2,但其他狀況需要執行B方針的流程1和C方針的流程2
神奇的PHP可以把他整理得很乾淨
class A{
function magic(){
doSomethingA;
}
function magic2(){
doSomethingB;
}
}
class B{
function magic(){
doSomethingC;
}
}
class C{
function magic2(){
doSomethingD;
}
}
$dynamicClass = new A();
$dynamicClass->magic();
$dynamicClass->magic2();
} else {
$dynamicClass = new B();
$dynamicClass->magic();
$dynamicClass2 = new C();
$dynamicClass2->magic2();
}
但是其實可以整理成這樣
$dynamicClass = new A();
$dynamicClass2 = $dynamicClass;
} else {
$dynamicClass = new B();
$dynamicClass2 = new C();
}
$dynamicClass->magic();
$dynamicClass2->magic2();
好處的話,當流程不只兩個,而是十幾二十個的時候,差在哪顯而易見
但是這也考驗著,有沒有辦法整合自己架構,釐清整體流程
因為在這裡雖然很明確的寫出magic和magic2作為方便理解,在現實狀況卻不一定是能很輕鬆分出來的
請把OOP的精神發揚光大,而不是只把他的封裝幹徹底
死迴圈,一堆人有這種本末倒置的觀念
寫到最後,通常會用這種理由來解釋自己的程式比別人品質更高
"你看,我這邊判斷得多麼精準,沒用到的就是不會執行到,多麼完美"
"你看,如果你想加額外的處理項目,直接在這底下開函數就可以了"
"你看,你完全不用管我這邊怎運作的,只要使用就行了,該出的例外訊息都會丟出來"
我要反問了
"現在不是額外的處理項目了,我們資料庫要換,處理方法要換,你能馬上改出來嗎?"
"現在合作架構有點異動,很多欄位(數量)都改變了哦"
最重要的
"現在XX功能出問題了,你打算怎麼讓別人知道該怎去追這麼BUG"
"你要怎麼讓別人知道你程式運作的方式以及調整架構的方式"
然後死盲點
"你真的以為用這一大堆判斷式確認沒有額外函數執行效率會比較高嗎?"
合作開發這種事情,一個人是幹不起來的
要讀別人的程式碼是必然,因為要合作,在來有BUG,即使你說你負責處理,退個一萬步總得讓對方知道怎把這條BUG報給你吧
有些人會問我,怎麼你說你的程式是OOP的架構,GET/SET怎這麼少,函數好像也沒開很多
我倒要反問一下這些東西跟OOP到底有啥關係了
大家常常看到的 Vehicle new Car new Bike覺得很完美對不對?
可是你有沒有想過那只是大準則,你真的一new就天下太平了嗎?,別妄想了
程式,最基本最重要的東西就叫做"流程(Step)"
所有東西都依賴於他,即便你是個OOP架構,你最終還是要給我個"使用順序"來完成事情
當你確定流程以後,才有資格說我按照使用狀況去封裝必要的程式碼
為什麼?因為這樣做才能讓合作對象最容易了解你在做什麼
怎樣算是一個成功的OOP,就看需求有變動(注意不是項目,多個欄位你就顯示不出來,請不要來亂)程式能跟著變化到什麼程度
最基本的,處理流程,順序,不同資料銜接的方式,在怎麼說都是需要靈活應變的
總不能說我的資料只能完美的給A情況使用,換成B,阿不好意思我要大幅度改寫...
你再怎麼解釋你程式高效能,最終就是被貼一個標籤,應用方式太狹隘,思考太侷限
那怎樣算是一個失敗的OOP,近期看到一個例子,來分享一下
這個OOP相當省記憶體,因為只要沒有做到的他就絕對不會初始化,這點已資源考量方面是相當完善的
然而,他是怎麼運行的呢?
當我new 一個A類別,我就會執行一些B函數,但執行到一半為了處理事情我要用執行階段的部分內容呼叫C函數處理,然後執行完後我要直接拿這個結果呼叫D函數...
(後來想想,應該有人會看不懂,那白話一點,這個狀況就是:
你執行A類別,B函數以後,剩下的CDEFGHIJKL你除非去追原始CODE不然都不知道她怎幫你處理資料的)
問題來了:
這些所謂的function都是丟在該類別裡面,當有人問你
"請跟我說一下這程式處理資料的流程,我覺得好像有個地方執行怪怪的"
下場,很簡單,你要從頭到尾解釋一次程式給他聽,而且恐怕第一次解釋還聽不懂
因為function不管你怎麼整理,為了高效化就是有許多各自的細緻處理,最終的下場就是
"執行順序消失了"
這是相當嚴重的事實,我有正常跑我的類別,可是執行順序我都需要反查一下才知道跑到哪了
先不考慮過多判斷是否早已掩蓋掉原本直接執行的效率
剛才是不是有提一件事情
"現在,我的處理資料流程要變動了哦,稍微變動個執行流程,因為中間我們要加個驗證了"
然後好死不死,原作者不在現場
快,告訴我,哪個傢伙趕快神解一下這個類別到底該加在哪個位置
物件導向,是將事情正確的拆開封裝,以"方便溝通",與"方便維護",和"方便調整"
但這個模式同時隱含著你必須處理好運作流程,否則該封裝沒有意義
我一直不懂為什麼有些人會用效率去解釋他的OOP做得多好
你們TMD為什麼沒想過原本直接下一條指令就能搞定的東西,被你包了這麼多層
怎麼看都不可能比原本的效率還好OK? 你沒把最重要的流程,架構,溝通做好
還反過來說你看我這樣封裝,沒執行到的都被我精確排除了
抱歉,我只說一句,你正在拿最沒有效率的手段說你正在提高效率
請絕對不要做這種搞笑事情
以此觀點來說,沒錯,我也要講另一件事情
那些看起來很強的perfect coding,我就真的當它是都市傳說
因為那常常是特定狀況下才有辦法這樣幹,又或者是自身已經對資料架構摸到熟到不能再熟,且資料架構也沒啥大問題的狀況下,才有可能完美呈現的CODE
很抱歉這個需求我就是要動到5個資料表,你要我用處理單一資料表的水準把程式跑出來
這就是不可能的事情,請不要對著這支程式說
"你看人家對(單一)資料表都處理的那麼完美,怎麼你的處理方式有點雜亂"
當你正在想這件事情的時候,請自己寫一下真正會變怎樣
如果全部都能照你所想的正確呈現出來,那你真的可以去讓對方信服
反之,雖然處理漂亮了但判斷變超複雜,STEP變超複雜,你TMD還是來亂的
因為根本就不可能這樣改寫
有些理論只存在理想,如果你覺得他可以實際用出來
請拿實際能辦到且自己正在應用的事情來說服別人(不是拿其他人的程式碼哦,這有天地般的巨大差距),而非只是宣傳一下好像很強的理論
就以為自己也辦的到,且這很完美,怎麼別人都不聽你的
理想與現實,一直都是兩回事,身為一個程式設計師,請務必先釐清這件事實
合作寫程式,開發階段的基本概念
1.流程麻煩清楚
2.讓別人一看就知道你在幹什麼
3.初期程式請勿封裝過頭
4.初期程式請勿封裝過頭
5.初期程式請勿封裝過頭
有件事情說了三次,為什麼,很重要
開發階段為什麼叫開發階段,就是因為我們可能還會按照需求調整
可能還會中途插入一些預想外的資料需要處理,也可能其中有一半要全部打掉因為不用了
你把程式全部像OOP概念一樣封起來,就程式精神沒錯,但就合作開發角度你TMD根本在搗亂
首先這種東西沒有辦法很快讀懂,浪費所有人初期確認你程式運行的方式,撰寫架構等等
再來,如果真的慘劇發生,"這一大半現在說不需要了,我們另一半資料應該用另一個資料庫,處理方法也要變更"
封裝過頭的下場就是你會抱怨怎麼這樣我超不方便改我程式的
因為近乎,不對,是整個要重寫
其次,遇到封裝無法處理(例如需要多考慮一個參數),結果又要說是程式限制導致,結果其他人要配合你解決嗎?
不可能的,你還是得大費周章調整自己已經封裝好的程式,因為這是你的問題
且還要額外多測試很多東西,因為你不能保證我只調整這邊,其他一律不會出錯
你當然也是可以不測試,但往後如果出錯就是被裱到更慘,因為通常已經是很多人開始使用,然後你也說這程式沒有問題的狀況
最後,最現實的
"我現在東西參照到你的,東西也完全符合格式,但就是出錯了"
結果一查,一開始沒有全面考量就封起來,結果要改掉這個例外狀況,我還是要拆掉重新寫在重新封裝
你覺得這樣回應有用嗎?
"這是這個函數的限制,你要呼叫這個函數,要自己避免我程式不支援的地方"
拜託,不用想就知道會引起公憤的行為,請三思而後行
補充一個更慘的事情,那就是因為別人看你的程式看不太懂,以為你封起來的東西並不支援需求,所以又另外寫一個,結果到時候還要解釋說
"如果你當初有多花幾小時研讀我程式的話,就會發現我寫的東西已經滿足你需求了,所以你這些並不需要寫"
即使你寫的東西再完美,都會讓很多人不爽,因為你寫的程式很難溝通
然而,OOP概念沒用嗎?封裝沒用嗎?考慮最佳效率沒用嗎?
錯,當然有用,非常有用
但是這種東西有用是,大家合作的部分都已經確定,整體架構趨於穩定,需求也穩定近期不會改版,或基本要封測上線
那我們就可以考慮哪邊可以開始整合,優化,提高效率
這時候當你提出,"我覺得這地方要進一步整合封裝起來,可以提高效率"
那,大家也可以快速地確認有沒有影響到自己的部分,有也可以馬上提出來
再者,你這時間點想幹這種事情,除非提案荒唐,否則獲得雙手贊成的機率應該非常高
因為你是針對穩定下來的東西想進一步優化他,沒有反對的理由
因為你接下來要封裝的東西,別人同樣呼叫你寫的程式,方法必定更簡單,或者根本沒有必要改呼叫方法
總而言之
重構,整合,封裝,絕非在最早的開發階段應該做到徹底完美的事情
因為你做了就等同在找合作夥伴麻煩,以及找自己麻煩
請先有初版程式,讓大家看懂你整體流程到底在幹什麼(當然還是要整理,只是別過頭,詳見文尾說明)
開發階段是討論程式架構與合作方式,分工方式的時間
而不是爭論哪種寫法效能比較高的時間
隨著需求改變,你所謂正確率最高的寫法有可能在當下直接變拖油瓶
最簡單的狀況就是因為絕對不會錯又大量狂跑一堆寫過頭的防錯機制
又或者你是為了因應未來"自己認定的可能修改方式"而特化了部分封裝,然而這永遠沒發生
結果發生的都是"自己認定以外的修改需求",結果感覺別人都在整自己,然而這不是從一開始想法就本末倒置了嗎?
所以,請務必清楚團隊合作開發一開始該做什麼
以上
說明:
1.文中所提及之基本易懂流程絕非單一函數CALL到底叫易懂,絕非SQL WHERE JOIN JOIN WHERE SELECT到底就叫易讀,這種也並非效能問題,而是會"直接死的問題"
2.效能問題大概像是"雙引號還是單引號效率高一點","我先用function整理起來,呼叫時間可以縮短0.01ms,記憶體可能減少1bit"的問題
是自作聰明,還是沒事找事做?
主管:請給我1+1的計算
恩...怎麼看都是echo 1+1 應該就OK了
等等,以後可能會改成2+1...好吧,那麼用傳入值的方式
var p = 1
var q = 1
echo p + q
嗯!完美!
不行不行,到時後說要突然把加換成乘怎麼辦
var p = 1
var q = 1
var op = "+"
function amazingPerfectFunction(p, q){
if (op == "+")then
echo p + q
}
call function amazingPerfectFunction(p, q)
等下,不行哦,搞不好有人p會亂改,或中途不小心改到
順便念一下好了
var p = 1
var q = 1
function amazingPerfectFunction(p, q){
try{
if (op == "+")then
echo p + q
}catch(notnumberexception e){
echo "你腦殘喔輸入什麼非數字!";
}
}
call function amazingPerfectFunction(p, q)
初版完美程式完成了:)
phpstorm 運行 phpunit的小問題
實際上在setting 做好直接引用的path to phpunit.phar即可直接使用
但是,這邊會遭遇到一個小意外:
如果你是按照PHPUnit的官網來做的話
https://phpunit.de/getting-started.html
最後的名稱是"phpunit"
因為PHPStorm只吃"phpunit.phar"這個特定名稱,所以載入會失敗
直接複製一個改名成phpunit.phar就可以直接載入
VirtualBox 共用資料夾 權限設定
參考自:
http://www.arthurtoday.com/2012/09/virtualbox-shared-folder-permission-denied-invalid-argument.html#.VCzomvmSz1Y
一般來說如果直接按一按設定做好環境,其實就可以直接用了
可是,只能用root
但是ubuntu環境本身就不是能用使用者root來操作的底
所以如果想要能直接點media/設定資料夾 就顯示的話
必須要sudo usermod -G vboxsf -a [使用者名稱]
Linux SSH Key遷移
確認是兩組相對應的key
如果key檔案不在~/.ssh/ 下就ssh-add,重開機就會不見,需要重新ssh-add
因此建議把key檔案放到~/.ssh/底下,開機後就會自動載入
ubuntu的設定網路別直接改interface檔
如題
猜測程式會覺得你寫的跟他預設的格式有點不同就判成別的版本
然後interface檔和系統設定值裡面的網路會雙雙掛掉....
當然可能只是個案
(我的狀況是interface和控制台的網路裡面的檔案都被ubuntu砍掉了)
總之紀錄一下這個狀況
[轉貼]Mysql Prepared Statement
有些人以為這種東西就是給PDO帶參數防inject用的,實在有點無言...
實際上這東西用途相當廣,也很適合應用於撰寫資料庫批次維護...
推薦你一定要看一下在mysql環境下怎麼直接做prepared statement
http://www.codedata.com.tw/database/mysql-tutorial-12-prepared-statement/
[轉貼] SQL Describe改(查comment 權限的表)
SHOW FULL FIELDS FROM database.table
SHOW FULL FIELDS FROM table FROM database
(如果已經USE過,直接FROM table就可以了)
資料來源:http://liaosankai.pixnet.net/blog/post/18480448
單元測試的真正意義(10/7更新)
就是Unit Test,結束,嗯?(不對阿,就真的是字面上的意思哦?)
不過確實,有很多人以為這東西是寫所有程序都應遵循的絕對準則,或者甚至以為Unit Test就是PHPUnit,JUnit,最嚴重的是還以為要涵蓋測試所有function,就是要確認我的資料處理完全正確...
(點選標題閱讀全文)