#關於成為工程師這件事 #文長慎入
如果有follow 我之前寫的種種文章,大概就知道我的一些經歷。但這邊還是來快速回顧一下。
大學的時候唸了歷史系,雖說跟分數也有關係,但一部分也是因為我對歷史很有興趣,小時候當所有人都想當老師,或醫生護士這種職業的時候,我總是想說要當那種什麼考古學家~探險家之類的,當然歷史學家跟發明家也是在考量的項目中,長大以後才發現,這好像有點不是現實中可以很容易實現的職業。
很多科目,像是歷史,或者其他社會科學相關的,在台灣畢業以後都非常難找工作,即使你認真向學,決定一路念到博士,也不見得畢業後可以找到教職或博後。即使是商學院畢業出來,在台灣可以做的也很有限,尤其當你是什麼管理學院相關的出來,也不太有機會直接躍升管理職。
台灣的產業其實比很多國家來的少,可以做的工作也有限,大部分都是科技相關,這也造就了台灣過去二三十年的榮光,到現在也一直是科技業為主流。當然科技業變成世界主流已經不是這一兩年的事情,全世界越來越多人想要擠進科技業,因為科技進步導致很多傳統產業面臨倒閉或者被迫改變。
說起來一開始除了自己想要試試看自己到底學不學得會寫程式這件情,再來就是因為不想一輩子領著低薪過著普通OL的日子,加上一直對國外有的憧憬,很想去國外看看外面的世界,體驗國外的生活,尤其是對歐美國家有著美好的想像。
要說當時為什麼做了這種倉促決定,其實大概就只是一個不甘心吧!因為在台灣沒有辦法念研究所,被各大學拒絕以後,就心想乾脆嘗試國外的大學,看有沒有人要我。其實大概就是個背水一戰的概念。
一直以來我都有點,盲目的亂衝。就是想到什麼就決定做什麼,當然有時候我也會變得很膽小,就會想太多,然後不敢前進。可是時常又覺得,應該要強迫自己前進,因為知道自己是個懶惰的人,所以不想辦法把自己帶到那個不得不的情況,自己就會一直怠惰下去。
說起來,一開始我也不是很認真的想要當工程師,也就是半推半就,覺得試試看的心態,身邊也沒有什麼人把這件事情當一回事,這都是到英國念研究所以後,才開始覺得自己可以做些什麼事情。但最近我也在反省,覺得自已以前在研究所也是很混,覺得自己第一年工作真的完全不知道在幹嘛。
最近到了新公司工作以後,發現公司很多人都是轉職的人,有人在媒體業待了十年,有人在金融業,有人從醫療產業,有人從產品經理轉職,大家都非常的認真,比我還要認真許多。
雖然我一直覺得,自己跟其他本科系畢業的人比起來,年紀很大,甚至會覺得自己轉行轉得太晚,有時候也會想說,為什麼自己國高中的時候不自己上網學寫程式,為什麼不好好念數學,這樣可以考個工程相關的科系。
可是在新公司遇到了很多他們以Graduate身份進來的轉職者,真的讓我覺得,其實自己轉的好像也不太晚。當然他們比我有毅力很多,很多人都是Bootscamp出來的,有的人甚至快要40歲了才以一個畢業生的身份進來。
我覺得在英國很好的一點是,這邊有很多公司可能願意收這種,想要轉職工程師的人。這些人有的可能甚至沒有唸過大學。
公司一個跟我一起onboard的資深工程師,他告訴我他沒有唸大學,全是靠自己學的,但網路上有很多開源專案他都是主要貢獻者。我覺得很厲害。
來英國以後我一直在反省自己,覺得有時候就是,自己會過得太安逸,就不太想努力生活,又或者覺得努力的生活好累,我幹嘛要這麼累,甚至會有一種,反正我只要表現得比其他人好就好。
因為一直以來在台灣的生活成長環境,我覺得自己的價值是被社會被周遭的人定義出來的。例如你的學歷,你的工作職稱,你的薪水,你的資產。
有時候我會覺得自己可能是個悲觀的人,又或者是其他人喜歡隱藏自已過得不好的部分?每次我看別人的部落格,或者別人敘述自己的職涯時,總是覺得別人的職涯好像都過得很順遂。
一直以來我都覺得,自己的職涯好像不是很順遂,其實跟很多人比起來好像已經不錯,畢竟有個工程師的工作,還是在國外的工作。可是實際上我都覺得,自己好像是個很差勁的工程師,為什麼自己好像寫出來的code都很爛,為什麼自己好像什麼都不會,為什麼自己好像學東西學得很慢,還有自己就是一個,很怠惰的人。我沒辦法像很多人是,可以一直去摸不同的東西,例如看到個新的東西出來,就馬上想要打開電腦去碰,我也不是那種,遇到一個解不出來的問題就想要一直去解開的人。更不是那種可以一直帶著我愛的電腦,去世界各地旅行,沒事就打開來寫code的人。
所以一直以來,我也時常在懷疑自己,自己是否適合當一個工程師。
這幾年在英國認識了一些朋友,我也一直覺得其他人都很優秀,尤其是當我一個很好的朋友說,他喜歡選擇困難的事情來做的時候,我真的覺得很愧疚,因為一直以來我都在嘗試避免困難的事情,大概也是因為這樣我開始覺得,自己是不是根本不適合當一個工程師,因為我根本不想要做有挑戰性的工作。
可是回顧自己以前在DHL做個海運OP的工作的時候,又覺得自己在那種環境下,很容易疲乏,就是那種,我該學的都已經學玩,然後每天接電話打電話發Email, 遇到的問題也都是用類似的方式去處以就可以解決。我也覺得自己沒辦法就這樣做個十年二十年。
當然那樣的生活還是有好處的,至少你不工作的時候可以全心全意的放空,也不用每天回家還要擔心deadline, 擔心code寫不出來,或者去想到底要怎麼寫,也不用整天擔心新的東西出來,沒辦法跟舊的東西相容,或者是不學新的東西,自己會很快被淘汰掉。
有時候自己也在想,乾脆逃去其他國家寫程式會不會比較好?我們公司因為是全球性的,所以可以調派到其他國家,但是公司說,假設我們去了其他國家可能是senior level, 不代表我們在英國可能一樣是senior, 因為不同國家的科技和技術能力是不同的。這代表說,工程師即使在某個國家做到一定的程度,去其他地方也不代表一樣厲害,所以自己還是要不斷的學習最新的世界趨勢,學習新的科技,不眠不休。這也是為什麼工程師很容易過勞死吧!
以前在台灣一直加班我覺得是身體勞累,但現在我覺得自己比較是心靈上的勞累。我甚至覺得自己應該要早早退休,然後開一個小店之類的,來賣便當。
不過如果現在要我轉去做其他的職業我也不知道要幹嘛。即使都是工程師,都是科技業,也分得很細,尤其在英國都喜歡分門別類。工作到現在快三年,若你要問我我的強項是什麼,其實我也說不太出來,大概就是web 相關的東西吧!所以關於職涯規劃這件事情我也一直在思考。
我認為自己應該至少要有個什麼Machine Learning 的相關知識,然後一些系統設計,或者DevOps的能力跟知識要有。當然,大部分的人可能會問到,在英國如果當工程師,當到一定的歲數會需要轉管離職嗎?其實好像不一定,很多公司的管理職跟技術職都是分開的,也就是說你走管理也不一定會領比較多錢,反正有兩條路讓你選。有的人可能做到退休都是工程師。
在英國工作到現在,其實我還是常常會覺得很不順遂,不管是技術,文化還是語言,應該說也不是不順遂,就是不自然,當然很多可能還是跟我英文不夠好有關係,我雖然可能可以理解90%的內容,可是剩下的10%如果不懂還是讓人感覺煩躁。
當然現在的情況是比剛開始工作好很多了,至少很多技術的東西已經有經驗了。我覺得剛開始轉職並且在英國工作的時候,真的讓人覺得很心累,雖然說也可能是因為我的Team剛好都是英國人,不知道為何,即使是現在的公司,公司很多元化,我被分到的Team也幾乎都是英國人QQ
反正大概就是會有一個時期,或者偶爾在聊天的時候,你覺得別人在講的某個東西,你完全不知道是什麼。你可能就跟著笑這樣。。。或者在講一些專有技術的名詞時,別人可能知道,你卻不知道,就會有一種恐慌。
我自己是覺得這方面有逐漸改善一點點,希望我在現在的公司可以做得比之前好,至少我現在比較聽得懂大家的北方口音。
至於寫程式方面,還是一樣很心累,就有一種,無底洞的感覺,不管你怎麼學都學不夠,學不完。像是跑馬拉松但是永遠到達不了終點的感覺。從我一開始學寫程式到現在還是這樣。
但如果說可以回到以前剛開始學的時候,我想我應該會希望自己看到任何不會的東西都不要跳過。我知道那樣可能會變成學得很慢,可是很多時候,像是我們想要建立一個網站,可能我們會Google,然後就會看到很多建議,例如用WP, 或者推薦你用什麼vue, react, angular, 可是問題來了,即使你會一些基本的JS, 你可以用這些框架或library建一個SPA(一個網站), 你還是不知道它實際上是怎麼運作的。他底層是怎麼跑的。這樣會有什麼問題呢?
當你自己在家裡按照教學做都可以做得很開心,可是當你要改東西,或者在工作的時候,發生了問題,你就不知道該怎麼辦,因為你不知道到底發生了什麼事情,為什麼會報錯。
另一種學習路線是,好,我要學寫程式,然後你就開始去看學習物件導向,學Java, 初學者都是,學寫一個Class, 學習那些型別,然後寫個hello world, 按下那個play 鍵,他就自己開始跑一些東西,然後build好了,你就看到下面的視窗打出hello world, 接著教學就會說,那我們來簡單的寫一些function, 然後你就會寫出一些基本的加法function, 給他int a, int b, 就會跑出a+b的結果。
更進階一點可能會有一些題目是,印星星,或印九九乘法表,或者用Apache web server, 架一個簡單的網站。學一點html, 一點CSS, 一點JS, 讓他看起來漂亮一點。
這個時候你個課程就差不多結束,你也有一個作品。
如果你想要找工作,可能會發現,工作很多考的內容你還是不會,或者你開始工作以後,發現很多東西還是不會。因為前面你做的那些事情都只是,根據指示做,就像你去IKEA買了家具按照那個指示來做,可是傢俱本身都已經切好了,零件也都配給你。今天如果要你自己去工廠買那些材料才切割才做,設計一個櫃子,你也做不出來。
所以問題來了,到底要怎麼樣學寫程式?我覺得大概就是,在做那些教學的時候,去思考,我現在做的每一步,是為什麼,如果不知道,就去Google, 不要貿然的進行。然後做完教學以後,看看自己能不能做出一個跟教學類似但不一樣的網站,最好是可以不要一直看著教學。
可以拿白板或紙,來畫一些圖,想想自己要做什麼,例如我要做一個,賣衣服的網站,我需要什麼東西,或者我要設計一款小遊戲,我要創造幾個角色,要有哪些怪獸,要有哪些關卡。
我自己是沒有去過BootsCamp, 但感覺BootsCamp的訓練都滿扎實的。英國有滿多免費的(雖然大部分是Women in Tech)的,所以想轉職的男生們可能要找付費的。
很多BootsCamp也是保證找到工作的,找不到可能會退錢。或者可以嘗試那種網路上免錢的。
當你開始工作以後,你可能要開始思考,你寫的code乾不乾淨,你有沒有寫測試,甚至你可以嘗試練習TDD(測試驅動開發),思考怎麼樣可以寫出好的程式碼,什麼叫做好的程式碼,越簡單越好,簡單易懂,白話程式碼,如果今天一個不會寫程式的人,可以經過你的解說,看得懂你的code, 那你真的就大成功了。
為什麼說要簡單易懂,因為通常工作以後你寫的code不是只有你自己要看,還有別人要看,甚至一年後的自己要看,之後你是不是還看得懂,例如命名,例如空行,例如有沒有重複的?
像是在工作以後,很多同事會用一些詞彙,例如DRY(don't repeat yourself), 或者網路上也可以找到很多文章,寫說要怎麼樣寫出乾淨的程式碼。除了乾淨以外,還要思考延展性,就像DIY的傢俱,或者書櫃,你一開始可能買了一個兩層櫃,你會希望你如果要變成三層可以加上去。或者是床,沙發,你會希望他們是可以我不佔空間,好收納,或者可以延伸。寫程式你也希望你寫的一些東西是這樣子。例如共用的程式碼,你可以寫一個可以把'2019/12/03' 轉換成 ’兩千零九年十二月三日‘ 的function, 你會希望這個function, 可以被廣為使用,可以是'20191203', '2019,12,03', 進來都會被轉換成文字的寫法這樣,那你要怎麼做?可以先去思考以要做的事情,然後寫出測試
像是在JS很多的測試是非常口語化的
describe('dateConvert', ()=>{
it('should return date using word format', ()=>{
expect(dataConvert('2019/12/03')).toEqual('兩千零
九年十二月三日');
})
})
如果有錯誤請各位糾正
反正工作以後,寫測試變成一件很重要的事情,還有要怎麼寫,因為當其他同事在看你的code的時候,如果你有寫完整的測試,同事也會比較好看得懂你的程式在做什麼
當然,沒有一個開發方法是完美的,也沒有什麼完美的code, 即使寫完了以後,也要檢查看看自己能不能把它變得更好,像是使用 TDD就可以一直加上新的測試,然後去想能不能把它變得更好,去重構。
各位如果有興趣的話也可以買一些書來看,雖然很多書已經出版很久,可是程式設計,跟軟體工程這塊,經典還是經典,可以幫助你了解,為什麼現在我們都用C語言而不是A語言,B語言,為什麼我們大眾使用物件導向來寫程式,不是使用Functional programming.
當你工作越久以後,可能會越容易遇到,你要去選擇你要用的程式語言,你要用的框架,你要用的工具。
有一天我問我的同事,到底要怎麼貢獻開源,他說不要為了貢獻而貢獻,一般都是,你因為自己在用這個開源軟體,遇到了一些問題,所以你去把它改善,或者說你需要一個工具,可是你Google很久發現都沒有,於是決定自己做一個。
雖然我覺得以目前的我來說,還很難達到這種程度,但希望我有一天可以。就像Vue.js的創辦人因為覺得Angular.js不夠好,於是決定把好的部分留下,再加上自己覺得可以讓他變得更好的部分,創造了Vue.js
其實我自己也很害怕去討論這些非常技術的東西,我很怕自己講錯誤導大家哈哈
成為工程師真的需要很強的心臟,因為需要接受很多批評,很多反饋,才可以進步。當然有時候我也很玻璃心,常常因為被其他工程師點出自己的錯誤就心情不好,可是如果都沒有人批評自己,自己大概也不會進步。我想這大概是跟其他工作最大的不同吧!
以前在做海運出口的時候,即使可能做錯也不會一直被講,除非你真的是做了很嚴重的事情,不會你每接一通點話,每寫一封信都有人來看,有人來糾正,有人來說,你Email要怎麼怎麼改,你這樣寫不行。
可是寫程式,你寫出來的每一行code都可能被品頭論足,每一行code都要確保它的質量,當然我知道不是每個公司都有code review, 可因為我一直以來都有這個東西,也導致我覺得壓力滿大的哈哈
不知道分享這些會不會讓大家也覺得壓力大
同時也有73部Youtube影片,追蹤數超過2萬的網紅Untyped 對啊我是工程師,也在其Youtube影片中提到,Coding vs Programming 軟體工程師在 編碼 or 編程? | 5 Differences between Coding and Programming【電腦說人話】 - 軟體工程師到底在幹嘛?內行外行怎麼說? Coding? Programming? 程式設計?編碼編程?想到電腦...
「java class教學」的推薦目錄:
- 關於java class教學 在 小吃貨的英國生活日記 Facebook 的最佳貼文
- 關於java class教學 在 小吃貨的英國生活日記 Facebook 的最佳解答
- 關於java class教學 在 紀老師程式教學網 Facebook 的最佳解答
- 關於java class教學 在 Untyped 對啊我是工程師 Youtube 的最佳解答
- 關於java class教學 在 吳老師教學部落格 Youtube 的最佳貼文
- 關於java class教學 在 吳老師教學部落格 Youtube 的最佳解答
- 關於java class教學 在 [翻譯] 給Java程式設計師的Scala入門教學- 看板Translate-CS 的評價
- 關於java class教學 在 Java學習筆記-方法(Method) 的評價
- 關於java class教學 在 第8 章繼承(Inheritance)、多型(Polymorphism) - GitHub 的評價
- 關於java class教學 在 [Java]_ch8.3_類別變數與類別方法class 人類{ private int 眼 的評價
java class教學 在 小吃貨的英國生活日記 Facebook 的最佳解答
#關於成為工程師這件事 #文長慎入
如果有follow 我之前寫的種種文章,大概就知道我的一些經歷。但這邊還是來快速回顧一下。
大學的時候唸了歷史系,雖說跟分數也有關係,但一部分也是因為我對歷史很有興趣,小時候當所有人都想當老師,或醫生護士這種職業的時候,我總是想說要當那種什麼考古學家~探險家之類的,當然歷史學家跟發明家也是在考量的項目中,長大以後才發現,這好像有點不是現實中可以很容易實現的職業。
很多科目,像是歷史,或者其他社會科學相關的,在台灣畢業以後都非常難找工作,即使你認真向學,決定一路念到博士,也不見得畢業後可以找到教職或博後。即使是商學院畢業出來,在台灣可以做的也很有限,尤其當你是什麼管理學院相關的出來,也不太有機會直接躍升管理職。
台灣的產業其實比很多國家來的少,可以做的工作也有限,大部分都是科技相關,這也造就了台灣過去二三十年的榮光,到現在也一直是科技業為主流。當然科技業變成世界主流已經不是這一兩年的事情,全世界越來越多人想要擠進科技業,因為科技進步導致很多傳統產業面臨倒閉或者被迫改變。
說起來一開始除了自己想要試試看自己到底學不學得會寫程式這件情,再來就是因為不想一輩子領著低薪過著普通OL的日子,加上一直對國外有的憧憬,很想去國外看看外面的世界,體驗國外的生活,尤其是對歐美國家有著美好的想像。
要說當時為什麼做了這種倉促決定,其實大概就只是一個不甘心吧!因為在台灣沒有辦法念研究所,被各大學拒絕以後,就心想乾脆嘗試國外的大學,看有沒有人要我。其實大概就是個背水一戰的概念。
一直以來我都有點,盲目的亂衝。就是想到什麼就決定做什麼,當然有時候我也會變得很膽小,就會想太多,然後不敢前進。可是時常又覺得,應該要強迫自己前進,因為知道自己是個懶惰的人,所以不想辦法把自己帶到那個不得不的情況,自己就會一直怠惰下去。
說起來,一開始我也不是很認真的想要當工程師,也就是半推半就,覺得試試看的心態,身邊也沒有什麼人把這件事情當一回事,這都是到英國念研究所以後,才開始覺得自己可以做些什麼事情。但最近我也在反省,覺得自已以前在研究所也是很混,覺得自己第一年工作真的完全不知道在幹嘛。
最近到了新公司工作以後,發現公司很多人都是轉職的人,有人在媒體業待了十年,有人在金融業,有人從醫療產業,有人從產品經理轉職,大家都非常的認真,比我還要認真許多。
雖然我一直覺得,自己跟其他本科系畢業的人比起來,年紀很大,甚至會覺得自己轉行轉得太晚,有時候也會想說,為什麼自己國高中的時候不自己上網學寫程式,為什麼不好好念數學,這樣可以考個工程相關的科系。
可是在新公司遇到了很多他們以Graduate身份進來的轉職者,真的讓我覺得,其實自己轉的好像也不太晚。當然他們比我有毅力很多,很多人都是Bootscamp出來的,有的人甚至快要40歲了才以一個畢業生的身份進來。
我覺得在英國很好的一點是,這邊有很多公司可能願意收這種,想要轉職工程師的人。這些人有的可能甚至沒有唸過大學。
公司一個跟我一起onboard的資深工程師,他告訴我他沒有唸大學,全是靠自己學的,但網路上有很多開源專案他都是主要貢獻者。我覺得很厲害。
來英國以後我一直在反省自己,覺得有時候就是,自己會過得太安逸,就不太想努力生活,又或者覺得努力的生活好累,我幹嘛要這麼累,甚至會有一種,反正我只要表現得比其他人好就好。
因為一直以來在台灣的生活成長環境,我覺得自己的價值是被社會被周遭的人定義出來的。例如你的學歷,你的工作職稱,你的薪水,你的資產。
有時候我會覺得自己可能是個悲觀的人,又或者是其他人喜歡隱藏自已過得不好的部分?每次我看別人的部落格,或者別人敘述自己的職涯時,總是覺得別人的職涯好像都過得很順遂。
一直以來我都覺得,自己的職涯好像不是很順遂,其實跟很多人比起來好像已經不錯,畢竟有個工程師的工作,還是在國外的工作。可是實際上我都覺得,自己好像是個很差勁的工程師,為什麼自己好像寫出來的code都很爛,為什麼自己好像什麼都不會,為什麼自己好像學東西學得很慢,還有自己就是一個,很怠惰的人。我沒辦法像很多人是,可以一直去摸不同的東西,例如看到個新的東西出來,就馬上想要打開電腦去碰,我也不是那種,遇到一個解不出來的問題就想要一直去解開的人。更不是那種可以一直帶著我愛的電腦,去世界各地旅行,沒事就打開來寫code的人。
所以一直以來,我也時常在懷疑自己,自己是否適合當一個工程師。
這幾年在英國認識了一些朋友,我也一直覺得其他人都很優秀,尤其是當我一個很好的朋友說,他喜歡選擇困難的事情來做的時候,我真的覺得很愧疚,因為一直以來我都在嘗試避免困難的事情,大概也是因為這樣我開始覺得,自己是不是根本不適合當一個工程師,因為我根本不想要做有挑戰性的工作。
可是回顧自己以前在DHL做個海運OP的工作的時候,又覺得自己在那種環境下,很容易疲乏,就是那種,我該學的都已經學玩,然後每天接電話打電話發Email, 遇到的問題也都是用類似的方式去處以就可以解決。我也覺得自己沒辦法就這樣做個十年二十年。
當然那樣的生活還是有好處的,至少你不工作的時候可以全心全意的放空,也不用每天回家還要擔心deadline, 擔心code寫不出來,或者去想到底要怎麼寫,也不用整天擔心新的東西出來,沒辦法跟舊的東西相容,或者是不學新的東西,自己會很快被淘汰掉。
有時候自己也在想,乾脆逃去其他國家寫程式會不會比較好?我們公司因為是全球性的,所以可以調派到其他國家,但是公司說,假設我們去了其他國家可能是senior level, 不代表我們在英國可能一樣是senior, 因為不同國家的科技和技術能力是不同的。這代表說,工程師即使在某個國家做到一定的程度,去其他地方也不代表一樣厲害,所以自己還是要不斷的學習最新的世界趨勢,學習新的科技,不眠不休。這也是為什麼工程師很容易過勞死吧!
以前在台灣一直加班我覺得是身體勞累,但現在我覺得自己比較是心靈上的勞累。我甚至覺得自己應該要早早退休,然後開一個小店之類的,來賣便當。
不過如果現在要我轉去做其他的職業我也不知道要幹嘛。即使都是工程師,都是科技業,也分得很細,尤其在英國都喜歡分門別類。工作到現在快三年,若你要問我我的強項是什麼,其實我也說不太出來,大概就是web 相關的東西吧!所以關於職涯規劃這件事情我也一直在思考。
我認為自己應該至少要有個什麼Machine Learning 的相關知識,然後一些系統設計,或者DevOps的能力跟知識要有。當然,大部分的人可能會問到,在英國如果當工程師,當到一定的歲數會需要轉管離職嗎?其實好像不一定,很多公司的管理職跟技術職都是分開的,也就是說你走管理也不一定會領比較多錢,反正有兩條路讓你選。有的人可能做到退休都是工程師。
在英國工作到現在,其實我還是常常會覺得很不順遂,不管是技術,文化還是語言,應該說也不是不順遂,就是不自然,當然很多可能還是跟我英文不夠好有關係,我雖然可能可以理解90%的內容,可是剩下的10%如果不懂還是讓人感覺煩躁。
當然現在的情況是比剛開始工作好很多了,至少很多技術的東西已經有經驗了。我覺得剛開始轉職並且在英國工作的時候,真的讓人覺得很心累,雖然說也可能是因為我的Team剛好都是英國人,不知道為何,即使是現在的公司,公司很多元化,我被分到的Team也幾乎都是英國人QQ
反正大概就是會有一個時期,或者偶爾在聊天的時候,你覺得別人在講的某個東西,你完全不知道是什麼。你可能就跟著笑這樣。。。或者在講一些專有技術的名詞時,別人可能知道,你卻不知道,就會有一種恐慌。
我自己是覺得這方面有逐漸改善一點點,希望我在現在的公司可以做得比之前好,至少我現在比較聽得懂大家的北方口音。
至於寫程式方面,還是一樣很心累,就有一種,無底洞的感覺,不管你怎麼學都學不夠,學不完。像是跑馬拉松但是永遠到達不了終點的感覺。從我一開始學寫程式到現在還是這樣。
但如果說可以回到以前剛開始學的時候,我想我應該會希望自己看到任何不會的東西都不要跳過。我知道那樣可能會變成學得很慢,可是很多時候,像是我們想要建立一個網站,可能我們會Google,然後就會看到很多建議,例如用WP, 或者推薦你用什麼vue, react, angular, 可是問題來了,即使你會一些基本的JS, 你可以用這些框架或library建一個SPA(一個網站), 你還是不知道它實際上是怎麼運作的。他底層是怎麼跑的。這樣會有什麼問題呢?
當你自己在家裡按照教學做都可以做得很開心,可是當你要改東西,或者在工作的時候,發生了問題,你就不知道該怎麼辦,因為你不知道到底發生了什麼事情,為什麼會報錯。
另一種學習路線是,好,我要學寫程式,然後你就開始去看學習物件導向,學Java, 初學者都是,學寫一個Class, 學習那些型別,然後寫個hello world, 按下那個play 鍵,他就自己開始跑一些東西,然後build好了,你就看到下面的視窗打出hello world, 接著教學就會說,那我們來簡單的寫一些function, 然後你就會寫出一些基本的加法function, 給他int a, int b, 就會跑出a+b的結果。
更進階一點可能會有一些題目是,印星星,或印九九乘法表,或者用Apache web server, 架一個簡單的網站。學一點html, 一點CSS, 一點JS, 讓他看起來漂亮一點。
這個時候你個課程就差不多結束,你也有一個作品。
如果你想要找工作,可能會發現,工作很多考的內容你還是不會,或者你開始工作以後,發現很多東西還是不會。因為前面你做的那些事情都只是,根據指示做,就像你去IKEA買了家具按照那個指示來做,可是傢俱本身都已經切好了,零件也都配給你。今天如果要你自己去工廠買那些材料才切割才做,設計一個櫃子,你也做不出來。
所以問題來了,到底要怎麼樣學寫程式?我覺得大概就是,在做那些教學的時候,去思考,我現在做的每一步,是為什麼,如果不知道,就去Google, 不要貿然的進行。然後做完教學以後,看看自己能不能做出一個跟教學類似但不一樣的網站,最好是可以不要一直看著教學。
可以拿白板或紙,來畫一些圖,想想自己要做什麼,例如我要做一個,賣衣服的網站,我需要什麼東西,或者我要設計一款小遊戲,我要創造幾個角色,要有哪些怪獸,要有哪些關卡。
我自己是沒有去過BootsCamp, 但感覺BootsCamp的訓練都滿扎實的。英國有滿多免費的(雖然大部分是Women in Tech)的,所以想轉職的男生們可能要找付費的。
很多BootsCamp也是保證找到工作的,找不到可能會退錢。或者可以嘗試那種網路上免錢的。
當你開始工作以後,你可能要開始思考,你寫的code乾不乾淨,你有沒有寫測試,甚至你可以嘗試練習TDD(測試驅動開發),思考怎麼樣可以寫出好的程式碼,什麼叫做好的程式碼,越簡單越好,簡單易懂,白話程式碼,如果今天一個不會寫程式的人,可以經過你的解說,看得懂你的code, 那你真的就大成功了。
為什麼說要簡單易懂,因為通常工作以後你寫的code不是只有你自己要看,還有別人要看,甚至一年後的自己要看,之後你是不是還看得懂,例如命名,例如空行,例如有沒有重複的?
像是在工作以後,很多同事會用一些詞彙,例如DRY(don't repeat yourself), 或者網路上也可以找到很多文章,寫說要怎麼樣寫出乾淨的程式碼。除了乾淨以外,還要思考延展性,就像DIY的傢俱,或者書櫃,你一開始可能買了一個兩層櫃,你會希望你如果要變成三層可以加上去。或者是床,沙發,你會希望他們是可以我不佔空間,好收納,或者可以延伸。寫程式你也希望你寫的一些東西是這樣子。例如共用的程式碼,你可以寫一個可以把'2019/12/03' 轉換成 ’兩千零九年十二月三日‘ 的function, 你會希望這個function, 可以被廣為使用,可以是'20191203', '2019,12,03', 進來都會被轉換成文字的寫法這樣,那你要怎麼做?可以先去思考以要做的事情,然後寫出測試
像是在JS很多的測試是非常口語化的
describe('dateConvert', ()=>{
it('should return date using word format', ()=>{
expect(dataConvert('2019/12/03')).toEqual('兩千零
九年十二月三日');
})
})
如果有錯誤請各位糾正
反正工作以後,寫測試變成一件很重要的事情,還有要怎麼寫,因為當其他同事在看你的code的時候,如果你有寫完整的測試,同事也會比較好看得懂你的程式在做什麼
當然,沒有一個開發方法是完美的,也沒有什麼完美的code, 即使寫完了以後,也要檢查看看自己能不能把它變得更好,像是使用 TDD就可以一直加上新的測試,然後去想能不能把它變得更好,去重構。
各位如果有興趣的話也可以買一些書來看,雖然很多書已經出版很久,可是程式設計,跟軟體工程這塊,經典還是經典,可以幫助你了解,為什麼現在我們都用C語言而不是A語言,B語言,為什麼我們大眾使用物件導向來寫程式,不是使用Functional programming.
當你工作越久以後,可能會越容易遇到,你要去選擇你要用的程式語言,你要用的框架,你要用的工具。
有一天我問我的同事,到底要怎麼貢獻開源,他說不要為了貢獻而貢獻,一般都是,你因為自己在用這個開源軟體,遇到了一些問題,所以你去把它改善,或者說你需要一個工具,可是你Google很久發現都沒有,於是決定自己做一個。
雖然我覺得以目前的我來說,還很難達到這種程度,但希望我有一天可以。就像Vue.js的創辦人因為覺得Angular.js不夠好,於是決定把好的部分留下,再加上自己覺得可以讓他變得更好的部分,創造了Vue.js
其實我自己也很害怕去討論這些非常技術的東西,我很怕自己講錯誤導大家哈哈
成為工程師真的需要很強的心臟,因為需要接受很多批評,很多反饋,才可以進步。當然有時候我也很玻璃心,常常因為被其他工程師點出自己的錯誤就心情不好,可是如果都沒有人批評自己,自己大概也不會進步。我想這大概是跟其他工作最大的不同吧!
以前在做海運出口的時候,即使可能做錯也不會一直被講,除非你真的是做了很嚴重的事情,不會你每接一通點話,每寫一封信都有人來看,有人來糾正,有人來說,你Email要怎麼怎麼改,你這樣寫不行。
可是寫程式,你寫出來的每一行code都可能被品頭論足,每一行code都要確保它的質量,當然我知道不是每個公司都有code review, 可因為我一直以來都有這個東西,也導致我覺得壓力滿大的哈哈
不知道分享這些會不會讓大家也覺得壓力大
java class教學 在 紀老師程式教學網 Facebook 的最佳解答
[Python 自製教學資源] Python 物件導向中,私有成員繼承的底層原理
網址: https://youtu.be/oMhCsWqXJnE
嗯...其實這份資源我本來沒有打算公開給粉絲知道的...不是我小氣,我是怕這份資料太冷門了。加上問題的回答非常針對同學自己寫的程式碼,考慮到普遍性不高,所以才會想是否只給那位同學看就好。
後來想到,這個粉絲頁應該也有不少高手,把這份資料公開,說不定有人會指出我講錯的地方,那不是更好嗎?所以就「忝不知恥」(笑)地公開了。野人獻曝、班門弄斧的地方,還請大家多指教。
想看懂這份影片,您得先熟習 (1) 一般的 Python 語法 (2) Python 物件導向語法 (3) 知道什麼是私有成員,再看這份影片比較有感覺。不過您若有一兩樣不熟,也歡迎看看啦~說不定您也會有所得喔!
其實 Python 做到「私有成員」方法很簡單,就是把原來加雙底線的 Python 私有成員(任何在 Python 物件內加上雙底線開頭的成員名稱,都會被自動視為私有成員。這跟 C++ 或 Java 得冠上 private 關鍵字的作法有點不同),冠上「_類別名稱」的前綴字(prefix)。如:class C1 類別內,有個私有成員叫做 __age,它底層的真正名稱,就叫「_C1__age」。這樣其它人想要存取,由於類別名稱的不同,就抓不到該私有成員。但是若懂底層原理,硬抓 _C1__age 這個名字還是抓得到的(胡適懂物件導向的話,大概會說出:「私有都不私有了」XD -- 梗:『老子都不老子了』)。
第一次公開比較進階的教學材料,有點忐忑不安。不知道這樣的資料大家會不會覺得太深、不應該出現在這個粉絲頁河道呢?喜歡的話,還請大家多多按讚鼓勵、分享給您的 FB 朋友、或者在下方留言討論喔!祝福大家有愉快的一天!
java class教學 在 Untyped 對啊我是工程師 Youtube 的最佳解答
Coding vs Programming 軟體工程師在 編碼 or 編程? | 5 Differences between Coding and Programming【電腦說人話】
-
軟體工程師到底在幹嘛?內行外行怎麼說?
Coding? Programming? 程式設計?編碼編程?想到電腦科學就會想到這些詞,但是它們到底是什麼意思?差別又在哪呢?
讓凱心琳告訴你這兩個詞的5大層面的差別!
(Tools 使用工具, Expertise 專業知識, Approach 方法途徑, Outcome 成果產出, Learning 學習過程)
在這個人手好幾台電腦的時代,實在是有好多電腦的詞聽不懂。Cookie 不再是好吃的餅乾,Class不再是學生上的課,Bug 因為非常不一樣的原因而令人討厭。Coding, Programming 兩個詞表面上好像一樣,但是實際上卻截然不同。好多詞不懂~沒關係!讓 Untyped 為你解惑!
【電腦說人話】這個系列是希望透過口語化的方式,透過生活中的例子去介紹一些看似艱澀像外星語但實際上卻不難懂的電腦科學專有名詞。希望能讓曾經對這些詞彙充滿畏懼與疑惑的妳,能夠不再害怕,勇敢學習Computer Science!
【㊫ 電腦科學/軟體工程 學習資源 📖】
全端工程師密技 Full Stack Eng - Career Path (Codecademy)
https://bit.ly/3niTwLN
前端工程師密技 Front End Eng - Career Path (Codecademy)
https://bit.ly/32K1eql
用Scala學習函式程式設計
https://bit.ly/2IF0Thv
Scala 函数式程式設計原理
https://bit.ly/3kBQXTb
平行程式設計
https://bit.ly/3pCeaZf
Android 應用程式開發 專項課程
https://bit.ly/3lGCUwW
普林斯頓大學 電腦科學 演算法 基礎理論
https://bit.ly/3nxomAh
Go 語言學起來
https://bit.ly/35AWhlv
Parallel, Concurrent, and Distributed Programming in Java 專項課程
https://bit.ly/2IGnlH4
Java 軟體工程基礎課程
https://bit.ly/3fa4gJi
全端開發 跨平台手機app 開發 完整課程
https://bit.ly/2UCGWum
#程式設計 #Programming #電腦說人話
一定要看到影片最後面並且在「YouTube影片下方」按讚留言訂閱分享唷!
-
歡迎留言告訴我你的想法,或是你想認識的程式語言唷!
每(隔週)週四晚上9點更新,請記得開啟YouTube🔔通知!
-
【相關連結】
Coding vs Programming
[https://www.codementor.io/@edwardbailey/coding-vs-programming-what-s-the-difference-yr0aeug9o]
[https://www.educba.com/coding-vs-programming/]
[https://www.goodcore.co.uk/blog/coding-vs-programming/]
【愛屋及烏】
Facebook 臉書粉專 👉 [https://www.facebook.com/untyped/]
Instagram 👉 [[https://www.instagram.com/untypedcoding/]
合作邀約 👉 untypedcoding@gmail.com
-
Untyped 對啊我是工程師 - There are so many data types in the world of computer science, so are the people who write the code. We aim to UNTYPE the stereotype of engineers and of how coding is only for a certain type of people.
凱心琳: 一個喜歡電腦科學邏輯推理,在科技圈努力為性別平等奮鬥的女工程師。
-
This video contains affiliate links, which means that if you click on one of the product links, I'll receive a small commission.
圖片影片音效:[giphy.com] [pngwave.com][freesound.org][soundbible.org]
【Disclaimer 聲明】
Some links are affiliated.
上面有些連結是回饋連結,如果你透過這些連結購買商品,我可以得到一些小獎勵,但不會影響到你購買的價格,甚至會是更低的價格!謝謝你的支持💕
java class教學 在 吳老師教學部落格 Youtube 的最佳貼文
文化JAVA物件導向程式設計2016_3(類別應用與運算子與重覆控制)
今天課程內容:
01_複習中文API設定與增加Scanner類別
02_版本控制與細節說明
03_改寫為JOptionPane的輸入方式
04_改寫為showMessageDialog與輸出可執行的JAR檔
05_如何解出JAR檔與反組譯CLASS
06_修改程式庫設定與跳脫字元練習
07_運算子與Switch範例
08_Switch車票範例與改寫為IF
09_Switch性別範例與改寫為IF
10_重覆控制for迴圈與奇數加總
11_For範例與巢狀結構
完整影音:
https://www.youtube.com/playlist?list=PLCfL1sBZ2_STmLOmuI7w2_j8BQXcama4a
教學論壇(之後課程會放論壇上課學員請自行加入):
https://groups.google.com/forum/#!forum/java_object2016
懶人包:http://terry55wu.blogspot.com/p/android.html
主要以實例說明為主,比較具體。至於抽象理論書上都有詳細說明,
請大家配合範例研讀,應該會更好了解的。
課程理念:Android智慧型手機平台,已成為手機上最完整的開放開發平台
人手必備的趨勢下行動上網已達1000萬人次以上,手機相關應用,將會超越PC,比PC更智慧,更貼近個人使用習慣,未來APP將漸取代Web,成為各產
業或政府對外窗口。
如何開發APP,以循序漸進的方式講授Android應用程式架構、圖形介面開發、測試與除錯等,進而取得證照。
吳老師教學特色:
1.影音複習分享(全程錄影)。
2.能不硬code程式,有程式也會提供畫面。
3.提供業界實務開發經驗。
4.書上沒講到的操作,圖形化工具使用。
5.隨時更新第一手資訊。
6.可延伸證照考試解題(TQC+)。
7.提供雲端影音連結
8.提供部落格教學日誌
9.提供論壇登入問題討論
上課用書:
Java SE 7與Android 4.x程式設計範例教本
作者:陳會安
本學期課程目標:
1.把JAVA融入到Android
2.Android入門
3.Android範例詳解
1.把JAVA融入到Android
於是將拿自己最熟悉的JAVA證照題目,
用最好的開發環境 ECLIPSE開發JAVA變得很重要,
可惜目前要找到如何用 ECLIPSE開發 JAVA的書籍似乎闕如,
但要開發JAVA與Androdi就一定要學好ECLIPSE,
於是劇本流程:
1.ECLIPSE的環境建置。
2.新建JAVA專案,開始寫101題樂透彩模擬程式。
3.轉成視窗介面。
4.輸出程執行檔,可以在WINDOWS、MAC、LINUS等環境執行。
5.將專案改成APP。
上下來還蠻緊湊,因為也要繳交作業,學生開始變得更積極。
回家之後我就變成後製,又搖身一半為部落客,
寫文分享JAVA開發經驗。
Android 教學研習心得分享懶人包:
http://terry55wu.blogspot.com/p/android.html
吳老師
java下載 jdk eclipse java教學網站 java教學影片 "java eclipse教學" "eclipse 教學" java證照解答 AWT類別 電腦證照
java class教學 在 吳老師教學部落格 Youtube 的最佳解答
文化JAVA物件導向程式設計2016_3(類別應用與運算子與重覆控制)
今天課程內容:
01_複習中文API設定與增加Scanner類別
02_版本控制與細節說明
03_改寫為JOptionPane的輸入方式
04_改寫為showMessageDialog與輸出可執行的JAR檔
05_如何解出JAR檔與反組譯CLASS
06_修改程式庫設定與跳脫字元練習
07_運算子與Switch範例
08_Switch車票範例與改寫為IF
09_Switch性別範例與改寫為IF
10_重覆控制for迴圈與奇數加總
11_For範例與巢狀結構
完整影音:
https://www.youtube.com/playlist?list=PLCfL1sBZ2_STmLOmuI7w2_j8BQXcama4a
教學論壇(之後課程會放論壇上課學員請自行加入):
https://groups.google.com/forum/#!forum/java_object2016
懶人包:http://terry55wu.blogspot.com/p/android.html
主要以實例說明為主,比較具體。至於抽象理論書上都有詳細說明,
請大家配合範例研讀,應該會更好了解的。
課程理念:Android智慧型手機平台,已成為手機上最完整的開放開發平台
人手必備的趨勢下行動上網已達1000萬人次以上,手機相關應用,將會超越PC,比PC更智慧,更貼近個人使用習慣,未來APP將漸取代Web,成為各產
業或政府對外窗口。
如何開發APP,以循序漸進的方式講授Android應用程式架構、圖形介面開發、測試與除錯等,進而取得證照。
吳老師教學特色:
1.影音複習分享(全程錄影)。
2.能不硬code程式,有程式也會提供畫面。
3.提供業界實務開發經驗。
4.書上沒講到的操作,圖形化工具使用。
5.隨時更新第一手資訊。
6.可延伸證照考試解題(TQC+)。
7.提供雲端影音連結
8.提供部落格教學日誌
9.提供論壇登入問題討論
上課用書:
Java SE 7與Android 4.x程式設計範例教本
作者:陳會安
本學期課程目標:
1.把JAVA融入到Android
2.Android入門
3.Android範例詳解
1.把JAVA融入到Android
於是將拿自己最熟悉的JAVA證照題目,
用最好的開發環境 ECLIPSE開發JAVA變得很重要,
可惜目前要找到如何用 ECLIPSE開發 JAVA的書籍似乎闕如,
但要開發JAVA與Androdi就一定要學好ECLIPSE,
於是劇本流程:
1.ECLIPSE的環境建置。
2.新建JAVA專案,開始寫101題樂透彩模擬程式。
3.轉成視窗介面。
4.輸出程執行檔,可以在WINDOWS、MAC、LINUS等環境執行。
5.將專案改成APP。
上下來還蠻緊湊,因為也要繳交作業,學生開始變得更積極。
回家之後我就變成後製,又搖身一半為部落客,
寫文分享JAVA開發經驗。
Android 教學研習心得分享懶人包:
http://terry55wu.blogspot.com/p/android.html
吳老師
java下載 jdk eclipse java教學網站 java教學影片 "java eclipse教學" "eclipse 教學" java證照解答 AWT類別 電腦證照
java class教學 在 Java學習筆記-方法(Method) 的推薦與評價
Hello, World! 另一個則是不同class的呼叫:. 程式, 輸出. class class_example{ public static void ... ... <看更多>
java class教學 在 第8 章繼承(Inheritance)、多型(Polymorphism) - GitHub 的推薦與評價
成員如果被宣告為"protected",則擴充它的子類別就可以直接使用該資料成員,而不用透過"public" 方法成員來呼叫,如範例8.5 所示範的。 範例8.5 Cubic.java. public class ... ... <看更多>
java class教學 在 [翻譯] 給Java程式設計師的Scala入門教學- 看板Translate-CS 的推薦與評價
譯自
https://docs.scala-lang.org/tutorials/scala-for-java-programmers.html
因為原文是用markdown撰寫,譯文也直接用markdown格式撰寫
github好讀版(?)
https://github.com/chikei/scala.github.com/blob/zh_TW/zh/tutorials/
scala-for-java-programmers.md
~~~正文分隔線~~~
## 介紹
此教學將對Scala語言以及編譯器做一個簡易的介紹。設定的讀者為具有程設經驗且想
要看Scala功能概要的人。內文假設讀者有著基本、特別是Java上的物件導向程設知識。
## 第一個例子
這邊用標準的 *Hello world* 程式作為第一個例子。雖然它很無趣,可是這讓我們在
僅用少量語言下演示Scala工具。程式如下:
object HelloWorld {
def main(args: Array[String]) {
println("Hello, world!")
}
}
Java程式員應該對這個程式的結構感到熟悉:有著一個 `main` 函式,該函式接受一
個字串陣列引數,也就是命令列引數;函式內容為呼叫已定義好的函式 `println` 並
用Hello world字串當引數。 `main` 函式沒有回傳值(它是程序函式)。因此並不需要
宣告回傳型別。
Java程式員不太熟悉的是包著 `main` 函式的 `object` 宣告。這種宣告引入我們一
般稱之 *Singleton* 的東西,也就是只有一個實體的類別。所以上面的宣告同時宣告
了一個 `HelloWorld` 類別跟一個這類別的實體,也叫做 `HelloWorld`。該實體會在
第一次被使用到的時候即時產生。
眼尖的讀者可能已經注意到這邊 `main` 函式的宣告沒有帶著 `static`。這是因為
Scala沒有靜態成員(函式或資料欄)。Scala程式員將這成員宣告在單實例物件中,而
不是定義靜態成員。
### 編譯這例子
我們用Scala編譯器 `scalac`來編譯這個例子。`scalac` 就像大多數的編譯器一樣,
它接受原碼檔當引數,並接受額外的選項,然後產生一個或多個物件檔。它產出的物
件檔為標準的Java class檔案。
如果我們將上面的程式存成 `HelloWorld.scala` 檔,編譯的指令為( `>` 是提示字
元,不用打):
> scalac HelloWorld.scala
這會在現在的目錄產生一些class檔案。其中一個會叫做 `HelloWorld.class`,裡面
包含著可被 `scala` 直接執行的類別。
### 執行範例
一旦編譯過後,Scala程式可以用 `scala` 指令執行。它的使用方式非常的像執行
Java程式的 `java` 指令,並且接受同樣的選項。上面的範例可以用以下的指令來執
行並得到我們預期的輸出:
> scala -classpath . HelloWorld
Hello, world!
## 與Java互動
Scala的優點之一是它非常的容易跟Java程式碼溝通。預設匯入所有 `java.lang` 底
下之類別,其他類別則需要明確匯入。
讓我們看個展示這點的範例。取得現在的日期並根據某個特定的國家排版成該國的格
式,如法國。
Java的標準函式庫定義了一些有用的工具類別,如 `Date` 跟 `DateFormat`。因為
Scala可以無縫的跟Java互動,這邊不需要以Scala實作同樣的類別--我們只需要匯入
對應的Java套件:
import java.util.{Date, Locale}
import java.text.DateFormat
import java.text.DateFormat._
object FrenchDate {
def main(args: Array[String]) {
val now = new Date
val df = getDateInstance(LONG, Locale.FRANCE)
println(df format now)
}
}
Scala的匯入陳述式跟Java的非常像,但更為強大。如第一行,同一個package下的多
個類別可以用大括號括起來一起導入。另外一個差別是,當要匯入套件或類別下所有
的名稱時,用下標(`_`)而不是星號(`*`)。這是因為星號是一個合法的Scala識別符號
(如函式名稱)。
所以第三行的陳述式導入所有 `DateFormat` 類別的成員。這讓靜態函式
`getDateInstance` 跟靜態資料欄 `LONG` 可直接被使用。
在 `main` 函式中我們先創造一個Java的 `Date` 類別實體,該實體預設擁有現在的
日期。接下來用 `getDateInstance` 函式定義日期格式。最後根據地區化的
`DateFormat` 實體對現在日期排版格式化並印出。最後一行展現了一個Scala有趣的
特點。只需要一個引數的函式可以用中綴語法呼叫。就是說,這個表示式
df format now
是比較不詳細版本的這個表示式
df.format(now)
這點也許看起來只是一個小小的語法細節,但是他有著重要的後果,其中一個將會在
下一節做介紹。
讓我們以,Scala可以直接繼承Java類別跟實作Java介面,來為這節做結尾。
## 萬物皆物件
Scala是一個純粹的物件導向語言,這句話的意思是說,*所有東西*都是物件,包括數
字、函式。因為Java將基本型別跟參照型別分開,而且沒有辦法像操作變數一樣操作
函式,從這角度來看Scala跟Java是不同的。
### 數字是物件
因為數字是物件,他們也有函式。事實上,一個像底下的算數表示式:
1 + 2 * 3 / x
只有使用函式呼叫,因為像前一節一樣,該式等價於
(1).+(((2).*(3))./(x))
這也表示著 `+`、`*` 之類的在Scala裡是合法的識別符號。
因為Scala的詞法分析器對於符號採用最長匹配,在第二版的表示式當中,那些括號是
必要的。也就是說分析器會把這個表示式:
1.+(2)
拆成 `1.`、`+`、`2` 這三個符號。會這樣拆分是因為 `1.` 既是合法匹配同時又比
`1` 長。 `1.` 會被解釋成文字 `1.0`,使得他被視為 `Double` 而不是 `Int`。把
表示式寫成:
(1).+(2)
可以避免 `1` 被解釋成 `Double`。
### 函式是物件
可能令Java程式員更為驚訝的會是,Scala中函式也是物件。因此,將函式當做引數傳
遞、把它們存入變數、從其他函式返回函式都是可能的。能夠像操作變數一樣的操作
函式這點是*函數編程*這一非常有趣的程設典範的基石之一。
為何把函式當做變數一樣的操作會很有用呢,讓我們考慮一個定時函式,它的功能是
每秒執行一些動作。我們要怎麼將這動作傳給它?最直接的便是將這動作視為函式傳
入。應該有不少的程式員對這種簡單傳遞函式的行為很熟悉:通常在使用者介面相關
的程式上,用以註冊一些當事件發生時被呼叫的回呼函式。
在接下來的程式中,定時函式叫做 `oncePerSecond` ,它接受一個回呼函式做參數。
該函式的型別被寫作 `() => Unit` ,這個型別便是所有無引數且無返回值的函式的
型別( `Unit` 這個型別就像是C/C++的 `void` )。此程式的主函式只是呼叫定時函式
並帶入回呼函式,回呼函式輸出一句話到終端上。也就是說這個程式會不斷的每秒輸
出一次"time flies like an arrow"。
object Timer {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}
def timeFlies() {
println("time flies like an arrow...")
}
def main(args: Array[String]) {
oncePerSecond(timeFlies)
}
}
值得注意的是,這邊輸出的時候我們使用Scala的函式 `println`,而不是
`System.out` 裡的函式。
#### 匿名函式
這程式還有改進的空間。第一點,函式 `timeFlies` 只是為了能夠被傳遞進
`oncePerSecond` 而定義的。賦予一個只被使用一次的函式名字似乎是沒有必要的,
最好能夠在傳入 `oncePerSecond` 時構造出這個函式。Scala可以藉由*匿名函式*來
達到這點。利用匿名函式的改進版本程式如下:
object TimerAnonymous {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}
def main(args: Array[String]) {
oncePerSecond(() =>
println("time flies like an arrow..."))
}
}
這例子中的右箭頭 `=>` 告訴我們有一個匿名函式,右箭頭將函式引數跟函式內容分
開。這個例子中,在箭頭左邊那組空的括號告訴我們引數列是空的。函式內容則是跟
先前的 `timeFlies` 裡一樣。
## 類別
之前已講過,Scala是一個物件導向語言,因此它有著類別的概念。(更精確的說,的
確有一些物件導向語言沒有類別的概念,但是Scala不是這類)。Scala宣告類別的語法
跟Java很接近。一個重要的差別是,Scala的類別可以有參數。這邊用底下複數的定義
來展示:
class Complex(real: Double, imaginary: Double) {
def re() = real
def im() = imaginary
}
這個複數類別接受兩個參數,分別為實跟虛部。在創造 `Complex` 的實體時,必須傳
入這些參數: `new Complex(1.5, 2.3)`。這個類別有兩個函式分別叫做 `re` 跟
`im` 讓我們取得這兩個部分。
值得注意的是,這兩個函式的回傳值並沒有被明確的給定。編譯器將會自動的推斷,
它會查看這些函式的右側並推導出這兩個函式都會回傳型別為 `Double` 的值。
編譯器並不一定每次都能夠推斷出型別,而且很不幸的是我們並沒有簡單的規則分辨
哪種情況能推斷,哪種情況不能。因為當編譯器無法推斷未明確給定的型別時它會回
報錯誤,實務上這通常不是問題。Scala的初學者在遇到那些看起來很簡單就能推導出
型別的情況時,應該嘗試著忽略型別宣告並看看編譯器是不是也覺得可以推斷。多嘗
試幾次之後程式員應該能夠體會到何時忽略型別、何時該明確指定。
### 無引數函式
函式 `re`、`im` 有個小問題,為了呼叫函式,我們必須在函式名稱後面加上一對空
括號,如這個例子:
object ComplexNumbers {
def main(args: Array[String]) {
val c = new Complex(1.2, 3.4)
println("imaginary part: " + c.im())
}
}
最好能夠在不需要加括號的情況下取得實虛部,這樣便像是在取資料欄。Scala完全可
以做到這件事,需要的只是在定義函式的時候*不要定義引數*。這種函式跟零引數函
式是不一樣的,不論是定義或是呼叫,它們都沒有括號跟在名字後面。我們的
`Complex` 可以改寫成:
class Complex(real: Double, imaginary: Double) {
def re = real
def im = imaginary
}
### 繼承與覆寫
Scala中所有的類別都繼承自一個母類別。像前一節的 `Complex` 這種沒有指定的例
子,Scala會暗中使用 `scala.AnyRef`。
Scala中可以覆寫繼承自母類別的函式。但是為了避免意外的覆寫,必須加上
`override` 修飾字來明確表示要覆寫函式。我們以覆寫 `Complex` 類別中來自
`Object` 的 `toString` 作為範例。
class Complex(real: Double, imaginary: Double) {
def re = real
def im = imaginary
override def toString() =
"" + re + (if (im < 0) "" else "+") + im + "i"
}
## Case Class跟模式匹配(pattern matching)
樹是常見的資料結構。如:解譯器跟編譯器內部常見的表示程式方式便是樹;XML文件
是樹;還有一些容器是根基於樹,如紅黑樹。
接下來我們會藉由一個小型計算機程式來看看Scala是如何呈現並操作樹。這個程式的
功能將會是足以操作簡單、僅含有整數、常數、變數跟加法的算術式。`1+2` 跟
`(x+x)+(7+y)`為兩個例子。
我們得先決定這種表示式的表示法。最自然表示法便是樹,其中節點是操作、葉點是
值。
Java中我們會將這個樹用一個抽象母類別表示,然後每種節點跟葉點分別有各自的實
際類別。在函數邊程裡會用代數資料類型。Scala則是提供了介於兩者之間的
*case class*。將它運用在這邊會是如下:
abstract class Tree
case class Sum(l: Tree, r: Tree) extends Tree
case class Var(n: String) extends Tree
case class Const(v: Int) extends Tree
`Sum`、`Var`、`Const` 類別定義成case class代表著它們跟一般類別有所差別:
- 在創建類別實體時不需要用 `new`(也就是說我們可以寫 `Const(5)`,而不是
`new Const(5)`)。
- 對應所有的建構式參數,Scala會自動定義對應的取值函式(即,對於 `Const` 類別
的實體,我們可以直接用 `c.v` 來取得建構式中的 `v` 參數)。
- `equals` 跟 `hashCode` 會有預設的定義。該定義會根據實體的*結構*而不是個別
實體的識別來運作。
- `toString` 會有預設的定義。會印出"原始型態"(即,`x+1` 的樹會被印成
`Sum(Var(x),Const(1))`)。
- 這些類別的實體可以藉由*模式匹配*來拆解。
現在我們有了算術表示式的資料型別,可以開始定義各種運算。我們將從一個可以在
*環境*內對運算式求值的函式起頭。環境的用處是賦值給變數。舉例來說,運算式
`x+1` 在一個將 `x` 賦與 `5` 的環境(寫作 `{ x -> 5 }` )下求值會得到 `6`。
因此我們需要一個表示環境的方法。當然我們可以用一些像是雜湊表的關連性資料結
構,但是我們也可以直接用函式!環境就只是一個將值對應到(變數)名稱的函式。之
前提到的環境 `{ x -> 5 }` 在Scala中可以簡單的寫作:
{ case "x" => 5 }
這串符號定義了一個當輸入是字串 `"x"` 的時候回傳整數 `5`,其他輸入則是用例外
表示失敗的函式。
開始實作之前,讓我們先給環境型別一個名字。當然,我們可以直接用
`String => Int`,但是給這型別名字可以讓我們簡化程式,而且在未來要改動的時
候較為簡便。在Scala我們是這樣表示這件事:
type Environment = String => Int
於是型別 `Environment` 便可以當做輸入 `String` 回傳 `Int` 函式的型別的代名。
現在我們可以給出求值函式的實作。概念上非常的簡單:兩個表示式和的值是兩個表
示式值的和;變數的值直接從環境取值;常數的值就是常數本身。表示這些在Scala裡
並不困難:
def eval(t: Tree, env: Environment): Int = t match {
case Sum(l, r) => eval(l, env) + eval(r, env)
case Var(n) => env(n)
case Const(v) => v
}
這個求值函式藉由對樹 `t` 做*模式匹配*來求值。上述實作的意思應該從直觀上便很
明確:
1. 首先檢查樹 `t` 是否為 `Sum`,如果是的話將左/右側子樹綁定到新變數 `l`/`r`
,然後再對箭頭後方的表示式求值;這一個表示式可以使用(而且這邊也用到)根據
箭頭左側模式所綁定的變數,也就是 `l` 跟 `r`,
2. 如果第一個檢查失敗,也就是說樹不是 `Sum`,接下來檢查 `t` 是否為 `Var`,
如果是的話將 `Var` 所帶的名稱綁定到變數 `n` 並求值右側的表示式,
3. 如果第二個檢查也失敗,表示樹不是 `Sum` 也不是 `Var`,那便檢查是不是
`Const`,如果是的話將 `Const` 所帶的名稱綁定到變數 `v` 並求值右側的表
示式,
4. 最後,如果全部的檢查都失敗,會丟出例外表示匹配失敗;這只會在有更多
`Tree` 的子類別的情況下發生。
如上,模式匹配基本上就是嘗試將一個值對一系列的模式做匹配,並在一個模式成功
的匹配時抽取並命名該值的各部分,最後對一些程式碼求值,而這些程式碼通常會利
用被命名到的部位。
一個經驗豐富的物件導向程式員也許會疑惑為何我們不將 `eval` 定義成 `Tree` 類
別跟子類的*函式*。由於Scala允許在case class中跟一般的類別一樣定義函式,事實
上我們可以這樣做。要用模式匹配或是函式只是品味的問題,但是這會對擴充性有重
要的影響。
- 當使用函式的時候,只要定義新的 `Tree` 子類便新增新的節點,相當的容易。另
一方面,增加新的操作需要修改所有的子類,很麻煩。
- 當使用模式匹配的時候情況則反過來:增加新節點需要修改所有對樹做模式匹配的
函式將新節點納入考慮;增加新的操作則很簡單,定義新的函式就好。
讓我們定義新的操作以更進一步的探討模式匹配:對符號求導數。讀者們可能還記得
這個操作的規則:
1. 和的導數是導數的和
2. 如果是對變數 `v` 取導數,變數 `v` 的導數是1,不然就是0
3. 常數的導數是0
這些規則幾乎可以從字面上直接翻成Scala程式碼:
def derive(t: Tree, v: String): Tree = t match {
case Sum(l, r) => Sum(derive(l, v), derive(r, v))
case Var(n) if (v == n) => Const(1)
case _ => Const(0)
}
這個函式引入兩個關於模式匹配的新觀念。首先,變數的 `case` 運算式有一個
*看守*,也就是 `if` 關鍵字之後的表示式。除非表示式求值為真,不然這個看守會
讓匹配直接失敗。在這邊是用來確定我們只在取導數變數跟被取導數變數名稱相同時
才回傳常數 `1`。第二個新特徵是可以匹配任何值的*萬用字元* `_`。
我們還沒有探討完模式匹配的全部功能,不過為了讓這份文件保持簡短,先就此打住
。我們還是希望能看到這兩個函式在真正的範例如何作用。因此讓我們寫一個簡單的
`main` 函數,對表示式 `(x+x)+(7+y)` 做一些操作:先在環境
`{ x -> 5, y -> 7 }` 下計算結果,然後在對 `x` 接著對 `y` 取導數。
def main(args: Array[String]) {
val exp: Tree = Sum(Sum(Var("x"),Var("x")),Sum(Const(7),Var("y")))
val env: Environment = { case "x" => 5 case "y" => 7 }
println("Expression: " + exp)
println("Evaluation with x=5, y=7: " + eval(exp, env))
println("Derivative relative to x:\n " + derive(exp, "x"))
println("Derivative relative to y:\n " + derive(exp, "y"))
}
執行這程式,得到預期的輸出:
Expression: Sum(Sum(Var(x),Var(x)),Sum(Const(7),Var(y)))
Evaluation with x=5, y=7: 24
Derivative relative to x:
Sum(Sum(Const(1),Const(1)),Sum(Const(0),Const(0)))
Derivative relative to y:
Sum(Sum(Const(0),Const(0)),Sum(Const(0),Const(1)))
研究這輸出我們可以發現,取導數的結果應該在輸出前更進一步的化簡。用模式匹配
實作一個基本的化簡函數是一個很有趣(但是意外的棘手)的問題,在這邊留給讀者當
練習。
## 特質(Traits)
除了由母類別繼承行為以外,Scala類別還可以從一或多個*特質*導入。
對一個Java程式員最簡單去理解特質的方式應該是視他們為帶有實作的介面。在Scala
裡,當一個類別繼承特質時,他實作了該特質的介面並繼承所有特質帶有的功能。
為了理解特質的用處,讓我們看一個經典範例:有序物件。大部分的情況下,一個類
別所產生出來的物件之間可以互相比較大小是很有用的,如排序他們。在Java裡可比
較大小的物件實作 `Comparable` 介面。在Scala中藉由定義等價於 `Comparable`
的特質 `Ord`,我們可以做的比Java稍微好一點。
當在比較物件的大小時,有六個有用且不同的謂詞(predicate):小於、小於等於、等
於、不等於、大於等於、大於。但是把六個全部都實作很煩,尤其是當其中有四個可
以用剩下兩個表示的時候。也就是說,(舉例來說)只要有等於跟小於謂詞,我們就可
以表示其他四個。在Scala中這些觀察可以很漂亮的用下面的特質宣告呈現:
trait Ord {
def < (that: Any): Boolean
def <=(that: Any): Boolean = (this < that) || (this == that)
def > (that: Any): Boolean = !(this <= that)
def >=(that: Any): Boolean = !(this < that)
}
這份定義同時創造了一個叫做 `Ord` 的新型別,跟Java的 `Comparable` 介面有著同
樣的定位,且給了一份以第一個抽象謂詞表示剩下三個謂詞的預設實作。因為所有的
物件預設都有一份等於跟不等於的謂詞,這邊便沒有定義。
上面使用了一個 `Any` 型別,在Scalla中這個型別是所有其他型別的母型別。因為它
同時也是基本型別如 `Int`、`Float`的母型別,可以將其視為更為一般化的Java
`Object` 型別。
因此只要定義測試相等性跟劣性的謂詞,並且加入 `Ord`,就可以讓一個類別的物件
們互相比較大小。讓我們實作一個表示陽曆日期的 `Date` 類別來做為例子。這種日
期是由日、月、年組成,我們將用整數來表示這三個資料。因此我們可以定義 `Date`
類別為:
class Date(y: Int, m: Int, d: Int) extends Ord {
def year = y
def month = m
def day = d
override def toString(): String = year + "-" + month + "-" + day
這邊要注意的是宣告在類別名稱跟參數之後的 `extends Ord`。這個語法宣告了
`Date` 繼承 `Ord` 特質。
然後我們重新定義來自 `Object` 的 `equals` 函式好讓這個類別可以正確的根據每
個資料欄來比較日期。因為在Java中 `equals` 預設實作是直接比較實際物件本身,
並不能在這邊用。於是我們有下面的實作:
override def equals(that: Any): Boolean =
that.isInstanceOf[Date] && {
val o = that.asInstanceOf[Date]
o.day == day && o.month == month && o.year == year
}
這個函式使用了預定義函式 `isInstanceOf` 跟 `asInstanceOf`。`isInstanceOf`
對應到Java的 `instanceof` 運算子,只在當使用它的物件的型別跟給定型別一樣時
傳回真。 `asInstanceOf` 對應到Java的轉型運算子,如果物件是給定型別的實體,
該物件就會被視為給定型別,不然就會丟出 `ClassCastException` 。
最後我們需要定義測試劣性的謂詞如下。
def <(that: Any): Boolean = {
if (!that.isInstanceOf[Date])
error("cannot compare " + that + " and a Date")
val o = that.asInstanceOf[Date]
(year < o.year) ||
(year == o.year && (month < o.month ||
(month == o.month && day < o.day)))
}
這邊使用了另外一個預定義函式 `error`,它會丟出帶著給定錯誤訊息的例外。這便
完成了 `Date` 類別。這個類別的實體可被視為日期或是可比較物件。而且他們通通
都定義了之前所提到的六個比較謂詞: `equals`跟`<` 直接出現在類別定義當中,其
他的則是繼承自 `Ord` 特質。
特質在其他場合也有用,不過詳細的探討它們的用途並不在本文件目標內。
## 泛型
在這份教學裡,我們最後要探討的Scala特性是泛型。Java程式員應該相當的清楚在
Java 1.5之前缺乏泛型所導致的問題。
泛型指的是能夠將型別也作為程式參數的功能。舉例來說,當程式員在為鏈結串列寫
函式庫的時候,他必須決定串列的元素型別為何。由於這串列是要在許多不同的場合
使用,不可能決定串列的元素型別為如 `Int` 一類。這樣限制太多。
Java程式員採用所有物件的母類別 `Object`。這個解決辦法並不理想,一方面這並不
能用在基礎型別(`int`、`long`、`float`之類),再來這表示必須靠程式員手動加入
大量的動態轉型。
Scala藉由可定義泛型類別(跟函式)來解決這問題。讓我們藉由最簡單的類別容器來檢
視這點:參照,它可以是空的或者指向某型別的物件。
class Reference[T] {
private var contents: T = _
def set(value: T) { contents = value }
def get: T = contents
}
類別 `Reference` 帶有一個型別參數 `T`,這個參數會是容器內元素的型別。此型別
被用做 `contents` 變數的型別、 `set` 函式的引數型別、 `get` 函式的回傳型別。
上面的程式碼使用的Scala的變數語法,應該不需要過多的解釋。值得注意的是賦與該
變數的初始值是 `_`,該語法表示預設值。數值型別的預設值是0,`Boolea8n` 型別
是偽, `Unit` 型別是 `()` ,所有的物件型別是 `null`。
為了使用 `Reference` 類型,我們必須指定 `T`,也就是這容器所包容的元素型別。
舉例來說,創造並使用該容器來容納整數,我們可以這樣寫:
object IntegerReference {
def main(args: Array[String]) {
val cell = new Reference[Int]
cell.set(13)
println("Reference contains the half of " + (cell.get * 2))
}
}
如例子中所展現,並不需要先將 `get` 函式所回傳的值轉型便能當做整數使用。同時
因為被宣告為儲存整數,也不可能存除了整數以外的東西到這一個容器中。
## 結語
本文件對Scala語言做了快速的概覽並呈現一些基本的例子。對Scala有更多興趣的讀
者可以閱讀有更多進階範例的 *Scala By Example*,並在需要的時候參閱
*Scala Language Specification*。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 211.72.92.133
... <看更多>