[iOS] Compilation time goes crazy when using `+` in Swift

Image Credit


Recently I have been working on one of my side project in Swift. Originally, everything looked fine, but not sure starting from when, the whole compilation process started to be slowed down a lot from 20s to more than 5 mins!!

Originally I was thinking it’s mainly caused by some of my 3rd-party libraries because I did install some new ones during that period. So as an engineer, I started to bisect and see what’s going on. But after uninstalling / reinstalling those libraries, things are not going well though.

Ok so it looks like this way is not working and not the root cause, so what’s next ? After thinking a while, I started to check codes line by line and see what’s the most suspicious part that can cause the problem.  TBH, there was no any piece of codes looking suspicious to me… Ok no ways to go again, the only thing I could do is to narrow down variables and started to comment out methods from entry point.

After a while, boooooom, I finally found the part which would cause the problem !!!!

螢幕快照 2017-08-03 下午2.31.27.png

What the hell, it’s all about + !! Because I mainly work things in JavaScript, it’s really not intuitive to me that this can be the problem! After googling around, here comes some comments about this problem :



It has to do with type inference. Each time you use the + operator, Swift has to search through all of the possible overloads for + and infer which version of + you are using. I counted just under 30 overloads for the + operator. That’s a lot of possibilities, and when you chain 4 or 5 +operations together and ask the compiler to infer all of the arguments, you are asking a lot more than it might appear at first glance.

That inference can get complicated – for example, if you add a UInt8 and an Int using +, the output will be an Int, but there’s some work that goes into evaluating the rules for mixing types with operators.

And when you are using literals, like the String literals in your example, the compiler doing the work of converting the String literal to a String, and then doing the work of infering the argument and return types for the + operator, etc.

If an expression is sufficiently complex – i.e., it requires the compiler to make too many inferences about the arguments and the operators – it quits and tells you that it quit.

I think I am too familiar with languages like JavaScript, so all the details like this are all hidden and not exposed to us. No matter how, it’s still surprising though. Hope in Swift 4, this kind of basic operations like Array concat can be optimized and boosted up.

在前往日本留學的路上 part 1

Image Credit



不過好景不常,就在我們都交了日文系的卡諾揪之後,這個想法就立馬被推翻了 xD 日本反而變成是我們最常去的國家之一!也是因為這樣,為了想要有一些共通的話題,所以我就想說來去師大上個日文課好了。



還記得是兩年前大概是 2015 年的四月左右的某個星期日,跟著 張淑惠 老師開始在師大上了第一堂日文課 D1。還記得那個時候的教室幾乎是暴滿的。整間教室坐滿了一群對日文充滿著興趣的學生,一起從五十音還有發音開始學習日文,然後還搭配著大家的日本語第一本當做教材交錯使用,整個超像回到大學時期的那段青春裡呀 இдஇ

兩年過去了,來到了 2017 年的三月多,同樣的老師,同樣的教室,唯一變的是身邊的同學們,整個 D 班從當時的 D1 到今天的 D9,只剩下我一個人是跟著老師從頭上到最後的,同學們來來去去,就像是人生中的過客們一樣,在大家有限的生命中留下了些什麼,同時也帶走了些什麼。而現在的班級雖然經歷了多次的關班危機(因為人數不足),不過最後都還是活下來了,連老師自己都很意外還能夠開班成功就是了!

Photo 14-05-2017, 4 14 12 PM (1)

「大家的日本語」這本教材,也不知不覺來到了進階二的最後一本,如果沒有意外,當 D10 上完最後的第 50 課的那一天,應該也就是告別老師還有師大的時候了吧!


還記得上到 D5/D6 左右的時候吧,那個時候班上有個女同學和我分享了她同時在東吳(西門的城中校區)上課的事情,上的是一三五的三日班,然後假日再跑來師大上日文,過著超拼的生活。那個時候我也不知道哪根筋不對,就跑出了「師大一週上一天的進度比較慢,那我也來東吳上看看」的想法。

那個時候剛好很熟的高中同學平時也有在自學日文,就邀他一起來去東吳上課,我們就一起開始了東吳二四班的生活。每次都是一下班就狂趕捷運 =͟͟͞͞( •̀д•́) 然後走去西門的東吳上課,為了平日上課不知道放棄了多少原本休息的時間,然後兩個人就互相 cover 作業或是上課的筆記。然後不知道是從哪個時候開始,我們就另外再找了也很熟的高中同學組成了日文/程式讀書會,每週三固定會去板橋的某間 Louisa 集合,我就同時邊和兩個人切磋日文還有程式,整個超充實阿阿阿 (☉д⊙)

就這樣在東吳也上了約一年的二四班,在主要兩位老師 許育惠(會話)/丁思湖(讀本)的摧殘之下,日文真的是有很大的進步。在會話的方面呢,因為老師是台日混血的關係(日文是母語等級),所以和他上課就像是和日本人在講話一樣,教了我們很多只有日本人才會使用的口語用法、單字…等等。老師也很愛來一個隨機 cue 人,被 cue 到就要立馬講一個句子出來才可以,然後會一直糾正你的發音,這真的是超棒的!不得不說在火線上真的學特別快… (つд⊂)

而讀本的丁老師也有自己另一套的教法,最特別的就是老師會叫大家回家背讀本的課文然後上課抽背,要你把學過的東西唸出來給全班聽。不得不說這真的真的真的超有壓力,因為早就過了背課文的年紀了,所以要和年輕人拼記憶力真的是累阿 (´c_`) 但是也就是因為要背課文,所以很多你讀過就會忘的一些句子就會因此記在腦海內,你真的不知道為啥這個句子是這樣但是你就是用的出來,像我現在就可以很流利的背出「百聞不如一見」的日文就是「百聞は一見に如かず」呢,wwwwww 這什麼鬼啦 ( ˘•ω•˘ )

Photo 15-03-2017, 8 18 42 PM



P.S. 如果對我在櫻花國的生活感興趣的話,也不妨看看一下我有在持續更新的社交平台 FacebookYouTubeInstagram!有任何問題或是想要討論的東西也歡迎直接留言給我一起討論 😛


[Nonsense] Just back!

Image Credit


Finally, after 1 year, I am back! It’s been a while not updating my own blog due to so many reasons. I did try to write down some words but always forgot to finish it. In addition to this, there are also some problems in the blog system itself so that I can’t even publish the post or update plugins.

Few days ago, I made a decision to migrate all my self-hosted blog to WordPress.com and pay for it. It’s nice to leave all weird problems behind to someone else and focus on writing contents. I am sure from now on, I’ll start to write more words down and share to the world 🙂

Although it’s kinda late, but I still need to say, goodbye 2016 and welcome, 2017 !

[Electron] How to codesign your Mac app

Image Credit



Recently, Electron desktop application gets hot and popular among developers. It’s easy for developers to quickly mockup a desktop application and distribute it to three different platform with zero efforts ! (This is really a lie after I made another popular open source project called Kaku with the same tech.)

Ok back to topic, for companies who want to distribute their desktop apps to the world, they must codesign the application first ! The reason why this is important is because if you don’t do so, if the user enable gatekeeper by default, the application will be blocked due to unidentified developer and users will not be able to open it !



So in this article, I’ll try to share some my experiences about how to do the codesign for Mac app and what’s going on behind the problems.


Thanks to Marco Pracucci who wrote some useful details in his post, you can just follow these simple steps to do codesign :

  1. Get a Developer ID certificate from Apple and install it into your Mac’s Keychain
  2. Sign your application bundle codesign --deep --force --verbose --sign "<identity>" Application.app
  3. Verify the signature codesign --verify -vvvv Application.app and spctl -a -vvvv Application.app

Note: The identify here is the id wrapped inside the parentheses that you can get from keychain like the screenshot below:


But … the world sucks

The first problem I have encountered is version problem.

After codesign the app on my laptop (running 10.11.4) and share this app to my team members to test with, for those who are using 10.10.x, they will not be able to use the app and the gatekeeper’ll keep complaining something like the image below : 


But for the others who are using 10.11.4, the app is working well on their laptops (WTF???)

After googling a while, I finally found a discussion thread here on GitHub talking about this ! If you codesign your application on 10.11.4 , you’ll successfully get it codesigned and usable BUT for users who are using 10.10.x (to be specific those who use laptops <10.11.3) will have problems when opening that app.

From the discussion thread, we can learn that there are something changed from 10.11.3 to 10.11.4. If you want to hack that around by yourself, you’ll need to follow the steps here. But for me, I use electron-packager, so if you are using that too, you can just upgrade to 6.0.0+ because they already handle that for you on that version with zero efforts !

How to verify your app

  • codesign
    • This tool is not only for doing the codesign, but also you can use it to verify whether it’s well signed or not. After running it, you can get things like this :
$ codesign –verify -vvvv Vectr-darwin-x64/Vectr.app
–prepared:/Users/EragonJ/…/Vectr.app/Contents/Frameworks/Electron Framework.framework/Versions/Current/.
–validated:/Users/EragonJ/…/Vectr.app/Contents/Frameworks/Electron Framework.framework/Versions/Current/.
–prepared:/Users/EragonJ/…/Vectr.app/Contents/Frameworks/Vectr Helper EH.app
–validated/Users/EragonJ/…/Vectr.app/Contents/Frameworks/Vectr Helper EH.app
–prepared:/Users/EragonJ/…/Vectr.app/Contents/Frameworks/Vectr Helper NP.app
–validated:/Users/EragonJ/…/Vectr.app/Contents/Frameworks/Vectr Helper NP.app
–prepared:/Users/EragonJ/…/Vectr.app/Contents/Frameworks/Vectr Helper.app
–validated:/Users/EragonJ/…/Vectr.app/Contents/Frameworks/Vectr Helper.app
Vectr-darwin-x64/Vectr.app: valid on disk
Vectr-darwin-x64/Vectr.app: satisfies its Designated Requirement

view raw
hosted with ❤ by GitHub

  • spctl
    • For this tool, this is mainly used to see whether your codesigned application will be blocked by gatekeeper or not, if you didn’t get anything wording like accepted, your application will always be blocked or treated as damaged by gatekeeper, so it’s really important to use this tool to do the check every time when you create the new application.
    • Note: If you are using Apple Developer ID certificate to build you application and be distributed by yourself, Remember to change your [System] > [Privacy] to “Mac App Store and Identified developers. Otherwise, you will keep getting rejected information.
$ spctl –assess -vv Vectr.app
Vectr.app: accepted
source=Developer ID
origin=Developer ID Application: Vectr Labs Inc. (XXXXXXXXXX)

view raw
hosted with ❤ by GitHub

How to test

You can check details here from Apple’s documentations, but I’ll still copy some here.

  1. To disable Gatekeeper using the spctl command
    • $ sudo spctl --master-disable
  2. To confirm that Gatekeeper is enabled using the spctl command
    • $ spctl --status
      • If enabled, you will get assessments enabled
      • If disabled, you will get assessments disabled
  3. To test your Developer ID-signed app
    1. Make sure your gatekeeper is enabled by follow above ways.
    2. Email your Developer ID–signed app to yourself and use the copy that Mail downloads to trigger the dialog.
    3. Host your Developer ID–signed app on your own local or remote server and use the copy that Safari downloads to trigger the dialog.
    4. By doing so, your gatekeeper will be triggered correctly !


A) My certificate on keychain keeps showing expired

This problem is critical and annoys developers who are not familiar with Apple certificate things (like me !) When working on the codesign feature, I noticed that no matter how hard I re-install the certificate that I download from Apple, it will keep showing expired with no reason !

After trying and discussing this with one of my iOS friend, we finally realized it’s related to this notice ! For someone (not sure who, but including me), the Apple Worldwide Developer Relations Certification Intermediate Certificate is going to expire on Feb 14, 2016 which will cause the problem to make your certificate keeps expired.

What you need to take action here is to renew the this core certificate and try to re-install (or re-create) your developer certificate again and things will be solved … WTF !!

B) Where to find my certificate ?

For most of people, if you are writing desktop application by Electron, normally you’ll distribute your application by yourself (like us). But, I noticed that it’s really frustrating to figure out how to get that Developer ID Certificate !!

I have tried several times from https://developer.apple.com, but there is nothing related to Developer ID Certificate (or maybe it’s mainly because I am using different role, so it’s not showing up ?) ! After reading tons of articles, I finally realized that it’s inside Xcode !! You can check the screenshot below :


But you can notice that the buttons are grey and is not clickable. That’s mainly because the role is wrong !! Even if you are admin role, you still can’t generate that ! Only Team Agent can do that ! So if you are developer or admin, Go ask your leader for that and tell him/her to press the button above to create the certificate for you.

After getting the certificate (it will be name like this xxxxxxx.p12), you can just double-click the file and install into your keychain. Remember, always keep them private 🙂

Note: Only the first one who made the certificate and uploaded to Apple Developer can have this .p12 file. This will only exist on his own keychain and you can’t even get it from Apple Developer. So remember to ask him to export that p12 file and share with the whole team ! Remember, if you lost this .p12 file, no one can save you and you need to regenerate another certificate again.

Last few words

It’s really a hard time to fight with codesign stuffs especially there are less resources talking about this. But whatever, I wrote them down already !! If this article does help you, please feel free to share !

And also, if there is anything wrong or missing in the article, feel free to tell me and I’ll update it ! See you guys next time 🙂


  1. https://pracucci.com/atom-electron-signing-mac-app.html
  2. https://github.com/electron/electron/issues/4899
  3. https://goo.gl/ZgKXr1
  4. https://developer.apple.com/support/certificates/expiration/

[Javascript] Something about pinch gestures

Image Credit


最近一直在研究如何在 Browser 上支援 Mac touchpad 的 Pinch 手勢,所以有一些心得想要記錄一下。

3rd party libraries

一開始的想法就覺得這種事情應該有什麼 3rd party 套件有支援了,只要簡單的把 event 和現有的程式接上就可以了。不過找了一陣子後,實在是沒有找到什麼好東西,通常大家推的都是 Hammer.js,不過其實這個 library 是專門設計給 mobile app 使用的,看了一下程式碼發現是組合 touch 相關的 event 後再經過數學運算後提供客製化的 gesture event 像是 pinchpan … 之類的。

不過這個和我的使用情境不太一樣,因為 gesture 相關的 event 只有在 mobile 的 browser 上才會存在,因此只能再找找別的方法。


之後很幸運的找到了 Chromium 開發者們的討論串,主要在討論的內容就是要如何把 touchpad 上的 pinch 手勢透過 wheel 這個 event 傳出去!那個討論串主要的重點就是在於 2014 年五月之後,Chromium 開發者們上了一個 patch,讓前端開發者可以透過正規的 wheel event (對了,wheelmousewheel 有點不太一樣,前者才是大家公認的標準,後者則是非標準,只有少部分的 browser 有支援,要注意一下)去偵測 pinch gesture 的觸發。當 wheel event 是透過 pinch 觸發的話,那傳進來的 event 的 ctrlKey 這個屬性則會被設成 true,所以開發者們就可以用這個值來做判斷。

而在我們公司裡,因為我們要監聽這個手勢的發生做客製化的視覺處理,而且我們不希望 Mac 上預設的 zoom in / zoom out 還被觸發,所以要記得透過 event.preventDefault() 來避免 Browser 做 zoom in / zoom out 的動作。



  • Safari
    1. 目前我手上最新的 Safari 9.0.x 版(Mac OS X 10.11.x)是沒辦法透過上面的方法來偵測手勢及取消預設的 zoom in / zoom out 觸發。
    2. 好消息是在未來的 Safari 9.1.x 版後,他們提供了新的 gesture event 讓開發者們可以去偵測手勢,不過這個版本目前也還沒釋出所以也沒辦法測試,如果官方文件沒有唬爛的話那就應該是可以支援,只是這個 event 目前應該也是 Safari only 的客製化 event 就是了,會不會變成 standard 也不知道。
  • Chrome
    1. 在 2014 年五月後的 Chrome 就支援上述做法來偵測 pinch 手勢了!(我很想查 Chrome 的版本號只是不知道怎麼找,如果有人知道那個 patch 實際被 land 到哪個版本的話,請和我說一下)
    2. 個人 Chrome 48+ 實測是 ok 的。
  • IE / Edge
    1. 如果討論串上的資訊正確的話,那 IE / Edge 應該和 Chrome 一樣有支援 ctrlKey 可以讓開發者去做偵測。
  • Firefox
    1. 無解 …
  • Electron
    1. 我有測試過 Electron 0.36.x+,因為他的核心也是 Chromium,所以這個做法也是可以支援的!
    2. 如果你是用 <webview> 的方式來載入你的 web app 的話,那你特別需要先在 render view 的地方聽  wheel event 但是不需要做任何事(超怪,無法理解),這樣這個 wheel event 就會正確的被傳進你的 <webview>,然後你的 webview 裡面如果有實作 event.preventDefault() 的話,那預設的 zoom in / zoom out 行為就會被取消,這樣你就可以在 webview (也就是你的網站裡面處理這件事情就好)



  1. http://jsbin.com/qiyaseza/8/edit?html,css,js,output
  2. https://bugs.chromium.org/p/chromium/issues/detail?id=289887
  3. http://stackoverflow.com/questions/15416851/catching-mac-trackpad-zoom
  4. http://stackoverflow.com/questions/29929411/disable-pinch-zoom-in-webkit-or-electron
  5. https://gist.github.com/NekR/9a80ebe73573e11f0351

[Look Back] 2015 – A Crazy Year

This image was made with Vectr


時間過的好快,2015 又過了呢 … 已經來到傳說中的 26 歲了呀。

逝去的 2015

過的好快,2015 就這樣過了,來列一下年初期許的事情有哪些完成了:

  1. 背好五十音 xD
  2. 挑戰一個人去旅行,學著和自己對話。
  3. 勇敢離開自己的舒適圈。
  4. 不要一個人過完這一年。(閃屁)

如果真的要說,2015 真的是一個瘋狂的一年。

工作方面,在七月的時候離開了 Mozilla,謝謝前同事們對我的照顧,在這個地方學了好多東西,然後又來到了另一個有趣的地方 Vectr ! 不只開啟了數位游牧民族的生活,也開始實作一些有關繪圖軟體需要的東西,這個經驗真的是很難得呀。

感情方面,雖然在 2014 年尾發生了一些事,但是卻又遇到另一個更好的人,也因此催生了 2015 年最重要的 Open Source 專案 – Kaku!也開始在師大學日文,不知不覺也上了一年的課,日文能力也略有進步,雖然在日本的時候只會講不會聽也沒什麼屁用就是了 xDD 只能繼續加油。


  • 金沢
  • 高山
  • 白川郷
  • 大阪
  • 奈良
  • 清邁
  • 拜城
  • 澎湖四天三夜
  • 四年一度的東港燒王船
  • 台南遠端工作一週

還記得以前曾和旅行咖的朋友說過日本是我們 50 歲以後才會去的地方,沒想到這一年我們兩個都去了日本,而我還去了兩次 xDD。邊打這篇的時候還邊翻了一下行事曆,才發現原來我跑了這麼多地方!旅行對我來說真的是生命中不可或缺的一環呀。

現在進行式的 2016


最後還是要謝謝在 2015 年出現在我生命中的所有人,不論是好是壞都是讓我繼續前進的一部分!謝謝你們,一起加油吧 🙂

[Memo] 數位遊牧的生活 Part 1

Image Credit





我想,所有的起點都是從 2014 年這封信開始的吧:


真沒想到我還翻的出來這封信,對我來說,這封信是目前職涯的轉折點(加現在這裡也才第三間公司,職涯是有多長啦 XD),也是我數位遊牧生活的起點。


大學畢業後,我就設立了一個目標,就是每一年至少要寫一些有趣的開放源始碼專案,先不管這些東西對別人來說有沒有用(有用當然最好),但是至少要寫一些東西出來。久而久之,我的 GitHub 開始累積了一些東西,而之中還真的有人在用 XD (我都不敢用了你們怎麼敢用!!?)。其實當初在寫程式的時候也沒想這麼多,主要也就是好玩而已呀(玩心 driven development xD),天知道這竟然會是日後和 Nick 接上線的橋樑!


Let’s talk

這邊真的要特別講一下,我真的覺得外國人找人的方法很特別(樣本數只有一,應該很不準 xD),有別於以往在 LinkedIn 上面的罐頭信,Nick (我們的 CEO)的做法就真的很不一樣,從上面那封信其實就可以看的出來如果他們對於你這個人有興趣的話,他們會先試著了解你這個人做過的所有事情不論是技術或是非技術相關的。以 Nick 為例,他的做法是上 GitHub 把所有在台灣的 JavaScript 開發者從頭到尾全部看一遍,然後從你的作品去了解你這個人的能力在哪裡,如果對你有興趣的話會再透過你在 GitHub 上面留的信箱來聯絡你,對你做進一步的認識。

補充:這裡有兩件事情我覺得很重要,一就是 GitHub 對於一個軟體工程師帶來的影響,二就是你一定要留一個別人找的到你的信箱,如果怕被機器人找到你的話就把 Email 的特別字換掉也是一種不錯的做法。所以如果想要和國外工作機會接軌的話,麻煩參考一下這段。

在初步的 Email 往來後(約十幾封 xD),就和 Nick 約了某天去士林吃夜市。我覺得對他們來說,實體接觸似乎是一個必要的過程,它提供一個無壓力的環境介紹(推銷)他們想要做的事情給你,也會從中和你聊許多有的沒的事情,從技術、工作、玩樂一直到生活層面都有。簡單來說,我覺得 Nick 這個人給我的感覺是除了找員工之外,還多了一種交朋友的味道在裡面,你唯一要特別注意的事情就是用英文坦住 4 個小時以上,並且試著用各種方法騙他們吃一些奇怪的東西像是「豬血糕」、「臭豆腐」或是「皮蛋」就可以了 XDD

不過說真的,我們約出來的次數應該有超過 2 ~ 3 次以上,而且每次的時間也都頗長,畢竟對一個 Startup 來說時間還有資源怎麼樣都是比大公司還受限呀,所以多花一點點時間找到對的人相對就重要許多了,那過程相對耗時也就可以理解了。如果硬要算的話,我覺得在這些過程上所花的時間真的比我過去面試(也才兩間而已是在大聲什麼 )過的公司還長許多呀。




對我來說,我覺得如果沒有經過第一份工作離職後那短暫 3 ~ 5 個月和室友在家自己寫程式的時候,我想遊牧的生活對我來說是一件非常困難的事情吧!還記得那個時候的我們對於離職自己創業(玩耍)有著一些憧憬,剛好前後我們都遇到了跳潮的時候,就順理成章的在家自己開著電腦工作。


不過想也知道這怎麼可能賺錢,到後面其實都是在用自己的老本來付房租還有生活費,存款也不知不覺中快見底了,而最後也不得不去接一些 Case 來試著養活自己,步調也就從此亂掉了。不過事後想想,我覺得這些事情都不是最難的,最難的事情其實是維持「規律的生活」還有「自制力」。而很剛好我們就是沒有自制力的那兩位,很常每天都睡到中午、想做事的時候就做事、想睡到的時候就睡覺,生活和工作再也此分不開來。而當然爾,最後這場鬧劇也就不了了之,我和我室友也各自另尋出路去了新公司工作了。






由左至右分別是 Nick 、Hychen、Yurenju、Emery 、 EragonJ
(雖然當時 Nick 人在國外,但我們還是請朋友硬是把他 Vectr-ed 進來 XDD)

(這篇文寫太長了,快轉鍵給他七略!)最後,我就告別 Mozilla(謝謝你們!)來到 Vectr 啦 😛 其實這也小小的圓了我想在外國工作的夢想呀(不是人在台灣嗎!)。以前雖然是在 Mozilla ,但是其實在台灣的人也都還是台灣人,說衝擊嗎其實也沒有很大的感覺,大家都是在網路上打打字、留留言比較多,也沒有什麼實際一起共事的機會。不過來到 Vect 就不太一樣了,也才只有五個人而且要打理所有大小事(還好我只要刷我家的馬桶就好),再加上我們每週定期有一次實體會議,所以其實大家接觸的時間真的蠻長的。而每次只要大家聚在一起的時候,我們三個台灣代表都要開啟全英文模式至少 4+ 小時以上,通常要一直到最後大家都元氣耗盡了才會結束 XDD 真的是一種很特別的體驗呀!

在這邊有很多新的東西可以學,也有很多機會和不同的人一起工作。對我來說,跳出自己的舒適圈只是第一步,數位遊牧生活也才剛開始而已,未來會怎麼走我也不知道,其他的就留到下一篇再說吧 😛

[Hack] Kaku – music player for next generation


每年都要花點時間做自己的 Open Source Project,而今年意外的有一個很好的題目可以來發揮 xDDD,所以就利用一些下班的時間把 Kaku 的整個雛型打造出來了!Kaku 是一個音樂播放器可以讓你自由地聽各個網路平台上面的音樂(目前支援的平台有 YouTube、Vimeo 還有 SoundCloud),算是一個各平台整台的小作品。


而在開發這個程式的時候也發生許多有趣的問題,所以想把我還記得的部分寫下來做個記錄 xD。

Node Webkit(NW.js) 起手式

因為我一開始的目標就是希望這個程式是各個作業系統的使用者都可以使用的,因此桌上型應用程式勢必是我的首選,又因為在實際寫 Kaku 之前,我有幫 Atraci 寫過一些相關的程式碼,所以對於如何操作 Node Webkit 提供的 API 有一點點研究,所以就選用 Node Webkit 當作我開發的基底。(我只是前端工程師阿阿阿)

說到 Node Webkit,他有個有趣的設計就是他提供不同的 JavaScript Context,因此你的應用程式雖然是用前端的技術打造的,但是因為可以跨用到 Node Context,所以就可以混用許多現有的 npm module 當做後端來處理資料,所以在我的設計下,在這個程式裡面就有這兩類不同的資料夾,讓程式可以很明確的切分他們的職責。


因為有過幾次合作開發 Open Source Project 的經驗,所以如果你要讓你的專案吸引其他開發者的注意力的話,那你一定要把開發環境搞定或是簡化到一個指令複製貼上就可以跑起來,要不然光是一開始就讓別人有很強烈的挫折感,那你的專案也不用期望會有多少人來幫忙開發了 xDD。

又因為 Kaku 是我想要來嘗試練習 React 的一個專案,裡面用到很多 jsx 的語法所以需要 precompile 的動作,而且又因為要把整個程式包裝成 Node Webkit 的應用程式,也需要另外做 build 的動作,因此我就用 gulp 當做我 building tool 的基底來把這些操作都包裝起來,讓開發者只要按一兩個 gulp 指令就可以了!

現在想想,一開始就把這件事情做好所帶來的效益真的很高,也真的有一些人上了一些 patch !


以前在 Mozilla 的時候,我們 app 的程式是架構在 require.js 之上以 AMD 的模式開發,所以時間久了我也漸漸的習慣了這種寫程式的方式,所以一開始的 Kaku 也是以這種方式寫的(對,之後被我全砍了)。但是時間久了我發現我漸漸的被他的東西綁住,整個 repo 開始要加入他專屬的設定檔去設定東西,最慘的就是寫測試的時候還要特別去設定一些東西才可以讓 AMD 的程式碼順利的跑在 require.js 上面。然後我記得最麻煩的是前端用的 require.js 和後端用的 require.js 無法混用,我還要特別抓一份存在 node_module (WTF),然後它對於 ES6 的支援度不知道為什麼有很多問題,所以到後面有很多東西不是沒有測試,而是我不知道要怎麼讓他成功的跑在測試環境上面所以才沒有寫,囧!

這些其實不是壓倒我的最後一根稻草,壓倒我的是 3rd-party library 對 AMD 的支援有一些問題,不知道是那些作者在寫 UMD 寫太爛還是怎樣,有時候那些判斷的順序寫錯就無法用,囧!!所以那個時候為了讓很多 3rd-party library 可以使用,還特別 fork 並改了好多個專案,雖然大多都是 quickfix 不過也是很麻煩呀!

之後,因為強者我前同事 @rickychien (Mozilla 已經變前公司了你不知道嗎 xDDD) 在這段期間內一直和我在討論引入 webpack 的事情,所以就在某兩天想說長痛不如短痛,一次改了一百多個檔案把之前 AMD 的東西全部拿掉然後把測試還有開發環境一次全部用壞之後,就成功的把程式碼全部轉過去了 xDDD(完全錯誤示範,請不要學!!)

這邊真的要慶幸之前是用 AMD 的模式寫程式,才可以把各個模組切的這麼乾淨,然後通通改用 Common js 的方式載入,然後透過 webpack 來做打包的動作,整個世界美好!

Test + CI + Documentations +++

雖然是 Open Source Project,還是要用高規格來寫程式,該有的 CI、測試、文件都沒有少(有很多還沒寫完就是了…),這些東西真的都是在你要改程式的時候才特別有感!還記得以前不知道在哪個文章上看到幾句話關於工程師最討厭做的事情(以下為大概):

  1. 寫文件
  2. 寫註解
  3. 寫測試
  4. 別人不寫文件
  5. 別人不寫註解
  6. 別人不寫測試

為了不要變成那個讓別人討厭的人,所以只好默默的把這些東西都補齊了 xDD,這些真的很重要呀!

從 NW.js 到 Electron

其實說實在的原本 NodeWebkit(NW.js) 用的好好的,只是想要嘗試一下 Github 特製的 Electron ,所以就一口氣換過去了 xDDD ,說真的之所以會想要轉換過去是覬覦他自動更新的功能,能夠讓應用程式自動更新真的很棒呀,不過研究後才發現他原生只有支援 Mac OS ,Windows 的則是要另外把他包進來,而 Linux 就什麼都沒有了 xDD,而且最麻煩的是要有提供一個 endpoint 讓他去存取得知最新版本,然後當使用者需要更新的時候才會再去相對應的載點下載。

其實想一想整個流程也是很合理啦,不過因為我不想要有伺服器來存這些東西,維護也有成本,所以我的東西都是放在 GitHub Releases 裡,因此就自己利用 GitHub API 自己簡單實做一個各平台都可以用的自動更新程式放在 Kaku 裡,讓他每次被啟動後會去判斷是否需要更新,如果使用者確認要更新後,會再把使用者導到下載程式的地方,完成半自動更新的流程(使用者唯一要多做一步的就是要自己解壓縮檔案然後覆蓋舊的程式這樣)。

說實在的 Electron 本身並沒有帶來太大的好處,一來是整合相關的 gulp 工具不多,二來是因為他的 global shortcut 的設計和 nw.js 的不一樣,需要多處理程式得到 focus 還有失去 focus 的事情(雖然也是好事啦),三來是我的程式沒有複雜到要用到很多特殊功能,所以花了很多不必要的時間 xD。不過用了就用了,有 GitHub 帶著社群開發也可以讓 Electron 更長久,持續觀注!


Kaku 有使用了很多社群開發的工具,盡量把主要的時間留在開發主要的商業邏輯,或是整合這些工具讓自己可以用得更順手。也因為這樣子,中間發現了一些工具的問題,這個時候要做的第一件事情就是先找找看有沒有其他更好的工具,如果沒有的話,我就會試著去 fork 那個專案然後修有問題的地方,最後再上 PR 給原作者。先不論那個 PR 會不會被接受,但至少在這個過程中,我也試著推動了輪子,試著讓這些東西變得更好,省下別人的時間。如果最後沒被 merge,笑笑也就過了是吧?


通常程式設計師都不太會注重這一塊,但是我覺得對於 Open Source Project 來說,這一塊相當重要。這邊想講的不是說要砸多少錢買廣告幹嘛的(拜託,這是 Open Source Project 耶),而是要有一個基本的門面,至少簡單做個網頁加點程式相關的圖片嘛!不得不說在這個資訊暴炸時代,如果資訊本身不夠吸引別人,即使你改變了這個世界幾百次,也不會有任何人注意到的。

沒有人注意到這個專案,就不會有人使用你的程式,就不會有開發者加入和你開發新東西,你就會開始覺得這些東西做了不知道要幹嘛只能自 High,久了也就失去動力繼續下去了。不過至少,你可以去一些開發者論壇以技術的角度切入並和大家分享你做了這些東西,除了彼此技術的成長之外,無形當中也是一種行銷不是嗎?

所以,我就請設計師朋友幫我做了 Logo,也自己簡單的做了一個網頁展示這個程式,雖然沒有多專業但也比什麼都沒有好多了!再適時加上一點點 Social buttons ,如果有人想要分享的話自然就會分享,這樣也就夠啦!


如果你沒用過 Kaku 的話,請立馬去官網下載,有什麼意見或想法都很歡迎留言給我,敬請期待下一篇文章 😛

[Memo] 兩年之後

Image Credit


時間過的超快,2015 年的七月也過了一半了,在離開 Mozilla Taiwan 半個月後,覺得要好好寫一篇文章記錄這段兩年的旅程。

還記得兩年前,在剛離開前前公司 Trend Micro 後(現在 Mozilla 已經變成前公司了 xDD),再次陷入了找工作的轟炸期,當時還特別寫了一篇文章記錄那幾個月的心境還有過程,在經過各大公司、團隊的連環面試後,意外的拿到很多間公司給的 offer,其中最感謝的就是讓我來到 Mozilla 的主管 – Timdream,沒有因為我只有 10 個月短短的經歷就刷掉我,讓我加入這個大家庭和每位強者同事學習很多東西,除了技術上的成長之外,也因為公司是跨國的公司,所以很多時候要和外國人還有自己 team 的人一起討論事情,雖然英文還是有待加強,不過也讓我在團隊合作這件事情上面學了很多呀。

在 Mozilla 的這段時間,去了很多國家、城市, 最讓我印象深刻的就是在剛進去的時候,剛好遇到三年(還兩年)一次的 Summit 大會,第一次看到規模如此大的會議(全世界的 Mozilla 員工還有 Contributors)、第一次去了美國的 Portland、第一次和同事出國旅遊。這次的會議真的讓我感受到西方國家的人對於工作還有生活的態度,雖然工作重要,但是工作後的玩樂還有 party 也是不能少的,該放鬆的時候就一定要放鬆,玩的比大家都還要 High 呀。




從 Summit 回來之後不知道過了多久,因為職務調動的關係就被分配到 Settings App team,這個 team 主要就是由人生勝利組的學長 Arthur 帶著其他人一起守住 FxOS 裡面的 Settings app(就是大家手機裡面的「設定」),不得不說這個 app 真的是包山包海包了又包包了再包,有一大堆和電信業者之間的通訊問題要處理、有一大家和系統之間的複雜互動還有一堆各 app 都要進來插一些自己的客製化設定,真的是一個不得小覷的 app!

在這個 team 裡,真的要特別感謝 Arthur、Ian 還有 Fred。感謝 Arthur 教我很多程式設計的一些眉眉角角,我永遠都會記得 Data / UI 分離這個準則的 xD。感謝 Ian 在 Settings app 裡藍芽的貢獻,如果沒有你擋下這些東西我們就屎定了 xD。感謝 Fred 和我一起處理很多 FxOS Tablet 的問題,當時 tune CSS 真的 tune 的很想死。到底是哪個____把 CSS rule 寫這麼死的啦 xD

也因為這個 team,在 FxOS 1.3 -> FxOS 1.4 workweek 的時候,我和 Arthur 一起和國外飛來的同事處理了很多 DSDS 的問題(就是所謂的雙卡雙待),而那是我唯一一次在 Mozilla 辦公室待到超過 11 點的時候,雖然那個時候很累,不過有這些戰友撐過那一週也是一個很特別的體驗!如果沒有這個 workweek,我也沒有機會去 101 頂樓看整片台北市的夜景(雖然裡面的商店都在賣高價商品給陸客有點煩人之外其他都算不錯),真的,很美。


之後,和整個 Gaia team 的大家也變得比較熟了,每一季大家都會舉辦 Team Building 出去某個地方玩一整天,大家一起打過桌遊、打過保齡球、玩過密室逃脫、去過淡水、去挑戰過熱血的抱石活動、去日月潭一起環湖騎腳踏車,好多有趣的事情都在這兩年內發生過,我還記得當時的宮博說過一句話,大意是說「在一些日子之後,最讓你印象深刻的不會是在這間公司工作過了什麼、做了哪些事情。反之,是那些曾經一起工作的人、那些回憶,才會讓你永藏於心」。




Special thanks to : Ricky, Gary, Greg, Arthur, Evan, Dominic, George, Ian, Rudy, Steve, Jessica, Sylvia, HsinYi, popochess, Yang-Jhu, Tim, Evelyn, Yuren, Edgar, Fred, Alive, Bella, Fang, Carol, Rex, Tzu-Lin, Luke, Clarice, Paul, Peko, Kate, Michelle … etc.





[FxOS] Settings App – Call Settings

Call Panel



Call Panel


Call Settings is one of the most important panel that can let users highly customize their own call related settings like Call Waiting, Call Forwarding … etc. (We will cover each part later) Based on the screenshot above, you can see that for this panel, it’s more like an entry point for every panel and also it will display some useful information taken from hardware.

But when you navigate from this panel to others and navigate back, you may notice that some menu items are disabled at first and you can’t manipulate that. This is not a bug but also quite a feature. By doing so, we can make sure that each time when displaying them, we will always use latest value from hardware to make sure we won’t display some outdated information to mislead users.

Call Voice Mail Settings Panel (Dialog)



Call Voicemail Panel


For every simcard, there must be a special number that you can dial to set your voicemail number and this is why we need this dialog in Settings App. When showing this dialog, it will try to get preset voicemail number in mozSettings db and show it at first. Here, you may get confused why it can get the right number from db, this is because in settings/js/panels/call/panel.js, we also need to show voicemail number on the menu item, so when trying to initialize the item, we will check whether there is any provided number from mozVoicemail API and store it into db, so that’s why in this dialog, you can get this value from db.

Call FDN Settings Panel



Call FDN Settings Panel


Enable / Disable FDN


This panel is also an entry point that we can set settings related to Fixed Dialing Numbers. Here, we provide a toggle that you can enable / disable this feature. When clicking on the toggle, it will trigger DialogService to show SimpinDialog which is responsible for all Simpin related operations. This feature will only be enabled / disabled when you successfully type your PIN2 correctly in the dialog.

Call FDN List Panel



Call FDN List Panel


Popup menu when clicking on FDN number


Here, in this panel, we will list down all preset FDN numbers in the list. When clicking on any number, we will show an popup for it and you can decide whether to call, edit and delete or not. Same with enable FDN, if you are going to do any operation I mentioned, we will use DialogService to show SimpinDialog to confirm this operation.

For any FDN number, they will all be stored inside your simcard. Sometime, based on your simcard, you may have an upper bound for the number of FDN numbers, but this depended on operators so the number may vary. So, if you hit an error message when creating a new number, you may go into this situation.

Call FDN List Add Panel (Dialog)



Call FDN List Add Panel (add mode)


Call FDN List Add Panel (edit mode)


When clicking on the Add button in Call FDN List Panel, this dialog will pop up and ask users to input preferred name and number for this set of FDN number. Instead of adding, this dialog is also can be reused for editing. Normally there is no specific validation rules for these two fields in our codes, instead, we will pass wrapped object from FdnContext.createAction and pass it to SimpinDialog, it will directly communicate with operator and if there is any error coming up, we will directly report it and display to users.

Call Forwarding Panel



Call Forwarding Panel


Honestly, Call Forwarding can be the most complex panel in Call Settings (especially before it was refactored), so let me briefly tell you a story behind this panel.

When users click on any menu item and type number for any Call Forwarding option (For this part, please check Call Forwarding Details section), after submitting, we can get wrapped results from the dialog and use call/call_forwarding.js to help us handle this object. After doing some tests, it seems that it is not able to do multi tasks when interacting with Gecko’s API (This should be the problem in modem). So, in order to make anything works perfect, we create another module called CallSettingsTaskScheduler (call/call_settings_task_scheduler.js) inherited from TaskScheduler (modules/base/task_scheduler.js).

TaskScheduler is obvious responsible for handling different tasks and make sure they are all scheduled and can be executed one by one without conflicting each other. While for CallSettingsTaskScheduler, it is just an extended class with some customized TASK_TYPE and error handling.

So back to topic, because we aren’t able to do more than one request on modem each time, we need the help from task scheduler to achieve this. This operation includes get and set, so they all should be scheduled. If we don’t do this in order, modem will directly throw out errors and our request would be dropped and this would make our state inconsistent with hardware.

In addition to this, there is also another special feature that TaskScheduler provides – if there is another same-type task coming up, we will remove queued same-type task and push the new on in the array. By doing so, we can make sure we won’t send outdated request and would always keep the latest one.

And for UI, when modem is busy on handling our operation, we should disable all UIs while normal, we should make them back. So, in panel, we will observe CallForwarding’s internal _state to lock / unlock UI.

For anything else, please check our script.

Call Forwarding Details Panel (Dialog)



Call Forwarding Details Panel (Dialog)


This is the dialog that you can set any number on each Call Forwarding option. Right now, because we do support 4 different options for Call Forwarding but with the same UI, we will reuse this dialog for all of them instead of duplicating many codes. But basically, there is no much logics hidden in this dialog and all what it does is pass the result back to Call Forwarding Panel (Caller) and the caller will do following operations based on returned values.

For more details about how Call Forwarding works internally, please check Call Forwarding Panel section for more details.

Call Barring Panel



Call Barring Panel


In this panel, you can restrict certain types of outgoing calls and incoming calls. There are no special logics handled in this panel and this can be treated as a toggle that helps you customize your Call settings.