高見龍

iOS app/Ruby/Rails Developer & Instructor, 喜愛非主流的新玩具 :)

你看過 Elixir 嗎?如果沒有,現在讓你看看!

Purple Crystal

圖片來源:Patrick Wallace

你看過 Elixir 嗎?如果沒有,現在讓你看看!

Elixir 這個名字,對女生朋友來說也許比較熟悉一些,因為它是一款知名化妝品廠商所推出的某一種保養品的品牌,但我並沒有接廠商的業配而且自己也沒在用保養品,所以今天也不是要介紹這款保養品。

我第一次認識 Elixir 這個單字,其實是因為當年玩 Final Fantasy 這款遊戲時候,遊戲裡有一款叫做「エリクサー」的道具,使用後會恢復全部的 HP 跟 MP,而這個「エリクサー」其實就是從 Elixir 這個英文字轉變來的日文外來語。

這篇文章要介紹的,是一款名為 Elixir 的電腦程式語言。本文的目的並不是要告訴你 Elixir 有多好多棒、效能有多好多棒(雖然是事實),而僅介紹一些我認為這個程式語言讓我覺得寫起來很開心的地方,特別是對一個喜歡 Ruby 的人來說。

首先,學習一門新的程式語言,先不說別的,外表看得順眼是很重要的。Elixir 這款程式語言的 Logo 是一顆紫色的水滴:

Elixir Logo

好吧,我個人覺得 Logo 還不錯看(我的看法啦)。

Elixir 是一款函數型的程式語言,跟其它物件導向的程式語言比起來,Elixir 沒有類別、沒有物件、沒有所謂的實體方法、類別方法,只有一般平鋪直敘的函數(Function)。

什麼是函數?我們國、高中的數學都應該看過這樣的東西:

f(x) = 3x + 2

這個一元一次方程式,就是一個函數。函數通常會有輸入值也有輸出值,以上面這個為例,它的「輸入值」是 x,「輸出值」是 3x + 2

在 Elixir,函數是一等公民,甚至可以把函數傳給另一個函數當做一般的參數。不過少了我們平常習慣的物件導向的觀念,一開始真的有點不習慣,會不知道該把程式寫在哪邊比較好。

Elixir 這個程式語言可以介紹的內容很多,應該不是我這一篇文章就可以聊完的,更多關於這個程式語言的細節,請各位移駕至 Elixir 的官網,在這邊就一些我個人覺得有趣、好玩的語法跟大家分享。

好玩的語法

Pipe Operator

也許你曾看過這樣的程式碼:

1
func1(func2(func3(super_function(best_function("I love you")))))

先不管這個 func1func2 或是 super_function 是在幹嘛,像這樣洋蔥式或大腸包小腸式一層包一層的寫法,雖然仔細看還是能知道意思,但可讀性上就稍微沒那麼好。如果改成多行,可以變這樣:

1
2
3
4
5
tmp1 = best_function("I love you")
tmp2 = super_function(tmp1)
tmp3 = func3(tmp2)
tmp4 = func2(tmp3)
tmp5 = func1(tmp4)

老實說這樣寫也沒好多少,特別如果又像我這樣故意用一堆之後用不上的 temp 變數。

Elixir 可以直接這樣寫:

1
2
3
4
5
6
"I love you"
|> best_function
|> super_function
|> func3
|> func2
|> func1

Elixir 的 |> 這個 Operator,意思就是「把前一個 function 執行的結果,當做第一個參數傳入下一個 function」,所以下面這段 Elixir 範例:

1
2
3
4
5
6
"ruby is awesome!"
|> String.split
|> Enum.map(fn(x) -> String.capitalize(x) end)
|> Enum.join(" ")

# 得到 "Ruby Is Awesome!"

它做了「把字串接開」→「把每個元素的首字改大寫」→「把各個元素組回字串」。其中中間 Enum.map/2 那段可以再改成這樣:

1
2
3
4
"ruby is awesome!"
|> String.split
|> Enum.map(&(String.capitalize/1))
|> Enum.join(" ")

像這樣可以把前一個 function 執行的結果,一路往下一個 function 接下去,可以讓每個 function 的「任務」分得很清楚,隨時可以再增加或刪除,個人覺得這樣超有趣的!

Metaprogramming

習慣 Ruby 之後,程式語言有沒有直接支援 Metaprogramming 的功能對我來說就會變得很重要。Elixir 直接就有支援 Metaprogramming:

其實我不太確定 Metaprogramming 該怎麼翻成中文比較適當,不過請大家先看看這張截圖:

elixir

從帳面上的數字看起來,放在 GitHub 的 Elixir 程式語言專案,有 89.7% 的內容是用 Elixir 這個程式語言寫的。咦?有覺得哪裡怪怪的嗎?也就是說這個程式語言,有將近九成的組成都是 Elixir 這個程式語言本身。用自己寫自己,我覺得這超酷的!

在 Elixir 要使用 Metaprogramming 的技巧,主要都是使用 macro 搭配 quoteunquote 來撰寫:

再從 Metaprogramming Elixir 書上借個例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
defmodule Math do
  defmacro say({:+, _, [lhs, rhs]}) do
    quote do
      IO.puts "#{unquote(lhs)}#{unquote(rhs)} 等於 #{unquote(lhs + rhs)}"
    end
  end

  defmacro say({:*, _, [lhs, rhs]}) do
    quote do
      IO.puts "#{unquote(lhs)} 乘以 #{unquote(rhs)} 等於 #{unquote(lhs * rhs)}"
    end
  end
end

先不管其實這程式看起來怎麼樣(好啦,其實有點不太容易懂),但用起來的樣子像這樣:

$ iex math.exs
Erlang/OTP 20 [erts-9.1.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Interactive Elixir (1.5.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> require Math
Math
iex(2)> Math.say 1 + 2
1 加 2 等於 3
:ok
iex(3)> Math.say 2 * 3
2 乘以 3 等於 6
:ok

發生什麼事了? 我先把 1 + 2 透過 quote 拆解成這樣:

iex(1)> quote do: 1 + 2
{:+, [context: Elixir, import: Kernel], [1, 2]}

這等於是直接在操作 AST(Abstract Syntax Tree)了,這超酷的。可以做到這種層級的操作,我想大概什麼功能都能寫得出來了。

其實在 Macro 在 Elixir 的應用非常廣,甚至後來有次無聊去翻 Elixir 的原始碼才發現,原來在 Elixir 裡,連 if...elseunless 之類看起來像關鍵字的語法,就是用 Macro 的方式寫出來的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 檔案位置:lib/elixir/lib/kernel.ex
defmacro if(condition, clauses) do
  build_if(condition, clauses)
end

defp build_if(condition, do: do_clause) do
  build_if(condition, do: do_clause, else: nil)
end

defp build_if(condition, do: do_clause, else: else_clause) do
  optimize_boolean(
    quote do
      case unquote(condition) do
        x when x in [false, nil] -> unquote(else_clause)
        _ -> unquote(do_clause)
      end
    end
  )
end

defp build_if(_condition, _arguments) do
  raise ArgumentError,
        "invalid or duplicate keys for if, only \"do\" and an optional \"else\" are permitted"
end

如果你仔細看上面這段原始碼,就會發現在 Elixir 的 if ... else 其實就是 case ... when 而已,這真的太有趣了 :)

對 Macro 有興趣的話,可以再參考官網上的文件

其它我覺得有趣的…

可以省略小括號

這對別的程式語言的人來說可能沒什麼感覺,但對寫習慣 Ruby 的人來卻是一大福音。

有 REPL 可以用

REPL 是「Read-Eval-Print Loop」幾個字的縮寫,許多程式語言都有提供這樣的工具,以 Ruby 來說是 irb,而在 Elixir 則是 iex。在終端機環境下輸入 iex 指令後會進入互動式的環境,可以在這裡試驗或練習程式語法:

iex

跟 Ruby 的語法有像

這對已經習慣 Ruby 語法的人來說算是福音,但別誤會,即使從 Ruby 轉換到 Elixir 也不會是完全無痛,畢竟 Elixir 是一款函數式的程式語言,沒有物件導向的那些類別、物件的東西,這點需要花一點時間習慣。

小結

學 Elixir 可以幹嘛

學這個可以幹嘛喔?想幹嘛就幹嘛,學習本來就不需要為公司、不需要為長官、同事、不需要為別人,只為你自己,你自己覺得有趣最重要!

話是這樣說沒錯,但實際一點,你爸媽可能還是會想問你學這東西要幹嘛?學這個找得到工作嗎?

如果想要開發網站應用程式,有 Phoenix 這款 Web 開發框架可以用,Phoenix 較早版本跟 Ruby on Rails 有 87% 像,對現有的 Rails Developer 來說還算是滿友善的(但改版後長得有點不太一樣了);另外想玩硬體,也有 Nerves 可以研究一下。

聚會

目前 Elixir 在全世界的人口數還不算多,就我觀察,在台灣應該就只有一小群人在用。不過每個月都有聚會,目前也有自己專屬的 Facebook 粉絲專頁

AD 圖片來源:Shiseido 官網

借用該知名保養品品牌的宣傳台詞「遇見『水玉光』,遇見更好的自己」,小改一下變成:

遇見 Elixir,遇見更好的自己!

研討會

雖然在台灣的使用人口還不算多,但我們明年在辦 RubyConf Taiwan 的時候,會把 Elixir 也正式的納入議程(就說 Ruby 跟 Elixir 是好朋友了)

反正在國外的 RubyConf 也越來越多的 Elixir 議程,即然這樣,我們就光明正大把辦在一起吧!

RubyElixirConf Taiwan

除了 Ruby 程式語言的老爸松本行弘之外,也邀請到了 Elixir 的老爸 José Valim 來擔任主題演講。

咦?說到底這篇竟然是 Ruby X Elixir Conf 的業配文啊,可…可惡!

為你自己學 Git

離上一篇文章已經是一個月過去了,又好陣子沒寫 Blog 文章了,其實是在忙別的事(藉口)。這回本來在忙的是公司的線上課程,但因為在準備這個線上課程的過程中需要先準備課綱及講稿,結果就不知不覺的把一本大概 300 頁約 15 萬字左右的書寫出來了(我也不知道是怎麼辦到的)。

既然都寫出來了,而且我自認這些我會的東西都是從網路上學來的,所以也沒什麼好藏私,就一樣放出來給大家參考。

網址:http://gitbook.tw

「為你自己學 Git」,如其標題,學習不需要為公司、長官或同事,不需要為別人,只為你自己。

learn git

所有內容都是我在五倍紅寶石培訓課程以及線上課程「人生不能重來,但 GIT 可以」所用到的教材,若發現內容有誤或有任何問題,歡迎直接來信,或是在該章節頁面下方留言 :)

除了少數幾個章節外,HTML 版本的內容將會在網路上供大家參考,不會收費;實體平面出版物目前已與出版社洽談中,應該這一、兩個月會有下文。當然,線上課程也是希望大家多多捧揚。

希望這本書的內容對大家有幫助。如果您對我們其它的培訓課程有興趣,歡迎您參考這個連結

「你知道 Git 是怎麼一回事嗎」

五倍紅寶石學院推出第一波線上課程 - 人生不能重來,但 GIT 可以,預計於八月底上線,現在預購可享九折折扣。同時配合 ModernWeb 2017 活動,在購買 Git 課程時候可使用折扣代碼「ModernWeb2017」,可再扣抵 300 元費用,有效期限僅到 8/19 止。

你知道 Git 是怎麼一回事嗎

「你知道 Git 是怎麼一回事嗎」這是我在今年 ModernWeb 研討會上分享的講題。這個主題基本上算是一個科普等級的分享,主要是介紹關於 Git 一些你可能知道,也可能還不知道,或是以為已經知道但其實是不知道的東西。

適合對象

主要適合平常工作有在用 Git 或是曾經有用過 Git,或是大概略懂略懂 Git 的朋友,如果這是你第一次看到這三個英文字母的組合,有滿大的機會你可能會不知道我在說什麼。但也沒關係,既然都來了,就安心坐下來吧,就把我當做是天橋底下說書的,當故事聽也可以。

由於場地及投影設備不是非常理想,在場地中、後排的朋友應該看不太清楚台上在表演什麼,轉出來的簡報檔又都是靜態的,無法看到真正原本的樣子。再加上本回主辦單位似乎好像也沒有提供錄影服務,剛好晚上也醒著,於是我就自己愛現的再錄了一次,供大家參考:

投影片連結:https://speakerdeck.com/eddie/ni-zhi-dao-git-shi-zen-mo-hui-shi-ma

有任何問題,都歡迎留言或來信討論 :)

Git 簡單嗎? 困難嗎?

大家覺得 Git 很簡單嗎? 還是很困難? 不就是 git add,然後 git commitgit push 這樣而已嘛,沒什麼難的吧?

我想在座的各位的答案應該跟我差不多:「Git 不好學」,不然大家今天就不會坐在這裡聽我講故事了。Git 是一種看起來不太難但其實很難精通的一種工具,要真的好好的使用這個工具,正確的觀念不可少。

也許你曾經使用過 CVS 或 SVN 之類的版控軟體,但 Git 在設計上跟這些版控軟體有本質上的差異,所以如果各位只是把 Git 當做是 SVN 的加強版的話,那在學習上可能容易卡關,或是誤解。像是他們處理檔案的方式、使用分支的方式等等,都有很大的不同。

20/80 法則

在 Git 裡的指令,主要有分兩種,一種是比較底層的,稱之 Plumbing,另一種比較高階的,稱之 Porcelain,早期版本的 Git 大部份都是底層指令較不易上手,後來才慢慢的加入了比較高階的指令,例如 add、commit 等這些都是屬於高階的指令。還好,我們平常用到的指令雖然不多,但已經足以應付平日的工作了。

一定要認識一下的四大天王

在 Git 的世界裡,有 4 種物件一定要認識一下,分別是 Blob、Tree、Commit 以及 Tag 這四種物件。其中,Blob 物件主要是存放檔案內容,Tree 物件主要是存放目錄以及檔案資訊,Commit 物件,看名字就知道是存放 Commit 的資訊,而 Tag 物件,也就是存放跟 Tag 相關資訊的物件(更正確的說,其實是 Annotated Tag 而不是一般的 Tag)。

在使用 Git 開始進行版控後:

  1. 當開始把檔案加到 Git 的暫存區(或稱之索引區),Git 便會開始生出一些 Blob 物件。
  2. 當開始進行 Commit,Git 便會產生出一些 Tree 物件,指向剛剛那些 Blob 物件。或是可能會有其它的子目錄,所以 Tree 物件也可能會指向其它的 Tree 物件。
  3. Commit 的同時,也會產生出 Commit 物件,它會指向某一個 Tree 物件。而除了最一開始的 Commit 之外,所有的 Commit 物件也都會指向它的前一個 Commit 物件。
  4. 最後,Tag 物件則會指向某一個 Commit 物件。

這四種物件的關連圖大概長這樣。

其實 Git 不在乎你!

很重要的觀念:「Git 只在乎檔案的內容,不在乎目錄或檔案名稱」,相同的內容的檔案,不管有多少個,在 Git 裡面都只會存一份而已。而 Git 使用的 SHA1 雜湊演算法,正是使用「內容」來進行計算的。

其實,Git 只是個內容追蹤軟體,只是剛好它可以被拿來當版控軟體而已。

Git 的 SHA1 怎麼算出來的?

以 Blob 物件的 SHA1 計算公式為例:

  1. 「"blob" 字樣」
  2. 「1 個空白字元」
  3. 「輸入內容的長度」
  4. 「Null 結束符號」
  5. 「輸入內容」

用一段 Ruby 的程式碼來說明:

1
2
3
4
5
6
7
require "digest/sha1"

content = "Hello, 5xRuby"
input = "blob #{content.length}\0#{content}"
puts Digest::SHA1.hexdigest(input)

#=> "4135fc4add3332e25ab3cd5acabe1bd9ea0450fb"

什麼是分支(Branch)?

有些人會把分支當做是「把檔案複製出來一份改,改完之後會再合併回去,所以在改的時候才不會影響到原來的分支」,但其實 Git 的分支不是這樣的。另外,為什麼大家常說在 Git 使用分支很便宜? 那是有多便宜?

因為,說白了,分支只是一個指向某個 Commit 的指標,所謂的分支,其實就只是一個有 40 個字元的檔案而已,不相信的話讓我們來看看:

$ cat ./git/refs/heads/master
0ea8463352e5fcac14b9bad84b691058cbbf8eb1

Git 的分支沒什麼,就只是這樣一個檔案而已! 如果你仔細觀察,便會發現這串 SHA1 值,正是某個 Commit 物件的 SHA1 值:

$ git log --oneline --graph
* 0ea8463 add c.html
* 632dca8 add abc
* e368aa4 init

注意到了嗎? 它正指向最後一次的 Commit 0ea8463

所以,為什麼說在 Git 使用分支很便宜? 因為所謂的分支,就說它只是一個 40 個字元的檔案罷了,所以當然不貴。

什麼是 HEAD?

HEAD 是一個指向某一個分支的指標,在分支切換(checkout)的時候,HEAD 會跟著指向切換過去的那個分支。

所以再回顧一下前面那張 4 個物件的圖,每一個分支,都會指向某個 Commit 物件,而 HEAD 則會指著某一個分支:

猜猜看,Git 是怎麼知道現在是哪一個分支?

在 .git 目錄裡有一個名為 HEAD 的檔案,它會記錄目前是在哪個分支的資訊:

$ git branch
  cat
* master

$ cat .git/HEAD
ref: refs/heads/master

可以看得出來現在 HEAD 的內容是指向 master 分支的,接著切換到 cat 分支:

$ git checkout cat
Switched to branch 'cat'

$ cat .git/HEAD
ref: refs/heads/cat

看到了嗎? 這個 .git/HEAD 檔案就是記錄著目前所在的分支。

標籤(Tag)是什麼?

標籤其實是跟分支有點像的東西,差別只在於在 Commit 發生的時候,分支會隨著一起往前移動,但標籤一旦定下來之後就不會再移動了。大家也許看過「海角七號」電影,用電影裡一句很紅的台詞「留下來,或我跟你走」舉例,留下來的是標籤(Tag),跟你走的是分支(Branch)。

沒有蠢問題

有沒有人想過以下這些問題?

Q: 一定要有 Master 這個分支嗎?
A: 其實也不一定,分支就只是一個像貼紙或標籤一樣的東西,想叫什麼名字都可。

Q: 合併過的分支可以砍掉嗎? 為什麼?
A: 看你心情,你想砍就砍,或是想留做紀念也可以。分支也只是一張貼紙而已,砍掉分支只像是把這張貼紙撕起來而已,不會影響原來已經存在 .git 目錄裡的物件。

Q: Master 分支可以砍掉嗎?
A: 可啊,再次強調,分支就只像是一張貼紙一樣,想撕就撕,唯一的限制就是,你要撕這張貼紙的時候,不可以踩在這張貼紙上,不然撕掉之後要去哪裡?

這些問題可能看起來有點蠢,但其實只要觀念是正確的,這些問題根本也算不上是問題了。

得罪了方丈還想跑…

其實東西進了 Git,想要把它刪還不太容易,不管是檔案不小心被刪了,或是還沒合併但卻被刪掉的分支,甚至被 Hard Reset 的 Commit,一樣都救得回來。操作細節請見影片介紹。

工商服務 Part 1 - 為你自己學 Ruby on Rails

最近給出版社一本書,是關於 Ruby on Rails 的入門指南,這是我們家在培訓 Ruby on Rails 學員時候會用到的教材。目前正在校稿中,我看了一下,大概 400 多頁,我也不知道我是怎麼辦到的,就發揮了我囉嗦的個性,一直寫寫寫就寫了這麼多了。沒意外的話,大概九月會上市吧。

所以內容均放在網路上,可免費閱讀,有需要的可自取。

網址:http://railsbook.tw

工商服務 Part 2 - 五倍紅寶石學院上線啦

之前常有朋友提到因為時間無法配合,或是人在中南部的緣故,無法參加我們家舉辦的課程。於是,我們開始準備線上課程了,希望之後可以讓更多的朋友在線上參與我們的課程。

網址:五倍紅寶石學院

image

課程預計將包括 Ruby/Ruby on Rails、Elixir/Phoenix、Git、CSS.. 等內容。目前第一波是 Git 課程,將於八月底上線,現在預購可享九折折扣。

線上課程網址:人生不能重來,但 GIT 可以

如果您還是比較偏好實體課程,也可參考這個連結

image

同時配合 ModernWeb 2017 活動,在購買 Git 課程時候可使用折扣代碼「ModernWeb2017」,可再扣抵 300 元費用喔,有效期限僅到 8/19 止。

為你自己學 Ruby on Rails

好陣子沒寫 Blog 文章,其實是在忙別的事(藉口)。雖然 Ruby on Rails 的學習資源向來不少,但看了一下坊間關於 Ruby 跟 Rails 中文書並不多,特別是專門給新手更少,於是在今年趁著參加 iTHome 舉辦的鐵人賽活動,把之前寫了一百多頁的 Rails 書拿出來繼續寫下去。

網址:http://railsbook.tw

「為你自己學 Ruby on Rails」,如其標題,學習不需要為公司、不需要為長官、同事、不需要為別人,只為你自己。該書所有內容是我在五倍紅寶石 Ruby on Rails 培訓課程所用到的補充教材,將以 Ruby 2.4.1 以及 Rails 5.1.0 之後版本為主,若發現內容有誤或有任何問題,歡迎直接來信跟我說(eddie@5xruby.tw),或是在該章節頁面下方留言 :)

HTML 版本的內容將會在網路上供大家閱讀,不會收費;實體平面出版物以及 PDF 電子書版目前已與出版社洽談中,應該近幾個月會有下文。

希望這本書的內容對大家有幫助。當然,如果您對我們的培訓課程有興趣,歡迎您參考這個連結

再見 2016,哈囉 2017!

2016 年快結束了,今年是挺忙的一年,發生了不少有趣的事。

2016 年幹了哪些事

校園推廣

一直以來我跟公司的夥伴都很希望可以把 Ruby 這個有趣且富生產力的程式語言推廣給更多的人,

今年還是有到交通大學、台灣大學、清華大學以及台北商業大學等學校持續的去洗腦宣傳 Ruby。感謝學校跟同學們的邀請,有機會能跟同學們介紹 Ruby 是個什麼樣的工具,以及如何使用 Ruby on Rails 快速開發網站。

數了一下自己去過的學校,發現已解除在「台清交成」演講的小確幸成就。

玩樂

今年九月份公司的日本員工旅遊:

image image

以及一家四口由關西到關東的遊山玩水:

image image

勉強算是有個交待了。

公司

今年大部份時間都是在忙公司的事,主要有幾件大事:

人員

在 2015 年年底,公司人數僅有 8 人,現在 2016 年年底,公司人員正職人員已有 17 員,加上長期配合的實習生及外發單位人員,再外掛一隻脾氣差的貓,公司人口平常已有 20 人上下,已經到了那種搭電梯要分二、三次才能全部下去的狀況。

順利的話,也許明年估計還會再繼續增加 3 ~ 5 名同事(希望坐得下)。

搬家

因為人員增加了,再加上原來的辦公室一開始就不是設計來工作的,老實說工作環境並不是很好,大家常會因為課程或活動需要移動自己的座位。算了一下,似乎公司今年有些盈餘,雖然原來的租約還有 3 年,還是在今年 7 月開始找新的辦公室。找了好陣子,最後找到在台北市 228 和平公園旁邊的一家瑜珈教室:

image

這個地點的生活機能很不錯,外面也有不錯的公園景色,不過隔間、天花板、地板跟冷氣都不適用,所以幾乎是整個砍掉重練:

image

image

雖然花了七位數的錢錢,裝潢了一個半月,不過可以提供給同事們更好的工作環境,也是值得的。

有陽光照得進來的落地窗: image

有個可以看公園景色的休息區: image

如果坐累了,也有地方可以站一下: image

推廣 Ruby 是我們一直以來的目標,所以教室區是一定要的: image

除了自家課程外,也提供給社群活動使用。

感謝同事們的不離不棄,在環境沒有很好的時候也還願意留下來幫忙。

投資

也許有些朋友已從其它媒體得知這個消息,就是我跟幾位社群朋友成立的公司 - 五倍紅寶石 被新加坡電商 Shopmatic 投資,成為其集團之子公司。

image

Shopmatic 是我們長期合作的客戶,從 2015 年 8 月起就開始開發電商開店平台,雙方合作一直非常愉快。後來 Shopmatic 也希望擁有一個專屬的開發團隊來提供更穩定的開發能量,因此與我們開始洽談投資事宜,直到今年 12 月才算完成所有投資程序。

雖然我們是 Shopmatic 在台灣的子公司,現有服務和專案都會持續,不會有太大異動。當然,社群活動也是一定要繼續進行的。

許願

年紀越大,越不敢亂許願(因為許了做不到也是沒用)

  • 希望小朋友們可以繼續平安長大,2017 年也可以再帶他們一起來去旅行。
  • 希望繼續推廣 Ruby 給更多人知道。
  • 希望可以把該寫的出版物完成。
  • 希望公司生意… 順利就好。

願望許完了,2017 年也要繼續努力!