2015年11月18日 星期三

以大三的角度看研究所這回事

關於升研究所這問題也討論到爛了,「我該不該念研究所」還有「念研究所對工作的幫助」這兩題,以台灣的環境來看要好薪水就該念研究所,而且念研究所會培養邏輯思考、思維辯證、文筆寫作等能力,很明顯地對工作一定會有幫助。

所以我想從另一個角度來看,對一個進大學的新鮮人,研究所對他的意義是什麼?大學生活對他之後升研究所會有什麼關聯?這篇文章會先舉大學生大一大二的生活寫照,之後帶到升研究所這回事,之後再談論台灣的就業環境是如何看待碩士生和大學生,並以我目前是大三生的角度來看待這議題,提出相關問題後再告訴大家結論。

案例一:
大學生A進入某國立大學後,生性活潑參與許多社團、活動,吃宵夜、夜唱、打LOL、夜衝都經歷過,大一過後成績普普,班上六十名排名40,沒有被當。

到了大二任職社團幹部,要籌畫活動、社團發表,也加入學生會,參與學校事務。可是大二課更重,被當了兩科主科,通識也掛了一科。有時候活動太忙就翹課,或是因為太累而上課在睡覺,之後成績掉到50名左右

不過因為他頗認真在經營活動,認識很多人,在學校小有名氣。後來大三後還是在跑活動,但是數量減少,成為半退休狀態。每天的生活就是上課、偶爾去跑跑活動。書開始唸得比較多,大三後成績班排維持在40-50

案例二:
大學生B進入同樣國立大學,延續之前高中的生活,很認真唸書,沒有像A參加社團,頂多就是去系上辦的活動,生活規律,不吃宵夜,也不去夜衝等比較會影響睡眠的活動。大一後成績班排第三。

大二時一樣延續大一的生活,生活規律,也很認真唸書,還會幫同學解答課業題目。大二過後班排二

大三時跟大二差不多,生活照常,學期過後班排第三。整體來說,是個很認真的學生,不過對於修課以外的事物比較沒興趣。

這時(兩位都是大三)A同學在臉書上發文:「明天就要期中考啊~兩百頁的課本還沒念,之後還要補修微積分嗚嗚~~是說後天還要去其他社團分享當主席的經驗>< 喔好懷念之前一起邊跑活動邊唸書的日子」。

B同學在臉書上發文:「嗚嗚上次只拿了85分,這次要好好準備,看之後班排能不能更好哈哈~」

對於A同學,可以想得到的是很多人給予安慰,並且祝他考試順利,然後說成績可以再加油就好;對於B同學,可以想得到的是會有人開玩笑地嗆他,或是說哇好厲害喔,但是可能會有酸人的口吻。

兩種生活寫照都會有人贊同,可是第一種能獲得較多關注是因為
  1. A同學認識很多人
  2. 我們傾向給予人安慰,尤其時看到別人出現困難時
換言之,我們可能認同跑很多活動但是成績顧不好是可容許的,可是當要你認同「一個人認真努力唸書」就會覺得他就很會唸書,兩邊的觀感就不太一樣。

之後在準備研究所時,A同學因為成績不好而放棄了推研究所的念頭,B同學則因成績好順利推上知名國立大學的研究所

我們都知道,現今研究所推甄不外乎就是看「從哪間大學畢業、在校的成績、在校排名、比賽經驗、特殊經歷」等,可是很多時候反而都是看中成績(之前跟系上許多教授提到是這樣)

而在台灣的產業界,假設是資訊、理工科系的出路,尤其是以大公司來說,因為履歷眾多,通常非台清交成的就都不看了(因為舉理工科系,所以先省略政大),而這些大公司又希望你有豐富的經驗,最好要能和產業結合,或是你有豐富的人脈、溝通技巧等,才比較受到青睞。

整理一下,我們目前有學生、研究所教授、產業界的三種視角:
  1. 學生:讀大學是一種探索的旅程,每一種選擇都是寶貴的經驗,也造就了往後的自己
  2. 研究所教授:你要讀好的研究所就要有好的成績
  3. 產業界:我要知名研所的碩士生,並希望會團隊合作、善於溝通、樂於學習、有豐富實作經驗
換言之,假設你今天要有好工作應該會希望有好的研究所學歷(通常指第一份工作),而要有好的學歷就是要有好成績,可是產業界又希望你有「除了課業以外的經驗」,變成你需要在大學「不僅要成績好,又要去參加活動(假設參加活動能獲得團隊合作、溝通的經驗)」,無形之下希望學生要全能實在是有難度,畢竟那是少數,學生要嘛就是很會唸書,這就可以走研究路線,要嘛就是知道如何帶活動、團隊合作或是帶團隊,這就很適合專案管理、行銷、公關、公司管理階層。

可是在目前環境下,學士生和碩士生多半會先選擇碩士生,尤其是大公司的人資會收到很多履歷,時間不夠下很難一一看完,當然會先挑選碩士生,而且盡量以國立大學為優先,可是這樣就造成一些大學時某方面很厲害但成績卻不佳的人的曝光度低落,仔細想想後可以採用以下方式:
  1. 改善課程,把產業界的問題當作學生的課程專題,並適時地融入小組討論、報告,並且要求學生實作出來,模擬產業界的情況
  2. 以實作取代看學歷。以資訊產業為例,在投履歷後,都給求職者程式題目,並且要求在一定時間內寫完,甚至可以用電腦來檢驗程式效率。以此為基準,有好的學歷再做加分。
也就是說,今天學生B很會唸書,可以靠好學歷進公司;學生A雖然成績普普,但是有其他額外表現也有機會進去公司,然後學生B可以做理論研發等,學生A則進入管理或是行銷、人力相關部門,讓每人各司其職,以發揮所長。

到後來還是覺得,大家會有種放不開的感覺。企業會認為學歷就是好的選才標準,然後研究所的選才就是看成績,因此變成大家都追求成績,某方面上造成實作程度低落,出來反而被企業抨擊。這時候我也覺得乖乖唸書的學生沒錯,他們很認真地按照遊戲規則玩,怎麼到後來沒做錯事就被踢出去了?而那些認真實作的人卻在一開始就被研究所踢出去。

所以,若真要產出對應產業界的人才,真的很需要產學合作,諸如德國,不設立許多大學,反而培養許多技職生去產業合作。

可是現在廣設大學後已經很難走回頭路,家長們也認為讀大學就是好工作的保證,問題是有好大學不一定有好工作,有好工作不一定代表你找到了人生的意義和價值。今天假若大家都認為我就看你的專長來雇用你,那學歷也只是第一份工作的門票,大家還是會看你真正的實力。

可是現在變成我大學念完,就要念研究所,研究所念完就要去當兵、找工作,之後買房買車,似乎這就是人一生該走的路。為何一定要接受同樣的人生道路呢?在歐美也沒那麼在意你有沒有唸大學,反而在意你的特色、價值(不過現在他們的高等教育普及率也愈來愈高),之後還是可以回來補學歷。

找到自己的核心價值和天分,並且用心地挖掘它,我想這才是教育的目的吧。

2015年9月10日 星期四

軟體工程書摘與心得 Part 2:物件導向軟體工程之另類思考

延續上篇,當我們有完整的需求分析後,接下來就是要實作程式碼。這部分我跳過很多,直接把我認為重要的拿出來。當類別圖畫好後,接下來就是要畫出序列圖(Sequence Diagram),之後對使用者案例進行健全性分析,最後連接上對於該程式的領域模型,之後軟體內類別和類別的關係大抵上就確定了。

物件導向的另類思考流程圖
至於什麼是序列圖?就是在一個動作中,列出參與該動作的物件,隨著動作進行時,找出物件和物件之間的交互子動作,直接看例子:

Sequence_diagram_for_handling_a_browser_request_using_the_Model_View_Controller_MVC_pattern

上圖中顯示要「處理來自瀏覽器的請求」時,所需要做的動作和參與的對象,隨著動作開始進行,首先Browser會發出HTTP GET Request()給Tomcat,之後就持續做一連串的動作,直到整個流程被完成。序列圖的好處是(1)知道參與者有哪些,(2)子動作其實會對應到所實作的函數,能很直覺地反映出程式該怎麼寫。

另外還有一個是健全性分析(Robust Analysis),他是把「分析的模型轉換成設計的模型」。依據使用案例模型,輸入使用案例、使用案例的情況(Scenarios)、使用案例對應的活動圖(Activity Digram),以及領域模型,輸出成以UML表示的合作圖(Collaboration Diagram)來記載,裏頭會有3種主要的設計成員:
  1. 邊界物件(Boundary Objects):用來描述系統與角色之間的互動
  2. 實體物件(Entity Objects):用來描述系統中經常存在的資訊(Persistent Information)
  3. 控制物件(Control Objects):用來描述對於其他物件的控制、安排,或是協調
使用健全性分析是幫助釐清目前定義的類別是否足夠、角色定義是否明確,可能在進行健全性分析的過程中會發現更多的物件或是新的屬性類別,然後用來重新繪製序列圖,所以序列圖的建立不是一次就完成的,是需要經過多次迭代的。

我覺得最厲害的還是序列圖,他可以直接讓我知道怎麼寫程式,同時又能了解物件的互動,真的很值得學習。

下一篇要介紹當軟體完成時怎麼做系統組態的管理與維護,如何讓軟體能適時地反映使用者的成長


2015年9月9日 星期三

軟體工程書摘與心得 Part 1:為何需要軟體工程&軟體工程之簡介

最近閒來無事去看了Livecoding.tv上程式設計師表演打code,就覺得怪了為何你腦袋能源源不絕想出接下來要做什麼,從這頁面又跳到下個頁面,雖然我也能看懂你在做啥,可是自己就不一定能這樣行雲流水般地打code(苦笑)。後來想想應該是我缺乏軟體工程上的訓練。

不然別人是怎麼會想說這邊要用這個protocol?下一個地方要用這個函數銜接?在軟體工程中我從這本書找到了答案:

根據書中解釋,1960年代末期由北約召集科學家探討「軟體危機」的問題,討論如何有更好的軟體開發方法來提升開發的效率、節省開發成本,同時獲得良好的軟體系統品質,因而催生了軟體工程的發展。對我來說寫軟體就如同建造房子,從畫藍圖、打樑樁等都有一套步驟和分析的方法,都需要投入大量的精力來完成。

而這也是會和有些人能把程式寫得穩健、可靠、可擴充,就是有進行完整的系統分析、需求了解、介面設計等才能達到一定品質。隨著軟體漸趨複雜,光是作業系統就可高達上千萬行程式碼,如何做好軟體開發就需要系統工程的幫忙,並借助軟體系統開發方法論,然後選擇軟體開發程序:

  1. 傳統階梯式的軟體開發程序:做好需求分析後,設計系統與軟體的架構,之後進行系統製作與局部測試,最後整合測試後就可上線使用還有維護
  2. 漸進式的軟體開發:透過需求分析後快速產生原型,之後陸續迭代產生新產品
  3. 需求規格化的軟體開發程序:將軟體系統的規格以數學模型來表示,之後自動轉成程式碼
  4. 組合式的軟體開發程序:分別完成系統內的各個元件,之後再組合起來
而隨著物件導向的盛行,也陸續產生新的開發方法(其實也很久的東西了):
  1. RUP (Rational Unified Process):結合螺旋式、反覆式及漸進式的開發方法,主要分成「開始階段」、「細化階段」、「建置階段」、「轉換階段」四種
  2. 敏捷開發:像是XP(Extreme Programming)、Scrum等
方法演進後手上的工具也不能輸人啊!因此就有電腦輔助軟體工具(CASE, Computer-Aided Software Engineering)的出現,早期CASE工具出現時人們的期望很高,認為可以大幅下降軟體開發成本,但當時的CASE工具並不成熟,沈寂了一段時間後大家才開始陸續使用,大家常用的IDE就是一個典型例子。

仔細回想起來,目前有很多火紅程式教學的網站,大家都用得開心,可是真的要開發一套系統就只能坐在電腦前打不出任何東西,一部分可能是程式技巧不足,另一部分就可能是缺乏軟體工程的訓練。當了解軟體工程時,就能超越一般的程式設計師成為軟體工程師,就像是從一位工人進化到建築師,從只會寫程式變成能洞悉大局、了解如何規劃與參與軟體開發的各個階段的「高級程序員(猿)」。

下一篇將會介紹軟體系統的需求工程,如何找到需求並把需求轉成軟體架構、規格就需要這篇啦~

2015年9月2日 星期三

iOS Push/Local Notification之原理

這次來介紹一下如何使用iOS上的Push Notification,舉凡Facebook上的訊息、Gmail的郵件通知都是此類。而首先就是要知道Notification有分成Local和Push兩種,前者像是行事曆的定時通知,後者就是前面講的。Local的通知好處理,可以指定日期和時間來通知:
 NSCalendar * calendar = [NSCalendar autoupdatingCurrentCalendar];

NSDateComponents * dateComponent = [NSDateComponents alloc] init];

[dateComponent setDay: item.day];  // item: self defined object

[dateComponent setMonth: item.month];

[dateComponent setYear: item.year];

[dateComponent setHour: item.hour];

[dateComponent setMinute: item.minute];

NSDate * date = [calendar dateFromComponents: dateComponent];



 UILocalNotification *localNotif = [[UILocalNotification alloc] init];

 if (localNotif == nil)

    return;

localNotif.fireDate =

[date
  dateByAddingTimeIntervalInterval:-(minutesBefore*60)];

 localNotif.timeZone = [NSTimeZone defaultTimeZone];

 localNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"%@ in
  %i minutes.", nil),
           item.eventName, minutesBefore];



localNotif.alertAction = NSLocalizedString(@"View Details", nil);

localNotif.alerttitle = NSLocalizedString(@"Item Due", nil);

localNotif.soundName = UILocalNotificationDefaultSoundName;
      localNotif.applicationIconBadgeNumber = 1;

NSDictionary *infoDict = [NSDictionary dictionaryWithObject:item.eventName
  forKey:ToDoItemKey];

localNotif.userInfo = infoDict;

[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];

那麼要設定Push Notification要怎麼做?首先要用Apple的Push Notification機制(簡稱APN),自己的Server發出通知後會傳到Apple的Server,之後再從Apple傳給使用者的App:


我覺得這樣做的原因是要保持通知的完整性和安全性,假如說你傳送有惡意訊息的封包給使用者豈不是不好?而建立整個連線流程如下圖所示,裝置先和APN建立TLS(Transport Layer Security)連線,之後取得憑證後TLS就算建立完成:

而Provider也是同樣要建立TLS連線和取得憑證:

而當憑證建立完成後App和APN, Provider的互動就是靠Token來完成,App若要使用Push Notificaition必須先行註冊至APN(從使用者那邊獲取通知許可),然後APN再回傳加密過的Token給Provider,之後該Token再從Device回傳到Provider,如下圖所示:
而在傳送Push Notification時會連同Token,並藉由裝置ID來回傳加密的通知內容給裝置:

到這邊整個Push Notification就算完成,接下來就是在AppDelegate.m加上程式碼:

// Remote notifications
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    NSLog(@"Receive deviceToken: %@", deviceToken);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    NSLog(@"Remote notification error: %@", error.localizedDescription);
}
另外當收到了Notification後要做什麼事就先靠didReceiveRemoteNotification來完成,而handleActionWithIdentifier則是當使用者對Notification做出回應後你要採取什麼動作時,可用completionHandler的block來完成:

// When app is waked up, this method will be called
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
    // with push notification from remote server
    // When app is running in the foreground, this method will be called
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler{
    // Test for identifier with a sample indentifier
    if ([identifier isEqualToString:@"ACCEPT_IDENTIFIER"]) {
        [self handleAcceptActionWithNotification:userInfo];
    }
}
以上就是整個流程,至於說要註冊憑證的方法可參考這篇:popcorny的碎碎念

2015年8月31日 星期一

NSOperation及NSOperationQueue與GCD之比較

之前上Stanford iOS 7的課程時有介紹到GCD(Grand Central Dispatch),是一種比較低階的函數,讓code可以在不同的thread中跑。可是假如說我今天要檢查該thread的運作情況,好比說他的優先順序、是否還在運行等,這時候GCD能提供的設定就比較少,於是就需要NSOperation和NSOperationQueue啦~

在Mac OS X 10.6之前,NSOperation跟GCD是採用不同的運作模式,10.6之後NSOperation就改成運作在GCD之上了,換言之他是比較高階的API,但是同時也保有GCD的效能。使用NSOperation時有以下步驟:

  1. 繼承自NSOperation
  2. 覆寫main()
  3. 在main中建立autorelease pool(自動釋放池)
  4. 把code放到autorelease pool中
  5. 針對需求,在外部檢查isCancelled等屬性
至於NSOperation中有以下method:
  1. start:呼叫該函數來執行該operation,但如果沒有特別指定去哪個queue時將會在main queue執行,要特別注意
  2. dependency:可以設定兩個operation的相依性來設定先後順序。舉例來說我今天下載了一段音訊,要等下載完成後才能進行裁剪,GCD中的dispatch_barrier_async()有提供類似的功能
  3. priority:這點是我覺得比較有趣的地方,可針對特定的operation來設定setQueuePriority:,像是NSOperationQueuePriorityVeryLow
  4. completion block:當operation完成後可以在setCompletionBlock:^{}去做其他事情,好比說存檔等等
另外NSOperationQueue相較於NSOperation就更為簡單,僅需要alloc並init即可,之後可調用以下方法:
  1. concurrent operations:這點比較複雜,簡單來說一個queue可以有多個thread,而每個operation會分配到一個thread來執行。舉例來說我有一個queue,然後加入2個operations,這樣建立兩個thread對應到每個operation,所以我這個queue就會有兩個thread
  2. maximum number of concurrent operations:設定每個queue中最多只能有幾個operations來執行
  3. add operation:增加operation到queue,如果要釋放的用使用release方法
  4. pending operation:查詢在queue中有哪些operations。只有「待執行」和「正在執行」的operation才會在queue中。這部分可以用NSArray來保存operations,或是使用NSDictionary來查詢相關的operation
  5. pause(suspend)queue:就是停止queue
  6. cancel operation:如果說該operation尚未執行,呼叫cancel會把operation從queue中移除;如果是正在執行的operation,就要看該operation會不會去檢查isCancelled
  7. addOperationWithBlock:如果當你不想要有NSOperation的子類別卻又想要來queue中執行,就可在該方法中的block插入程式碼。這有點像GCD的block。不過要注意的是若要參考block外的物件,就必須傳入weak屬性的物件
最後綜合比較NSOperation和GCD,我覺得GCD比較簡單、直覺,但是可以操作的範圍不大(因為就是函數),可是其他物件可以繼承NSOperation,獲得了使用多線程的能力。所以我想當要操作物件時就用NSOperation,然後某些片段(下載等需求)就可以用GCD來解決。總之在iOS中多線程是個很重要的觀念,有這麼好用的功能就要好好用它啊~~

Protocol v.s. Delegate

最近剛好寫了一些跟NSOperation的東西,裡面用到許多的Protocol和Delegate,之前學到我們可以宣告一個Protocol,然後讓class去遵循它,可是那為何我們還需要有Delegate? Delegte不也是讓我們去遵循其中的方法來實作嗎?就像是我們在寫UITableView時都要有UITableViewDataSource和UITableViewDelegate來對資料和cell進行設定(因為View無法擁有自己的資料)。那麼兩個這麼像,Protocol和Delegate又有什麼差別呢?

答案是一定有差別的,不然你就不會一直看到這兩個名詞。先複習一下什麼事Protocol,假設當我宣告MyProtocol中有個aMethodInMyProtocol時,任何一個遵循MyProtocol就可調用該方法;另外也可讓實體變數遵循Protocol,譬如我的MyClass中有以下變數:

@property (nonatomic, strong) id  <myprotocol>  instanceThatImplementMyProtocol;

此時該instanceThatImplementMyProtocol就可調用MyProtocol的方法。此外宣告Protocol時也可再遵循其他Protocol,例如:

@protocol Foo
...
@end

只有當你實作了anotherProtocol後,然後你再實作Foo後你才可以說已經實作好該Foo Protocol。那麼在Delegate又是怎麼樣呢?

Delegate說起來是一種設計方法,全名叫做Delegation Design Pattern,Delegate要求遵循該delegation的class去實作Protocol的方法(可以說是一種「方法」),使得該class可以在特定時候使用該Protocol的method。對我來說,Protocol提供一個介面來讓大家共享裡面的方法,然後Delegate會讓用它的class去實現該方法,使用Delegate的好處是可以減弱耦合,達到共享的目的。

另外取自StackoverFlow的解答,我覺得看英文比較能懂:)
The class that uses the delegate knows that its delegate coforms to the protocol, so it knows that it can call the implemented methods at given times. 

2015年5月10日 星期日

The Pragmatic Programmer : from journeyman to master 書摘


我們,採集的只是石頭,卻必須時時刻刻展望未來的大教堂。
                                                                                                                —採石工人的信條

  1. 第一章:注重時效的哲學
    • 負責你的代碼,不要找蹩腳的藉口
    • 不要容忍破窗戶:有問題就及時修改,別累積技術債
    • 做團隊裡「做變化的催化劑」:提供大家改變的契機,讓大家追隨你而改變
    • 永遠記住大目標,要見樹並見林
    • 使質量成為需求問題:讓你的用戶參與權衡
    • 定期為你的知識資產做投資
    • 批判地分析你讀到的和聽到的
    • 你說什麼和你怎麼說同樣重要:交流、知道你要說什麼、瞭解聽眾、選擇文件的風格和美觀
  2. 第二章:注重實效的途徑
    • 不要重複你自己:和重用(Reuse)差別在,重複(Repeat)在於你做了同樣的事情,你應該只做一次卻做了很多次,造成時間和成本浪費;而重用則是再次利用優秀的程式碼來達到效率上的精進。
    • 讓重用變得容易(Make It Easy to Reuse)
    • 消除無關事物之間的影響:提升系統各組件的正交性(即降低耦合性)
      • 有正交性的好處:提高生產率、降低風險、項目團隊、設計
      • 編碼:讓代碼解藕、避免使用全域變數、避免相似的函數
    • 可撤銷性:不要存在最終決策,你的產品隨時隨地都有可能砍掉重練
    • 使用曳光彈來幫助你找到目標:和原型製作的差異在於曳光彈代碼是完整的,之後會構成最終系統的骨架的一部分
      • 用戶能及早看到能工作的東西
      • 開發者建構了一個他們能在其中工作的結構
      • 有了集成的平台
    • 為了學習而製作原型:原型所具備的元素有
      • 正確性
      • 完整性
      • 健壯性
      • 風格
    • 靠近問題領域編寫程式(Program Close to the Problem domain):選擇特定語言或是編寫特別定義過的程式來解決問題
    • 估算以免發生意外
      • 理解提問內容
      • 建立系統的模型
      • 把模型分解為組件
      • 給參數指定值
      • 估算項目進度
  3. 第三章:基本工具
    • 用純文本保存知識(Keep Knowledge in Plain Text)
    • 利用命列Shell的威力(Use the Power of Command Shells)
    • 用好一款編輯器:好的編輯器應該具有以下特性
      • 可配置:可高度客製化
      • 可擴展性
      • 可編程性
    • 總是使用原始碼控制工具
    • 要修正問題,而不是發出指責
    • 不要恐慌
      • 將你的數據視覺化
      • 跟蹤
      • 使用橡皮鴨:向別人解釋你的程式碼,讓別人像鴨子一樣一直點頭,直到問題出現
      • 消除過程
    • Select沒有問題
    • 不要假定,要證明
    • 學習一種文本操縱語言
    • 撰寫能撰寫程式碼的工具
  4. 第四章:注意時效的偏執
    • 你不可能寫出完美的軟體
    • 使用DBC按照合約設計:
      • 前條件
      • 後條件
      • 類別不變項
(未完.....)

2015年5月2日 星期六

數學思考(Think Mathematically) 筆記&閱讀心得

大二下過了這麼久,終於有時間好好讀一本書了。

這次借來的看的「數學思考」是由建中第49屆314班全體同學合譯後出版。其實會讀到這本書真的是因為大學的專業課程所需,像是統計、作業研究、電腦網路等,大部份都需要縝密的分析和邏輯能力,逐一抽絲剝繭後才能找到解決方案。既然想說自己不是讀書的料,那就只好強化數學能力,畢竟數學是所有學科的基礎嘛。

⟪筆記部分⟫

這本書主要提供了一套可依循的步驟來看待數學問題。作者引入了「要點思考」(Rubric Writing)這方法,主要步驟有:

  1. Stuck
  2. Aha!
  3. Check
  4. Reflect
第一個Stuck是指遇到困難,作者提到「遇到困難是件榮譽的事」,因為你可以從中發現到思維上的障礙和不足點,好比說我是不是「沒有搜集足夠的已知條件」、「我不確定我的所求」或是「所使用的工具不對」等等。另外在這階段時要多多使用「特殊化」和「一般化」的技巧,特殊化是指找出某個符合題目的例子,包含要找到特例,來輔以自己的想法;而一般化是問說「為什麼這樣做才是正確的」,就是確認自己的方法是否正確,之後能不能套用到類似性質的問題上。

第二個Aha!是指在解題時想到好點子就記錄下來,不管是靈光一閃或是經過縝密推論而得到結論,讓你很開心、愉悅,覺得離解答又更進一步的想法,都把它記錄下來,在往後的計算也可能再次用到。

第三個Check顧名思義就是檢查任何的計算或推理,你也可以用幾個例子檢查你所發現的法則(特殊化),最後再看看你的解法是否能解決原命題。

最後一個的Reflect是指想一下發生了什麼事。可以寫下重要的想法或是記憶中引人注目的時刻,然後確實地仔細思考在這一題中學到了什麼。

經過以上步驟就完成了要點寫作,再加上作者所提供的「進入」、「攻擊」、「回顧」,這張圖在解決數學問題上就顯得十分有用。

p.129 數學思考整體步驟

⟪心得⟫

這本書閱讀起來十分輕鬆,一個晚上就讀完了。看完後我第一個想法是:「假如我高中時代有看過這本書就好了。」從小時所接受的數學教育一直以來都是大量算題目、介紹很多工具和方法、熟練不同的解題技巧,到最後只要題目再有新的變化還是招架不住。我記得我高中有個老師每堂課就要我們背題目,尤其是矩陣那個章節更是要求。所以從教育來看,有兩個點很值得檢討:

1. 思考、辯駁、討論的訓練


台灣的數學教育一直很填鴨,課堂上我們總是希望老師教得愈多愈好,教更多解題技巧,學生做愈多題目愈好,可是卻常常缺乏討論的機會。近日才看到關於猶太人的教育相關文章,他們對於孩子放學後會問說:「你今天有沒有問了好問題?」而不是像台灣的家長問說:「今天考得如何?」「有學到什麼?」。愛因斯坦曾說想像力比知識重要,我把它解讀為「提出好問題比獲得知識更重要」因為提出問題時你要對該領域有一定了解,而且也代表你願意學習。

在我們的中小學教育中其實還蠻有這種練習的,讓學生發言、問問題,都是很好的機會。可是到了國高中,面臨升學考試壓力,這種討論的模式大量減少,問問題也傾向於很簡單的回答,非常可惜。

此外台灣人也很奇怪,就是會有菁英主義。菁英不是不好,可是大家總會希望說有個唸書高手出現,他總是自己唸書,然後硬是比別人高分,造就班上大家都自己念自己的,你要跟我討論課業門都沒有。可是假如你今天沒有外在幫助,缺乏討論和問問題,又怎能期待大家都變好呢?

2. 分析問題、深入思考的能力

從高中進入到大學後,教授開始用原文書上課。一方面是讓我們練英文整我們,另一方面是讓我們完整接觸洋人的想法和思考方式。可是台灣學生在這塊十分欠缺(對我就是其中一位),他們對於一個問題都可以有很完整的思考脈絡,就跟在數學思考裡面闡述的雷同,從已知慢慢推到未知,並且不注重於標準答案,而是自己的答案能不能說服他人。

在台灣考試考久了我們都希望出現那種十秒鐘就能解的題目,我們要求標準、快速的答案,所以才會有人覺得台灣都被標準答案綁死,導致我們長大後無法洞悉問題、提出有效且長遠的解決方案。

與其做大量訓練,不如給我們下一代有用的魚竿,教孩子如何思考,尤其是在數學這塊。



2015年4月6日 星期一

為了開發iOS App,要如何先學好Objective C? How to learn Objective-C well in order to develop iOS App?

這個寒假以來大概是我腦力消耗最多的時候了。自從學校的網頁設計課程教授網頁手機版設計後,我就打算改成iOS版,然後開始想買哪種Mac,後來在室友的幫助下買到一台二手但是狀況極佳的Macbook Pro,就這樣開始了學習Objective C的旅程。

而剛好買玩電腦前後,學校有了個做App的比賽,剛好就藉這機會報名參加。那時候剛好是期末考,要在期考時完成作品說明書也是很累人。他有分初審和決賽,結果初審只有格式不符的沒通過,對於自己的辛苦準備實在有點過意不去啊。

實際上也是到1/25之後才有時間學習,剛開始被MVC的觀念卡住,還有一些瑣碎的物件導向知識又會出來反咬我。所幸後來就慢慢克服。我使用的教材以Stanford CS193p Fall 2013-2014為主,查資料時使用"Programming in Objective-C Fifth Edition",對我來說這線上課程真的就有如在史丹佛上課一般,老師講得緊湊又有趣,非常推薦。

回歸正傳,要開發iOS App還是蠻建議從Objective-C開始,理由不外乎有:

  1. Objective-C現有的程式碼多,Stackoverflow上一堆相關問題回答
  2. Objective-C已經存在許久,穩定度經得起考驗
  3. 學會Objective-C轉換到Swift根本無痛轉移,只是有些微語法差異
學了一陣子後發現重要的還是基礎觀念,每次有Bug大概有一半以上都是基礎觀念在咬我。很多想說我這功能不知道怎麼寫、不知道有什麼函數可用,其實網路上很快就可以查到。StackoverflowApp Coda上就有很多可用的程式碼。可是你如果不知道函數要吃的參數型態、這邊該不該alloc、NSDictionary要怎麼用、MVC架構如何導入,那很快還是會卡住。

我個人蠻推薦高見龍大大在部落格上的說明,像是protocol、instancetype都介紹得很詳細。另外雖然說語法常常會讓人卡關,可是相對應的電腦科學背景也頗需要。像是我最近剛讓iOS去跟SQLite做query,一些資料庫背景知識有時候會跑出來咬我。

不過我相信只要有毅力,真的就會慢慢地把App做出來。加油!

2015年3月11日 星期三

跳脫舒適圈一直都是好事?

有人說,跳脫舒適圈,可以讓人成長,挑戰自己的極限,還能擴展視野,看到不一樣的東西。

現代產業強調跨出舒適圈,投入其他領域,找到不同的商機,甚至異業結盟都有可能,讓自己的專業無限擴展。換言之,窩在自己的舒適圈,一樣可以活得很好,但是可能就看不到外面更美好的世界了。

不過,大二後我對這個有了不同看法。第一,一個人如果突然跑到自己完全不熟悉的領域,而且完全都沒準備,這樣用「救火」來說是否比較貼切呢?一位法律背景突然要去開刀也不太可能。因此,應該說是要找個跟自己有「一定」關聯的產業去做,才不至於出現極大的反感。好比法律系的可以去打醫療官司,可以去對付專利蟑螂。縱使之前不知道這是什麼,一做下去仍是很有意義的。

反之,如果新領域僅是要你幫忙、替他人賣勞力、絲毫不給你發揮空間,而且又跟自己背景極大的無相關。此時,就要審慎評估了。當然也有不乏救火的人才,柯P就是很典型的例子,受到刺激之下出來競選成為台北市長。他在手術房的經驗給政治人物新的看法,做事快狠準,乾淨俐落。

而這當然建立在他願意去做,他也覺得很有意義。於是乎,我試著探討「跳脫舒適圈」是否要什麼前提?倘若我覺得沒意義還要去做嗎?萬一我覺得有意義,但是做了之後發現不是自己想要的呢?這都見仁見智。重點在於,至少要有意願去做,也要去模擬看看做了之後會發生什麼事情。

其實當自己做了全盤考量,就等於跳出了舒適圈了。

因此,我會覺得,要跳去的地方最好要跟自己領域有關聯,或是符合自己某些特質。這樣做起來才會有意義,縱使可能會很累,但是已經做過全盤考量,才有本事走下一步,也才讓「跳脫舒適圈」的意義完整體現出來。


2015年1月31日 星期六

能力 v.s. 熱情:寫程式要有滿腔熱血,但是我們要怎麼把程式學好? Ability v.s. Passion: Being enthusiastic is the essence in programming, while learning skill counts.

最近在學ios objective c開發,突然有些感觸。自己學寫程式兩三年了,早就知道程式是我這輩子最想做的事情。但是有時候熱情並不會讓自己突然變成程式高手,也不會一夕之間變成比爾蓋茲。你可能聽過身邊的人說他覺得寫程式很有趣,但是到後來能變成程式高手的又有幾個呢?他們會持續做這份工作嗎?

對於非英語系國家的人來說,在英文環境下寫程式同時也變成一種障礙。

你看出來了嗎?有時候固有滿腔熱血很重要,但是一股腦兒地往前衝只會讓自己跌個狗吃屎。

我之前寫程式就是一直往前衝,我看到什麼文章就看,別人推薦的也看。雖然說多多益善,但是卻沒有深刻理解,就像過往雲煙一下子消散而去。我一直以為多看、多寫、多想就可把程式學好,但是顯然地我想得不夠深。而且我看來,學習能力也是很重要的一環,孔子說:「學而不思則殆。」真有他幾分道理。好比說學習函數我就會注意:

  1. What(追本溯源):函數的作用是什麼?語法是什麼?為什麼要有這個函數?設計理念是?如果有類似函數,他可帶來哪些效益?如果不使用它我還有哪些函數可用?
  2. How(運籌帷幄):這函數要怎麼用?放在哪個區塊?他有哪些parameters?他和其他元件可以怎麼互動?我怎麼發揮它的最大效益?
  3. When(抓住時機):什麼時候要用這個函數?為什麼有些programmer在這裡要用這個,原因是?
只要想要把這三個東西抓住,我就會一直查很多資料,同時間我也學會了。而這也是為何給同一份程式作業,有些人會腦袋一片空白,有些人很快就知道如何下手。差別很可能就在這裡。

整體來說熱情是幫助自己在遇到障礙時不會退縮,但是寫得好不好就很攸關學習能力和思考能力了。以學習能力來說,一定要不斷地問自己為什麼,讓你的思考得到極大化。

而在學習一個新語言時,因為程式語言的基礎理念大同小異,有先學過c其實就很夠用。使用高中的讀書技巧也很有用:
  1. 掌握程式整體脈絡、語法特色、函數寫法、資料型態等
  2. 把握來龍去脈:寫程式就像蓋房子,基底(使用何種程式)怎麼建?建材(資料型態、函數)選擇?
  3. 上機實作、多看別人的程式碼,還有Don't reinvent the wheels!
相關自學能力可看這篇:自學能力 - MBAlib

最後著看到這篇文章的人都能變得愈來愈強!