4 days ago

我在兩年多前寫過類似的這樣一篇文章

現在我的想法轉變成:我認為不應該導入,而是應該導入 MDD ( Money Driven Development ) 。

到底現在這篇文章是要闡述什麼邪魔歪道?

重看我當年的那篇文章,我想我寫那篇文章時犯下跟很多程式師,以前從來沒想過的一個問題:對 startup 定義錯誤。

在繼續講下去之前,我想我要把我近兩年來理解到的一些名詞再重新寫一次,後面的文章脈絡才能拓展開來。

Startup

Startup 是有一個點子,你認為可行,於是你想要嘗試這個商業模式,或者是將你想像的概念轉換成商業模式。

Company

而 Company 是你有一個已經稍有形狀的商業模式了,你想固定下來,以一個商業組織的形體去營運。

程式設計師加入多半的是 Company 不是 Startup

絕大多數的程式設計師都是加入 Company(因為 Company 才有錢付給工程師去每天專心優化塑形商業模式),而不是 Startup。只是很多大家以為的 Company 根本連商業模式沒有,天真的以為程式寫出來,交付正確的 Spec ,消費者就會自動買單。

Startup 需要的是不斷探索什麼行為是真的可以賣錢的。為了達到這件事,未必需要寫程式,可以是放需求表單,可以是用露天拍賣,可以是用 FB 訊息交易,可以是用 FB 養觀眾。

這些,可不可以自己寫程式達到?可以,只是成本超級高,高到難以想像的地步。同時,程式設計師通常也不希望做這樣的工作,因為他們會覺得「老闆是王八蛋,什麼都沒有想清楚就叫他們做。」

所以程式設計師通常本質上加入的是一個 company,只有已經確定要做什麼了,程式設計師拿到「確定的需求與模式」,將之塑形。

正常的業界

接下來要討論,為什麼有這樣的爭議。原因在很多的「公司」,進行軟體專案的方式是在一般人眼中是很奇怪的。

首先,他們會任命一個不懂生意也不懂技術的人,其實是一個跑腿人物,負責「跟老闆或 BD搜集需求」再「寫 Spec」再「請工程師完成」,擔任一個翻譯的工作。這個職位叫 PM。這也是大部分專案完蛋的原因。

既然是「翻譯」,那中間的那個人兩邊的語言都不會說,你覺得會發生什麼事情?當然是交付錯誤(與 BD 所要的的解決方案不同)。程式設計師為了解決「翻譯者」能力低落的問題,主張中間應該不需有翻譯。所以開始主張 BDD。

實作一個軟體時,需求者應盡量提供原始情境:

1) 誰會使用這個軟體
2) 使用者在操作時會產生什麼情境。
3) 基本邏輯
4) 什麼是必要的,什麼是應該可以有的,什麼是完全不能做的。
5) 以 Story 敘述,而不是 Spec。

讓程式設計師,可以盡量出設計貼近可以解決原始需求(程式設計師稱之為『正確』)的方案。

好了。回到 Startup 與 Company 的話題。這套手法在 Company 行得通,也必須。因為中間需要經過太多的合作人員,所以我們要透過這樣的手段,盡量減少「翻譯」Cost。

Startup 本來就不是規模化自動化的階段

但是 Startup 需要 BDD 嗎?Startup 都沒人沒錢沒時間耗一天到晚在實驗新需求了,怎麼會是需要用到 BDD 這樣的技巧。Startup 所需要的是 Money Driven Development。只做賺錢必須的功能,找到幾個有錢賺的模式,能 Scale 需 Scale,那時候大家才有興致談 BDD 。

所以 Startup 前期應不應該導入 TDD / BDD?我現在認為這兩個名詞根本不是可以放在一起討論的東西。

就跟我覺得 Startup 跑 Scrum 是奇怪的做法一樣。

(我不是反 Scrum,Scrum 的一些手段對於釐清時程,Story ,權重。不管是專案大小都很有幫助。但是不是每個團隊都可以導入或適合這套流程的。)

 
17 days ago

這是最近做產品的一些雜感。放在 FB 有不少迴響所以貼過來。

做產品 = 「解決問題」

很多人做產品,包括我很久以前做產品。其實都犯了一個很大的謬誤。就是太早寫 code,甚至是說太早寫 spec。

做產品,精確地來說,就是在「解決問題」。

很多產品之所以會失敗,就是可能下決定的那個人(有可能是 Founder,有可能是 PM )看到了問題,先做了第一個假設性的解法,並決定將之 implement。

因為這個假設性的解法,很可能是有盲點的。但 Founder 或 PM 下了命令,它必須得執行。團隊覆對實作手法產生了矛盾大吵特吵。經過了大半天,合作的眾人才可能發現。原先被設定的解法,可能是錯誤的。

甚至當初被武斷所下的結論,甚至也可能是錯誤的。甚至再追溯下去,還可能發現原來的那個問題是假問題。

一旦太早由個人所推出的結論規格化,並且放到整組人馬的生產線上。後面自然可能巨幅浪費資源,甚至可能因為其他面子或政治問題再也難以回頭。

由這個主題延伸談下去的部分可以往下繼續談:

  • 創業 MVP
  • 寫 code 是否 tdd, 是否需要早期架構封裝化
  • 好的稱職 PM 應該為團隊做什麼

創業 MVP

一些活躍的網路從業人員,創業的 pattern 是:因為有著精湛的 coding 技術或者其他網路資源,所以想創業時第一想到的就是蓋平台 => 找錢。或者是先寫 code 再 pitch 找錢。

事實上這是錯的。

創業,實質上就是解決問題並將之商業化。

要先找到了想付錢的買家,再有了初步方案,再透過前幾筆的銷售確定的這個解決方法可以 work。再想要把這個過程 automated 化。automated 的這一步才是寫 code。

之所以為什麼很多時候,想發包給接案公司的客戶或者是公司內部的 PM 連 User Story 都寫不出來。那是因為他根本連自己的商業模型都沒有 run 透想通。既然沒有想通,何來 automated 化。

這中間大部份的實作者(aka RD)都沒有錯,因為在不知道你想解決什麼問題之前,能做的只是能憑藉著過去的經歷與想像把類似的模型蓋出來。

創業與做產品就是在一個一個回覆客訴與處理危機的過程中,慢慢把模型砌出來。

當然,沒有人說這個成本很低。

只是大部分沒有悟通這件事的人,會選擇在一開始就想閃避這件事的風險,例如一開始就創業者「想建立平台讓大家上來用」,PM 一開始就寫出「詳細的規格」。

結果在中間實做 Interact 的時候造成了更大的風險,甚至產生結不了案,錢提早用完的悲劇。

開發產品是否需要 TDD,是否在早期就需要將架構封裝化

實際上寫 code 的也是會遇到類似的狀況。

有些個性過於要求完美的 RD,也是會做出類似的事。明明只是一個簡單的功能,卻 Over Architecture。程式碼很漂亮,但是改不動。

程式碼只是表達解決方案的一種手段。

Over Architecture 或過於封裝的程式碼往往不是去除程式債,反而是新增的程式債。

因為這些人的過於封裝,不是增加 Story 的可讀性或維護性,他們的修改手法,反而恰恰把 User Story 支解到無法辨讀。大大造成隊友擴充功能或者修改方向的困難。

同理,什麼時機寫 Test

  • (後補 Test ) 你已有了粗略的方案,你想要將之塑形化,並且希望他不會在意料之外的情境下發生。同時避免其他人以後修改這段程式碼時,破壞了執行結果。
  • (先寫 Test ) 你手上拿到了一個非常清楚只是要重複的方案。你要用結果驗證你的 automated 方案是無誤的。

程式碼的乾淨度與創業成功的因果關係

同理,Code 的乾淨度與創業成功也沒有正相關,至少,在最初期沒有正相關。

Code 的乾淨度與 Project 成功的正相關度是受到 RD 教育訓練的影響產生的迷思。

大多數成功的專案,專案 code 都很噁心。至少在一開始很噁心。創業要的是正確的解決方案,而不是優美的 coding style。就如同創業公司的 Stage 演變。沒有人 care 你是怎麼優美的解決,人人只要買解決,而不是你多優美的解決。

什麼時候 code 會變得乾淨,當你有 A round 的錢,B round 的錢時候。有錢 hire 資深人士 refactor的時候。
你的「生意模式」需要「塑形化」,需要「水平擴展」化。這時候你的 code 就會變得乾淨。

不是一開始你的 code 就「先行塑形」「先行水平擴展」,那麼就會成功。而是一開始的主意 works,由生意驅動的 refactor。才帶來後面的 clean code。

只是人人往往倒果為因。

PM 的職責

PM 的職責是什麼?

既然創業做產品是解決問題。PM 的職責是負責去搜羅資源負責讓實作者更能設計出正確方案的或者接近類似方案的人。而不是「方案制定者」。

很多爛網路公司的產品會失敗,是因為請了不懂實作的 PM 亂寫規格,導致的黑暗混亂與巨幅浪費資源。之所以這些 PM 不懂實作,是許多 RD 認為「搜羅資源與需求」不需要技術(他們自己也懶,而且 RD 喜歡寫 code 當戰士勝於在前面當坦克)。

而 PM 又認為自己是 "Manager",既然他負責搜羅這些資源,就有權力引導甚至是決定專案的方向。

如果你仔細觀察,打造出成功產品的 PM ,往往有技術背景。

一個成功的 PM,應該具備下列特性

  • 能夠協助 Unpack 問題本身
  • 能夠協助引導討論方向
  • 能夠協助搜集幫助討論方向的資源
  • 具備一定的實作能力知道資源的限制與 Tradeoff
  • 引導溝通
  • 緊盯資源的花費與加速或放慢專案的進度
  • 花上大量的時間與專注力在 improve 團隊溝通速度與方法

因為實作產品,本身就是一件協調眾人之力,釐清問題,溝通,Prototype,Implement 並balance resource 的過程。

 
about 2 months ago

我們公司系統裡面有一個使用情境:有一個 method 要去查詢一個 Order,路上哪些司機車上放的貨可以送單,甚至這些司機可以要設定條件多少距離內可以送。

OK.

  • order has_many sold_products
  • sold_products belongs_to menu_item
  • driver_session has_many driver_session_items
  • driver_session_item belongs_to menu_item

這個使用情境就是要對 driver_session 造一個 scope 然後丟貨物需求數量,回傳可以繼續串接下去的 ActiveRecord::Relation。

一般 method 實作想法會是

  • 我先去問路上有哪些司機,身上有載客戶所要的貨
  • 然後對這些司機一個一個對他身上的貨夠不夠送
  • 然後列出這些司機的名單

虛擬碼會是

def my_method(order)
  results = []
  on_road_drivers.each do |driver|
    resuls << driver if driver.can_ship_this_order(order)
  end
end

然後再去下 on_roard_driver 和 can_ship_this_order 的條件。問題是這會有 db 掃描的問題。有 20 個 driver,3個 driver_session_item 就要問 20*3 = 60 次。有 10 個單要問就要問 600 次。(這是純 Ruby 解法,不是 SQL 解法)

下 SQL 難度沒有太高。不過難的是如何用 ActiveRecord 把這個作法拼出來,還能維護。

先說最後解法。

  module ClassMethods
    def fulfill(item_hash)
      item_hash.map {|item_id, amount| joins(:driver_session_items).merge(DriverSessionItem.where(:menu_item_id => item_id).where("available_qty >=?", amount).select(:driver_session_id))  }.reduce(scoped) { |scope, subquery|
        scope.where(id: subquery)
      }
    end
  end

主要想法是用 array 的 map 拼 SQL 出來再塞 subquery。是的,scope 可以用這種奇技淫巧用 map 出來再塞回去組 query。ActiveRecord 翻譯的動...

延伸閱讀可以看這兩篇:

http://stackoverflow.com/questions/6686920/activerecord-query-union
http://stackoverflow.com/questions/11838537/query-intersection-with-activerecord

不管你是要做 UNION, INTERSECTION 或者是多條件的 JOIN 都可以用這種密技解。而且 code 可以維護,不用真的寫 SQL。

 
2 months ago

每年過新年前夕就會看到一堆人在討論專案管理工具或方法 XDD

大概是這時候各 Manager / Lead 現在才有喘息的時間可以來 Survey 工具。然後趁這個過年大 break 一口氣改掉專案進行方法。上一次寫這方面的懶人整理包已經是三年前。我也來整理新版的心得。

有興趣的可以配我之前的文章看

網站程式上線前需要準備的事 ( 2012/3 撰)

專案管理之道在「協調」

在談如何挑專案管理工具或方法之前。有一個中心原則很重要,我覺得必須要寫:

「這世界上沒有一套大一統的管理術,還有神奇專案追蹤工具。不會讓你裝了之後大家就變成超級賽亞人,人人練成通靈術。」

而專案管理也不是大家想的那樣,學了以後「命令」「指揮」大家做事比較有效率,專案管理是「協調」大家「一起做事」的技巧。

「協調」,「協調」,「協調」!

很重要所以要講三遍!!

瀑布與敏捷

專案進行方法有幾種,瀑布式,敏捷式(還有分 Scrum, Kanban, Scrum + Kanban ...) ,到底哪種比較好?

我的看法這幾種方法是因運組織以及組成人事有關。

有很多人講敏捷就要先幹瀑布式一下。抱怨只是做個簡單的東西結果 spec 被不專業的人花上很多時間寫了一堆廢物,拖了一堆時間結果 delay,實際實作時卻脫離現實。

我個人認為這其實跟組織運作有關。通常一個組織會出現「瀑布式做法」,通常已經代表這個組織太大或太冗了或者缺乏合作情感。頭無法控制到腳,或者 pm 根本無法跟實作團隊建立互信,或者根本是與不熟的外部團隊(外包)合作,為了避免產生糾紛才會有這種做法。

Spec 與 Story

寫 spec 跟 story 也是不一樣的東西。

spec 是很精確定義要做什麼,細節要做到怎麼樣的程度,不容修改。這適合你已經知道要做什麼了,你這次要做第二遍第三遍,所以只是重複上一次要做的東西,然後加上局部修改。

而 story 是你有一個使用情境,但你不知道確切成品會長成什麼樣,所以我們需要有一個 story「讓參與專案的人反覆討論改進」。

讓「讓參與專案的人反覆討論改進」

「讓參與專案的人反覆討論改進」「讓參與專案的人反覆討論改進」「讓參與專案的人反覆討論改進」

這件事超重要。所以也要講三遍!

我相信大部份的軟體開發與情境,都是不知道確切成品會演化成什麼樣。所以比較適合的是「敏捷式」與寫 Story 。

這也是本文要接續寫下去的方向。

Scrum or Kanban ?

好了。屁了這麼多廢話,到底要選哪一種?

好。先講結論:不要選 Scrum XDDDDDDD (那些靠教 Scrum 賺錢的不要揍我)

沒有啦。其實我沒有想要擋人財路。Scrum 很好,但是我會勸你去學 Scrum 但不要「導入」Scrum。(好吧看起來還是很欠揍,有人可能又會跟我吵那是因為 Scrum 學不到位才會講這種妖魔鬼怪的言論)

OKOK。我承認我不是什麼敏捷高手,只是低手。我只是在寫我的想法,理性勿戰 XDDDD

我個人對 Scrum 的看法,是 Scrum 是是一整套「工具集」。它是提升效率的一套「敏捷」「Framework」(這也是 Scrum 開宗明義講的)。每一個組織都有每一個組織各自的問題,一次全導 Framework 進去未必會幫到自己的組織,可能還會搞到非死即傷。

Scrum

有些讀者可能對 Scrum 沒那麼熟悉,我大概講一下這套工具箱裡面有什麼:

  1. User Story (敘述我們要解決什麼問題,以及相關的使用者情境)
  2. Story point (每一個 User story 的權重)
  3. Scrum Master, Stakeholder, Team member ( 裡面成員扮演的角色)
  4. Sprint (衝刺週期)
  5. Standup (站立會議,成員每天報告之前做了什麼,今天做了什麼,未來要做什麼,今天遇到什麼難題希望 Team Member 幫忙解)
  6. Retrospective meeting (回顧會議,在這個會議檢討我們這個 sprint 的部分有什麼需要改進的)
團隊難以導入 Scrum 的原因

為什麼很難全導呢?

  1. Story point 要怎樣分(爛票要優先做嗎?可以裝死嗎?政治問題與能力問題)
  2. Team member role (Scrum master 誰當?角色重疊會不會有後遺症。政治問題與能力問題)
  3. Sprint (啊我們一個 Team 同時在做多個 project ,哪有辦法精確估計守備範圍和速度? )
  4. Scrum 重視 Story,大家都在拼 Story point。那 Epic (不在 Story 上的技術問題,但很重要,比如 Refactor 或者是 Performance Tuning )怎辦?

etc.etc.

這些都是導入 Scrum 會面臨到的問題。導入開始產生一堆問題,接著 Team member 就會產生一堆疑惑,大家開始質疑,一個弄的不好大家就覺得比之前複雜超多好累不想弄喔,就 GG 了。

但這表示 Scrum 不值得導入嗎?

不不不。你應該看你有什麼樣的問題要解決,拆進去用,逐一導入。

我在前面的部分就說了:Scrum 是一套工具集,裡面的工具是是真的很不錯。

Scrum 細細說

User story 與 Story Point

User story 的誕生是為了解決在專案過程中,因為負責專案管理的人過於描述細節而把原始目的破壞殆盡的狀況。很多時候,專案經理為了求好心切,甚至過於精確描述實作細節

  • 不僅花費了不必要的時間(講的方案不好
  • 還造成負責實作者的困擾 ( RD 或者 Design 覺得不切實際
  • 甚至 RD 做完了,stakeholder 才講這不是他要的。(因為精確描述時作方法,會造成實作者實作時缺乏上下文,想像錯誤 )
  • 只描述了一部份的細節(比如說只講商店要怎麼結賬,卻忘記講後台也要有後台可以管理訂單)

但做專案重要的是

  1. 中間經手的人通通都理解要解決什麼問題。在什麼時限之前。
  2. 我們手上有多少資源
  3. 我們可以在第一版做到什麼程度
  4. 能不能讓實作者在第一版就解決最真切的問題
  5. 能從不同使用者角度審視這個軟體
  6. 第一版我們要做哪一些功能。哪一些馬上就要做,哪一些可以之後再做。哪一些給 Senior 做,哪一些給 Junior 練手用。

Sprint / Standup / Retrospective Meeting

Sprint

做軟體不能沒有遙遙無期沒有 Release date。也不能「只有一個 Release date」。這會造成花了大把時間卻做歪掉。

或者是 14 天內只要 a,b,c 功能,但實作者卻因為想一口氣做完 a,b,d,e,f, 功能,一口氣報了 30 天才能「通通完成」,結果第三十天才發現 c 沒做。

這就是為什麼必須要有 Sprint。規劃一個短時程,把值得先實做的部分衝刺,邊改邊做小 release。

Standup

而 Standup 的用意不是為了監視 Team member 有沒有做事。而是為了保證每個人「做對事」。軟體開發者不是通靈者,沒辦法 100% 辦法精確 implement。

為了避免劇烈的 misunderstanding 發生,standup 是在每天一個固定時間讓大家交流實作狀控使用。報告現在的狀況,當發生無法實作或者需要改優先權,甚至改實作者(有些 junior 做不出來)的時候馬上可以調整。

可以讓大家常常保持在 same page,對專案有一個清晰的了解,保持士氣。

Retrospective Meeting

同時,為了團體的成長,在 Sprint 結束後,也會有一個回顧會議,去檢討在這個週期中,我們各自或甚至公司有什麼地方可以做得更好的地方。大家一起改進。而非一直忍耐某人某鳥事忍到受不了然後離職。

Scrum 要解決的事

看完這些,你知道 Scrum 要解決的是哪些事了嗎?

  1. 對專案目標的理解程度
  2. 對專案時程的透明程度
  3. 進步,溝通,協調

導入者要先知道自己組織有哪些問題,然後去調整去用工具才有意義。

Kanban 要解決的事

同樣的 Kanban 也是類似的想法。Kanban 沒那麼複雜的工具集。核心就是三個故事版:

  • 未實做
  • 實做中
  • 已實做

目的是為了讓專案所有成員了解現在的實作狀態。從而自己發展各式各樣的輔助方式協助時程內完成一定的目標。

敏捷是怎麼回事?

所以看下來,敏捷是怎麼回事?

  • on time
  • on budget ( resource )
  • deliver correct result
  • communication / collaboration

如果專案管理者只是想要「命令」實作者「通靈」。說真的我覺得導什麼敏捷方法都沒用。

最有效的方式是「擲筊」

我怎麼做專案管理以及用什麼工具?

具體一些細節可以看三年前的系列的文章。就不重複講裡面的內容了。這一段主要是描述現在我怎麼樣做專案的

  • 要做某功能前請某 pm 在 Hackpad 起草 User Story
  • 要開始實作實,用 Redmine 開一串巢狀式的實作票 ( Story, Design, RD frontend , RD backend, RD mobile, QA )
  • Redmine 與 Hipchat / Slack 整合,team member 都可以在 ‪#‎techlog‬ 上看到全部的票的更新狀況
  • RD 依照 ticket 號碼開實作 ticket branch, Senior 根據 branch code review, PM 根據 branch 跑驗收, devops 針對 ticket branch merge 并 deploy.
  • Admin backend 不寫測試,API 與 Service Object 一律要寫測試。code reviewer 不 review 任何 紅燈 branch.
  • deploy 是使用 samson 整合 CI 做 deploy
  • 內部 mobile release 是使用 crashlytics
  • CI 是使用 solanolabs
  • 難以敘述的部分使用 screenshot 與 google hangout 直接講
  • Tech / Design / Mobile team 會用 Hackpad 一有 release 會寫 updates 寄給全公司。

我們現在開發團隊的狀況是:美國,台灣都有 RD。靠這些工具, weekly pm meeting, company tech touch base, engineering demo 與 retrospective meeting 確保公司上下想要的東西是一致的。

平均我們 redmine 一周會產生100-150 張 ticket, rails 的主 branch 一個月 2000 commit,一周大約會 release 5-7 個 major feature。code climate 現在 3.08 分。test coverage 大約 60%,API 的部分應該有 90-95%。

我們怎用 Hackpad?

用 Hackpad 有兩個地方。

1. 寫 User Story。

User story 寫

  • 要完成什麼商業目標
  • 希望出貨的時間
  • 會動用到的 Team
  • 主要的使用者角色以及相關場景
  • 必要 Must / 有時間再做就可以 Nice to have

這時候會起一個 Redmine 的主票,在 slack cc 相關人等上去評論

2. 寫 Product Updates

因為我們 Tech team 開發速度和能量太驚人。非 Tech 的人常常會被新冒出的功能驚嚇到,或者已經上線的功能他們不知道還跑來催。

所以當我們 Deploy 或者要 release build 時,會寫 Tech Updates 寄給全公司。讓大家對我們這一兩天做了什麼有基本的了解。或者做好應有的應對衝擊。

以免產生要馬覺得 Tech 都亂作亂 deploy 功能,或者是 Tech 都 delay 功能的誤會。

我們怎用 Redmine ?

會用 Redmine 是因為試到一個功能其他專案管理軟體「都沒有」。就是「無限的巢狀票」。(我不是說其他套軟體不好。每一套有它適合的專案複雜度)

我們會用巢狀票去切細切碎 Story。Redmine 對於需要跨多 team 合作的專案非常適合。特別是我們幾乎所有的專案都需要 backend, front, design, 還要 release 到三個 client 上。

同時,切碎 Story 也有助於 RD 專精在功能的思考與任務分配上。其他專案管理最大的缺點就是通常只有兩層 Task。不太夠用。
就算是寫一個中型功能,RD 有時候也會遇到 nice to have, tricky bug, edge case, complex implementation, 不拆票很容易就鬼打牆。junior 更是不拆票就當場死,而且還死在非常前面。redmine 可以幫助 RD 有自我 task management 的習慣。

redmine 還有 related ticket 可以用。大家可以用 related 串來串去,related to / block by 之類的。
我們通常會這樣切票,

master 票,下有

  • story 票
  • design 票
  • backend 票
  • fnd 票
  • ios 票
  • android 票 implementation 做完會關掉開 QA 票。

然後因為我們公司有太多線 project 還有軟體有太多 phase release 要管了。所以我們還有一個 basecamp 去管這些 release。不然會管到爆炸..

Take away

所以結論是什麼? XDDDDD

結論不是我告訴你哪一套軟體或哪一套流程比較好。然後你回家照著用結果處處踢鐵板。

反省團隊的根本效率問題是什麼

而是要認真去檢視你到底要解決團隊裡面的什麼問題,一次解一個問題,遇到問題再去翻書逛 blog。

很多時候不是某某書上沒寫什麼,或者是某個作者對某方法或某軟體有強烈的偏見。而是你再找解法時,沒有認真先去 identify 你的問題到底是什麼。(「效率不彰」本身不是一個「詳細的問題」)

就連我自己寫不同專案在不同場景時也會用不同工具 Set 了。有時候我自己寫 side project 根本沒有 user story 也沒有 project management,甚至連 branch 都不切,Test 也不寫,但這樣慢嗎?無敵快的勒 XDDDDDD 但這卻不是一個專案合作上的好方法。

我這一篇文章主要是在介紹我現在管專案所使用的 General Method 與 General Tool,相信裡面大部分也是一般團隊常遇見的問題。

我自己認為,專案執行上有問題不脫是幾點問題

  • 對目標迷失
  • 時間觀念迷失
  • 外行領導內行
  • 缺乏溝通
  • 專案不透明

朝著這幾點改善才能大幅改善團隊裡面的效率。去挑選工具與方法也才顯得有意義。

幾本書推薦

這三本書是我覺得講敏捷觀念與方法比較根本的三本書,也許讀者可以從這三本書入門

這三本都有簡體中文版。露天上找得到。

歡迎各位業界朋友在本文留言討論專案執行經驗。

 
3 months ago

First, I want to thank our team for making such incredible works. Without everyone's hard work, we can't make this.

This article is about how to refactor a live production rails website from GPA 1.4 to GPA 3.0 (Code climate score) in 6 month. The behind scene.

(Apology for readers, I am not native speaker, so it might have some grammar in this article)

Background

I believe there aren't too much people having such experience on refactoring. That's why I choose to reveal the scenes behind.

I joined our team after Series A as software architect.

General overview of our team in July, 2014

  • Our tech team from 3 => ~ 20 in 2 month
  • Our Rails code and API is really massy, GPA 1.4 is 7/22's mail screenshot, when we first apply CodeClimate, the score is 1.1 ( I only see projects having ~> GPA 2.5 before)
  • We have > 10 Rails engineers, having ~15 pull request/day, but our system engineers can only manually deploy 3-5 pull requests per day. And website and mobile constantly crash because API 500.
  • total ~2000 commits in 1 year.
  • NO TEST AT ALL
  • NO DOCUMENT AT ALL
  • Our major API response time > 700ms
  • most Grape API are > 1000 lines, with nested & nested architecture.

螢幕快照 2015-02-07 下午8.44.26.png

General overview of our team in January, 2015

  • Our GPA is 3.06
  • Code > 60% test coverage.
  • API has ~95% test coverage.
  • Fully document on API.
  • ~2000 commit per month since July
  • major API response time < 80 ms
  • using CI service and Auto Deployment system ( self-hosted Samson. )
  • We shipped 6-8 major features every week.

螢幕快照 2015-02-07 下午8.45.47.png

Step 1 : Write documentation ( for making test cases )

There are many ways to start. You probably will guess the first step of refactoring is "add test". But there are so many codes, where should we start to add test? Will developer willing to add tests?

The first step we choose is "writing documentation".

Although we are using Grape, Grape can integrate with Swagger. But this is not enough for making developers "want to write test". Because grape-swagger only can help you manually testing on website easily.

But when writing test, developer still need to make test case themselves and constantly check the original implementation. It will make developer don't want to write test at all.

So our first decision is "write all documentation for ALL api endpoints" on wiki.

螢幕快照 2015-02-07 下午9.36.59.png

Step 2 : Writing tests for every API.

There are many codes we need to add test. But we choose to add API test first, not model unit test.

The reason is we are a live business, can't afford any 500 error during business hours. So we need to make sure our API should not having 500  at least. And before deployment, every pull request should pass CI service.

We make following decisions.

  • Suspend development for 2 weeks, asking all engineers start helping add API tests.
  • Split every API test to an redmine ticket. ( engineers is hard to say no on small ticket )
  • Only write 200 case , and format assertion for most APIs.
  • If there are test cases on documentation, using those as fake data.
  • Not writing any tests except 200, format assertion. if there are 3rd party API integration in API
  • Not writing any tests except 200, format assertion. if that API is very complex.

Step 3 : Extract business logic to ServiceObject from API, and write tests for ServiceObject

The reason we don't write any test if there are 3rd party API or the method is too complex, is because

  • we don't really have enough time writing tests ( our focus is still shipping features)
  • we don't want to mock everything while writing tests.

After added most API tests. We start extracting business logic from API. Many people only know grape API's workflow is one way only. So they don't know how to write test properly.

but actually you can use this techniques to wrap most logic to an ServiceObject ( grape use catch / throw to implement error helper ) , like:

class PlaceOrderService

  def initialize(user, options={ })
    # ....

    # ....

  end
  
  def perform!
       check_for_valid_payment_method
     create_normal_order
     .....
     sending_email
  end

  def check_for_valid_credit_card
    if !has_valid_credit_card?
      error!({
        "code" => "454",
        "message" => "Sorry, you don't have a valid card to pay this order. Please update your billing info and try again."
      }, 400)
    end
  end
  
  def error!(message, status)
    throw :error, message: { error: message }, status: status
  end
  
end

Therefore, you can easily

  • write test for every method
  • only mock small thing you don't want to test for now.
  • or even mock ServiceObject in your API test.

That give us ability write detailed test and make our business logic much clear.

In this stage, we go back and add detailed test cases for major APIs instead of just testing for 200 & format assertion.

Step 4 : add unit tests for almost unrefactorable part.

We have two parts are almost unrefactorable or untestable:

  • billing formula
  • order routing algorithm

These two are very important to our system, but the code is almost unreadable and hard to write test. But we need to constantly change it, without add test, we can't improve or extend them.

We take a trick on adding these tests, the trick is

  • pulling real data on production  as test case.
  • only assert value

Then we have baseline on refactoring.

Step 5: Refactor!

With these tests, we finally can refactor most of our codes in day to day development. We extract most of our business logic to following patterns:

  • ServiceObject ( to gather most business workflow)
  • ValueObject ( instead of creating fat method )
  • Calculator ( for different pricing / tax calculation )
  • Validator ( to validate order's information, we usually run > 10 checks to make sure order is valid )
  • Serializer ( instead of return complex hash )
  • Cells ( make view maintainable )
  • StrategyClass ( for different event and different pricing model )
  • Worker ( most our performance bottleneck is realtime calculation, we move those to background )
  • Concern ( extract common logic from different model )
  • SOA ( we pull our important part as an independent service, then we can benchmark them by switching IP instead of hardcoding switches. )

Step 6: TDD

People always said TDD is hard. because writing test is not relatively easy for most developers.

But most case is if your team don't have test at all, and your business doesn't interact very often, then developers feels there are no reason for them to write tests, and especially them don't even have example test code to copy & paste.

In my opinion, TDD is not good fit for startup, but is very good fit for Series A company. Because Series A company often have clear goal,grow dramatically, and need much solid architecture to scale their software to Series B.

TDD will make your team run faster and faster, shipping quality code. your code won't break just because there are 2 new developers recently onboard.

After having > 75% API tests, we start asking all developers

  • if someone want to ship an API, they must submit API with their tests.
  • If someone want to implement an complex function, they should also submit with tests.

And with many example test codes, and CI service. ( developer's  pull requests won't be approved while test failed). People start writing tests, or even become TDD.

That's why we can improve our code from 1.4 -> 3.0.

We not only make our codes having tests, but also make all our developers start thinking testing is totally necessary.

Takeaway

  • If your don't know how to start, write integration test first.
  • Integration test -> Service Object test -> Unit test
  • Assert value & format -> Write tests for each test.
  • People write tests only if there are already have test cases.
  • People write tests only if there are codes for copy.
  • Do refactor with tests.
  • You don't need to write test when you are a startup company, but do write tests when you are a Series A company.
 
4 months ago

推薦朋友 權自強 這本新書。台版 Remote「我們辦公室沒有人!管理大解放,自由工作團隊如何創造更高績效」

book.jpeg

先自我揭露一下,權自強有說要送我書試閱,喜歡的再幫忙推薦給朋友。但是因為我想先看,在書還沒寄到之前就先跑去誠品買了 XD 所以我是在沒收到贈書的前提寫的。寫這篇推薦純粹是我喜歡所以我推薦。

如果你想要創業雇用 Remote 的人,或者是你想要應徵 Remote 工作。我建議你入手這本書然後畫重點。這本書用很平實的手法,敘述了他創業之始如何用 Remote 的招募方式,在台灣建立了一個二三十人的工作團隊,並運行順利。

這本書相當值得一看的是,很多人都覺得 Remote 不可高攀。而 37signals 出那本 Remote 的書有寫等於沒寫。因為 37signals 很屌是黃金聖隊(37signals 是 Ruby on Rails 這套 Framework 的發明者),每天A 咖履歷都收到手軟不想再收,所以他們才做得到。( Remote 的關鍵在於「能不能 Hire 到負責任且有創造性的天才 A 咖」,而 37signals 根本不用放廣告大家就搶破頭了。所以講 Remote 一點說服力都沒有。)

這本書讓你見識到一般台灣小公司也可以做到。而且他們還不是寫 code 的技術公司,而是網路行銷公司。

我覺得書中不脫幾個重點。但是作者讓你能夠相信,把握住重點你也做得到,這本書反覆了強調幾點雇人的重要原則:

  1. 只雇用你能夠信任的人
  2. 盡量信任他們能夠完成工作
  3. 被動只等老闆指派且無法完成交派工作,更別說舉一反三的員工,千萬不要碰。只雇用有責任感,能夠主動發掘問題解決問題主動回報進度的人。

其實我覺得還是回到那句老話。如果你要參與 Remote 或者想要雇用 Remote。能打交道的還是只有 Senior 工作者而已。

因為 Remote 有幾點關鍵

1) 工作者要非常有責任感
2) 工作者有責任心時時去掌握團隊工作動態,去幫助隊友。而不是給隊友製造大便還不自知。
3) 遇到問題有足夠的能力自救,或提前向發出求救信號。
4) 限於 Remote 因素,可能公司很難好好的傳承經驗或者給教育訓練。所以新入職者要有能力可以迅速 pickup。
這些都是 junior 很難達到的境界。

在寫這篇文章時,我依稀記得以前也在我的部落格稍微聊過這些話題,隨手附上:

最後推薦各位去這一本書:「我們辦公室沒有人!管理大解放,自由工作團隊如何創造更高績效」,我相信各位的錢會花得值得。

唯一可惜的就是這本書沒電子版可以買。我好像認識 PCUser 的老闆,應該要去靠夭一下了...

 
4 months ago

有讀者問我如何一直保持繼續進步的秘訣,這是我給的五點建議:

  1. 開口問在這領域明顯比你熟悉的人,我現在的作法是如何,請問相對比較好的作法是什麼。認真靜下來聽,而不是只是問好玩的只想尋求認同。

  2. 去看書。甚至是跨領域的書。很多時候當代缺乏解決的人才。但上一代未必沒有。歷史上99%的事件都是不斷的重複。有時候看書一下子就解了鬼打牆。或者是跨領域去找答案,技術管理的書就那幾本,可是商管的書很多,建築的書也很多。

  3. 去上課。付費的最好。可以問到飽的最好。動手作的最好。付費會痛才會有認真心態。能問到飽的才可以套到教材內沒寫到的實務經驗。動手作的課程你才有肢體記憶。

  4. 找強者電你。我看過太多人遇到瓶頸,下意識的解決之道就是逃離該環境,另闢一個地方想找一本武林秘笈偷偷專心練功,期待有一天能十年磨一劍名震江湖。殊不知這是最爛的方式。你就完全不懂武功如何運氣,自己在家練怎可能不砍到手,打坐運氣結果走火入魔經脈全廢。 高手跟你一對練,瞬間你就省十個月時間。在家偷練自造輪子是成長最慢的方式,沒有例外。

  5. 不斷練習不斷檢討。向人學的東西都不是你的。惟有反覆練到身體記憶隨手就能使出,這東西才是你的。

 
7 months ago

距離上一次發表文章已經是快要三個月前了。Rails Pacific 2014 也在上週末順利落幕,終於可以坐下來好好寫一篇文章了。

15193298338_bda87e98c9_k.jpg

Rails Pacific 這一次的真是超乎預期無比的成功。結束的時候講者和參加者還開始抱怨「太意猶未盡了,怎麼只有兩天而已,好短」,下一次應該來辦個三天還是五天(?)雖然聽了很開心,但是光是兩天的 Conf 就已經能把人搞死。

所以下次(2015)應該還是會只有兩天。但是會考慮增加 After Party 團體出遊的可能性。

為什麼要籌辦這樣一個 Rails 亞洲年會?

其實大部分的原因,我已經寫在當初這篇舉辦的初衷裡面了。這幾年我時常出國,參加國外的 Conference 來衝擊自己視野。

坦白說外國講者與本地講者真的實力有相當大的差距,不管是講題挑選,議題深度,解題角度都是非常不同的。社群朋友 Bruce Li 在今年跟我去過一次 RailsConf 2014後,整個人就有相當大的成長。

參加外國 Conf 是對技術開發者本身很好的投資,但像去一次 RailsConf,旅費是相當驚人的,一次就要差不多 10 萬台幣左右。不是一般 Developer 都能這樣投資。(Bruce 說他存了兩年...)

我就在想。既然要飛出去太貴,但何不把整組講者搬到台灣呢?

所以最後我們就真的這樣幹!不惜血本的去邀請了十個亞洲地區的超一流國際講者來台灣。
(全國際講者。這好像是沒多少人幹的瘋狂舉動。)

時間和場地

這次的時間是刻意安排的,之前幾個亞洲地區的舉辦人就有聊到,大家應該把舉辦時間拉近一點,這樣講者比較好邀,機票錢也比較省。

所以時間就比較無恥的排在 Rubykaigi 後一週的 9/26, 9/27。很多不願意飛那麼遠過來的美國講者,就會「願意」順便飛過來。

而這次被稱讚「極盡霸氣」的場地「張榮發基金會國際會議中心」,其實是個意外的巧合。因為這兩天是個超熱門的日子,因為我們打算又辦 Conf 又辦 Workshop,在這個日子能符合的熱門場地不多,然後很不巧的都在我要下訂前一天或前三十分鐘被訂走。這個會議場地是我在絕望之餘,上網搜尋出的第一個還有空而且符合預算的選項。(而且非常空....XD)

我們之前根本不知道這個場地如此的完美、霸氣以及巧合。(場地一樓大廳就是超大的鄭和船,五樓是海事博物館,跟 Rails "Pacific" 極度切題)。我想辦在這裏一切就是天意吧。(場勘照片)

14969686487_9ec23caa20_o.jpg

十樓 Workshop 打開窗戶就是正對總統府的 View

689e83eda48b211a7ddd5bfe5910b76d.jpg

然後 Workshop 講者都玩起了對景福門的縮時攝影

食物

食物不用說一向是我的「超級」強項。因為我一向擔任公司的伙委。我對於食物的標準就是「一定要豪氣而且吃的爽」。所以菜單裡面很扯的會有「碳烤牛排」「醉雞」「清蒸深海比目魚」這種鬼東西。(一個人的餐費接近 600 元,外燴廠商還覺得我們叫太多菜了)

5c730e1a7f0a1dc72e81e2d0527808d5.jpg

45a2fdf8cc23be26db1625b61448d8bd.jpg

不過美中不足的一點小插曲是,因為我們在 Conf 前公佈了菜單,導致票又突然賣了十幾張。原本食物準備了大約 1.3 倍左右。因為人數爆增,然後大家又因為太好吃樣樣都夾,結果食物就變成「剛好夠」「所以吃的不太爽」 Orz

這是下次應該要考慮到的變數 XD

Wifi

我第一次簽約時,場勘還可以。而且場地宣稱有 100M 雙向光纖。本來算是放心。但還是有申請了中華電信一條 60M 備用。但是前一天場測的時候,現場狀況很不好,源頭 Router 乎快忽慢。於是我們就把原本的備案拿出來用。

因為我們之前有多次籌備 Rails Workshop 的經驗。Workshop 成敗很大的一個因素就是現場網路穩定度,過去我們測出來是一顆 Airport Express 可以撐 50-60 人的 session 分量打全場這樣。之前就有買了三顆給三個 Workshop 用。在第一天 Workshop 結束後的下午,我們把三顆 Airport Express 拆到主演講廳當 Repeater 串聯「擋看看」。

結果網路竟然無比的順暢。

講者 Prem 還稱讚這是他去過那麼多次國際 Conf,第一次用到網路是這麼順暢的,而且還是用蘋果 Solution硬幹的 XDDD

(如果你的 Conf 小於 200 人,下次可以試看看這樣惡搞看看)

售票與贊助

售票

票價採取了國際 Conf(接近)公定價:5000-7500。這是國際上一般 Conf 的價錢。不過因為但跟本地的票價有非常大的落差。為了讓參加者能夠有物有所值的感覺,所以第一天安排了 Workshop(因為通常一個 Workshop 差不多就是這個錢了)。

贊助

這次真的特別感謝 Tealeaf AcacdemyFaria Systems 兩位老闆 Kevin 和 Theo,第一時間聽到我要辦 Conf,就直接大方贊助(兩間公司就有21萬)。讓我們贊助部分省力不少。而且能夠把 Conf 內容加碼辦得更棒。

有人問為什麼我們贊助商列表沒有想像的長。這要特別一提的是,因為這次本來就打算這次就是要辦爽的,最多我個人可以多負擔到 30 萬。(因為講者預算拉了一下就要 30 萬)。所以在租場地、安排食物、買東西上,都是預算拉了 OK 就直接買,沒有在「節省」的。(我真的想知道辦一次這樣不可能的 Conf 到底要花多少錢,你可以覺得我是瘋子)

而當初是算了一下贊助拉到三十幾萬就可以幾乎不賠太多錢。於是當一次談完這兩間廠商確定經費夠用後,我們就不繼續跑了。(因為安排贊助商的後續 plan 也很累的,拉太多甚至會搞爆議程)

而當然最後讓人震驚的是,這樣霸氣的惡搞竟然預算還沒被執行完,於是 After Party 就決定加碼改去吃高級海鮮燒烤吃到飽 + 生啤酒喝到飽。(那時候估包一個酒吧大概要 5 萬,但是我手上還剩20萬沒花完,就豪氣一點決定包一個海鮮燒烤酒吧震撼一下!反正也才多 3-4 萬 XDDDD)

10628016_10152765143748552_3611857378492914077_n.jpg

10686843_10152765142813552_6939903072151966932_n.jpg

Panel Discussion

這次 Conf 有兩場 Panel:「Refactoring」與「Becoming senior developer」。

15173632477_5bf6f5a26e_k.jpg

Panel Discussion 應該可以說這次 Conf 的大冷門了,幾乎每份會後問卷都是 「Panel Discussion 太精彩了。你們怎麼會想出要辦這種東西?」「這次時間實在太短了,意猶未盡。可不可以下次時間延長一倍之類的」「可以的話,我想看他們一直吵下去不要停」。

其實當中的秘辛是...因為第一天下午辦 Workshop,但早上不知道要幹嘛,所以「Panel Discussion」是殺時間用的....XDDDDD

我在外國參加 RailsConf時,Panel Discussion 是我很喜愛的一個環節,RailsConf 有一次就是 Rails Core Panel discussion。原本這種活動可能一般人會覺得很無聊,但是要是與談人是一堆大神的話,那麼這種等級的對話可能會變得非常有趣,而且大神互嗆的內容還可以讓旁聽者學到超多東西。(這些內容通常是不會在 Slides 裡看到的)

所以這次安排議程時,我也想要有這個環節,所以加上去。但效果實在好到令人稱奇。

(這次也要感謝兩位主持人 KennethMark,事先跟講者來回對過幾次問題,才有這麼完美的表現。)

收支

收入部分

  • 門票部分:~42 萬
  • 贊助部分:~31.5 萬

支出部分

  • 場租:10.5 萬 ( 1.5 天劇場型場地 + 3 * 0.5 教室場地)
  • 講者機票:12 萬
  • 講者住宿:14 萬 (神旺飯店 4900* 3+)
  • 講者接送:0.6 萬 (計程車 + Uber )
  • Before Party:4.3 萬 (神旺飯店 2F 潮品集,套餐與港點)
  • After Party:8.8 萬 (好客高空酒吧海鮮燒烤吃到飽 + 生啤酒喝到飽)
  • 兩天食物(含早茶與茶點):6.6 萬 (飛仕蘭)
  • 大會錄影(優惠價)
  • 現場網路:0.6 萬 (中華電信 60M 光纖)
  • 雜支(網路設備,印刷,立牌,T-Shirt,臨時器材租用...etc.)約 4.5 萬

總支出大約是 67 萬上下。

老實說 Conf 辦到一半我們也很訝異這樣的數字(特別是還剩錢)。因為以往去其他 Conf,很多內容都是相當將就,食物吃不飽,演講聽租公家機關,但聽主辦者說可能還是會辦到差一點虧錢。於是我們就覺得這次根本就是惡搞亂花錢,鐵虧一屁股,虧個少於30萬就是萬幸了。結果像我們什麼東西都是一路霸氣到底,竟然還是至少有剩 5-6 萬 =_=。

實在讓我太吃驚了 Orz

其他心得

  • 這次讓工作人員很 Proud 是,蠻多講者和參加者都稱讚這是他們參加過最好的 Conf,Great & Very well-organized,第一次辦 Conf 能辦到這種程度真是很厲害。(而且這次一半以上講者都是該國的 Organizer,要讓他們講出這種話有難度)。(而且他們還偷問我們這麼誇張的 After Party,到底是需要花多少錢 XDDDDD)
  • 聽到 well-organized 蠻心虛的就是了。因為八卦是:到Conf前一個禮拜我們都還在擔心會不會大爆炸,印刷品包括識別證和T-Shirt都是Conf 舉辦前一天才「應該會寄到」。立牌差一點開天窗。場地找了好久才定案。飯店差一點訂到出包。etc.etc....所以這次也實在太出乎籌辦組自己的意料了!
  • 原來真的會有人看菜單來報名吃飯,多了十幾張票,害我們原本食物準備應該是夠的,結果差一點不夠。
  • 張榮發的服務超級無敵好,景觀與設備非常霸氣!推薦!
  • 參加者受到非常多國外講者帶來的知識與視野衝擊(這正是我們想做到的)。
  • 因為好幾個講者都在研討會上提到 ActionView 設計不合理的問題,於是會後講者決定跨國合作重寫這部分,會在 Rails 5 釋出。(真是讓人激動 & 與有榮焉)
  • 這次因為宣布到開辦,只有三個月的時間,又是第一次辦,所以宣傳和 Update 沒有做得很好。不過因為第一次搞這麼大已經做出口碑了(據說下次日本要組一個大團來參加下一屆)。所以下屆在高雄應該會搞得更盛大。
  • Panel Discussion 幾乎所有人的意見都是要增長,並且場次增加。
  • Workshop 很有收獲,但希望增加初學者場。

官方照片

https://www.flickr.com/photos/railspacific

官方錄影

我們有僱用攝影師,45 天後會釋出 Confreaks-like 版本。

不過會眾有槍版可以擋著先( https://www.youtube.com/playlist?list=PLvRovXx4tzas8CQtAKC5VeZpjPO7SH-uk ),但缺 Panel 的部分。

致謝

工作人員

這次我要感謝最多的是 Taipei Rails Meetup 社群當地的支援。這次的工作人員有:

  • xdite (籌劃,付錢,挑食物,拉贊助,簽所有的名)
  • 小蟹 (網路、雜務、導遊、拉贊助)
  • Kenneth (與所有講者的溝通往來,主持人)
  • Sdlong (食物大隊長)
  • Mark(主持人、導遊)
  • Bruce (Workshop 大隊長)
  • 鴨七(Workshop 組與講者邀請)
  • Walter (簽到工作人員)
  • Ruddy & Eugene (簽到工作人員)

(都是社群常客)

特別是 Kenneth,它包了幾乎所有講者的往來郵件與擔綱主持人的工作。有跟講者打過交道的就知道這是巨痛苦的工作,沒有他的大力幫忙可能 Conf 就開超大洞...Orz

贊助商

這次也要感謝所有贊助商的幫忙。有一些參加者稱讚我們這次 5000 塊的門票,真是「物,超,所,值」。但真實的情形,不是物超所值。而是每個人的成本根本就超過 5000 元啊 XDDDD 多的部分都是贊助商出的。特別是這些贊助商都是一聽說台灣要辦這樣的 Conf,二話不說馬上贊助。真的是超級義氣的!

參加者

還要感謝所有的參加者,Conf 門票是很真的很貴。也感謝大家願意相信主辦方,能夠捧場這樣的研討會。希望你們在這樣的 Conf 都有 Gain Something。

另外要 update 一下。(以免有參加者漏掉了我們的會後信)

我們打算送出明年的 10 張 RailsPacific 門票,資格是:

下一次的 RailsPacific 2015

下一次的 RailsPacific,是 2015 的 9 月,而且會是辦在「高雄」。

我們希望比這次辦得還要盛大,歡迎大家再度參加!

 
10 months ago

最近幾次上課同學都有問到 !? 的問題。因為已經回答三次了,覺得應該足夠做懶人包。

Ruby 中的 ! 與 ?

加在 method 後面,如 empty? 或 gsub!

在 Ruby 中,method 的命名,是允許後面加一個 !? 結尾。

一般的慣例是,如果

  • 設計一個 method 後面有 ?,如 empty?,表示回傳值「預期」會是 (boolean) true / false
  • 如果一個 method 後面有 !,如 gsub!,表示此 method 執行,「預期」會改變原物件裡面的值。

(如果你自己設計的 method,加 ? 其實不會自動轉 true / false,這只是一個「大家認為」「預期」應該的慣例)

2.0.0-p195 :001 > string = "ABC"
 => "ABC"
2.0.0-p195 :002 > string.gsub("A","a")
 => "aBC"
2.0.0-p195 :003 > string
 => "ABC"
2.0.0-p195 :004 > string.gsub!("A","a")
 => "aBC"
2.0.0-p195 :005 > string
 => "aBC"

加在變數前面,如 !current_user

! 前面表示相反值。

if !current_user:若 current_user 不存在

! 與 = 放在一起,如 !=

!= :就是 不等於

( current_user ) ? current_user.name : "Anonymous"

三元判斷式:上面這一段等於

if current_user
   current_user.name
else
  "Anonymous"
end

!!

!! 把該物件轉成 truefalse

2.0.0-p195 :008 > a = "a string"
 => "a string"
2.0.0-p195 :009 > !!a
 => true
2.0.0-p195 :010 > b = nil
 => nil
2.0.0-p195 :011 > !!b
 => false

Rails 中的 ! 與 ?

save 與 save! / create 與 create!

Rails 中的這兩組 save 與 create 與行為與 Ruby 的不太一樣。

其中 save / create,遇到過 validation 時,只會回傳 truefalse。但有時候我們要 debug 一個表單,有時候一直不知道為何表單為何沒成功一直 false,有時候會使用 save!create! 去 debug。這兩個 method 會 throw ActiveRecord::RecordInvalid exception 中斷程式。明確的告訴你壞在哪邊。

Rails 4.0 以前的 method?

在 Rails 4.0 以前的版本。若你有一個 boolean attribute 叫 is_admin。你可以直接在程式碼裡面呼叫 is_admin? (不需另外包裝)就會回傳 true / false

Rails 4.1 + 這個版本的 ! 與 ?

Rails 4.1+ 內建了方便實作類 state machine 的 enum 。!? 會自動幫你變更狀態和查詢狀態。

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

# conversation.update! status: 0

conversation.active!
conversation.active? # => true

conversation.status  # => "active"


# conversation.update! status: 1

conversation.archived!
conversation.archived? # => true

conversation.status    # => "archived"


# conversation.update! status: 1

conversation.status = "archived"

# conversation.update! status: nil

conversation.status = nil
conversation.status.nil? # => true

conversation.status      # => nil


可以看到一些微妙的差別。


廣告:歡迎參加 亞洲首次的 Ruby on Rails 年會 - Rails Pacific 9/26-9/27。有亞洲全明星及講師以及多場實用 Workshop。 7/31 前報名早鳥票台幣 5000 元。請速搶購。

 
10 months ago

og-image.jpg

首先,要很高興的跟大家宣布,亞洲首次的 Ruby on Rails 年會 - Rails Pacific 要在台灣籌辦了!

時間會是在 9/26-9/27 (五、六)。在 RubyKaigi 的後一週。請大家幫忙宣傳這個活動。

這個 Conf 會是一天 Workshop、一天 Conf 的形式。我們邀請了幾乎是亞洲全明星級的 Speaker 來台灣做演講和工作坊。此次機會十分難得。敬請把握。

票價是台幣 5000 元。學生票是 3500 元(需附有效學生證,限碩士以下)。

大會網址:http://railspacific.com/

為什麼要有這個 Ruby on Rails 年會?

東南亞幾個國家的主要幾個明星級講者,甚至是 Conf 主辦方,其實都是互相認識的。大家聊天的想法,都是亞洲各國除了要有自己的 RubyConference 外,也應該要有一個共同的 RailsConference。

(美國有自己的 Rails Conference ,歐洲有 RailsBerry,北歐有 Frozen Rails ,就是亞洲沒有)

而各國的 Ruby Conference 當中其實非常矛盾的是:明明很多人職業是 Rails Developer,很多講題也是針對 Rails 為主,卻只能塞在不到一半的 Session 席次。我們希望有一個專門只談 Rails 的 Conference。

為什麼辦在台灣

  • 台灣在東南亞島鏈上是中心點,大家飛來這邊機票費用不容易爆炸。
  • 台灣的 Rails Developer (想學,其實正在用)的人,其實在東南亞比起來算很高的。

我常常參加世界各地的 Ruby / Rails Conference,常跟世界各國 Rails、與國外想找 Rails Developer 的公司打交道之後。我發現幾件事:

  • Ruby on Rails 的需求量,永遠都處於大量缺乏人才的狀況。
  • Ruby on Rails Developer 薪水非常的高。
  • 台灣 Rails Meetup 的參與人數,在世界上比起來是非常高 active 的社群 ( 20-40 / per week, 40-100 per speech )

但問題是,即便台灣有這麼多想學且正在用的 Rails Developer,卻不知道「世界上哪裡有 Rails 工作」,哪裡有外國公司要找 Rails Developer,只能被動的等其他公司來台灣找人。

所以我們想辦一個 RailsPacific,把這個線牽起來,讓台灣成為 Rails 社群在亞洲的 Community Hub。

Conference 內容

亞洲的 Ruby Conference 多半集中在當地 Ruby 的應用(一半),以及一些 General 的 Rails 設計技巧(一半)。講題數量被壓縮,且整體 Rails 的 track 相對於 RailsConf(美國談論)的主題和水準是有差距的。

我們希望要辦就辦一點轟轟烈烈的,在亞洲就把水準拉上去。而且讓大家不必花大錢機票飛到美國去,在亞洲就能能吸收到這些經驗,學到這些技巧。

因此 Conf 的內容我們會集中在以下相關議題:各國的大型 Rails 網站的維運技巧。Rails Developer 如何自我成長。各國的社群籌組交流。學習 Rails 的進階的議題:如 Rails Internal 架構解析,如何 follow edge Rails,網站架構設計實戰等等...

這些一般很難在亞洲 Ruby Conference 出現的議題。

關於講者

Rais Pacific 這次請到全為亞洲全明星的陣容。為各位介紹一下陣容:

三位 Rails Commiter ( All times #21, #27, #34 )
  • Ryan Bigg : (大洋洲:澳洲)知名 Rails 書籍:Rails in Action 3 的作者,2011 Ruby Hero Award,Rails core commiter #21。
  • Akira matsuda : (亞洲:日本)知名的日本 Rails core commiter #27 ,Asakusa.rb 的創辦人。曾在 RailsConf 演講 Rails Internal 的主題。
  • Prem Sichanugrist : (亞洲:泰國)知名的泰國 Rails core commiter #34,在 thougtbot 工作,曾在多個 RubyConf 演講 Rails Internal 的主題。
六位明星級講者
  • ihower: (亞洲:台灣)台灣 RubyConf 創辦人,Rails Best Practices 作者
  • Shibata Hiroshi:(亞洲:日本)日本的 Ruby Commiter,在 Paperboy 公司任職,擅長大型網站運營經驗,且對設計架構、調校、追 Edge Rails 相當在行。
  • Richard Lee : (亞洲:台灣)iCook 創辦人兼 CTO,iCook 有多威大家都知道了
  • Christopher Rigor (亞洲:菲律賓)Engineyard 亞洲區 Application Support Team 的頭,Rubyconf PH 的主辦人
  • Nick Sutterer (德國,現居澳洲)知名 Gem : Cells, Reform 的作者
  • Ding Ding Ye (亞洲:中國)RubyConf 2013 籌組人,敏捷項目管理工具「風車」的創辦人。知名 Podcast:Teahour 的創辦人與主持人。

為什麼一天是 Workshop

我們去過一些 Conference,發現若「只」舉辦 Conference 其實是對聽眾較不足的。

  • 不會所有議題都有興趣聽,有時候會跳過
  • 動手比較能記住東西

所以有時候去一個 Conference,記都記不得這次聽過什麼

而這次我去 RailsConf,有一軌就是單純只開 Workshop。而大家對於這屆 Workshop 的水準讚不絕口(甚至有從來沒在市面上出現過的整天 Elixir Workshop,教得超經典超贊的,光這個 Workshop 就值得那張門票了...)

我們做過調查,發現大家在日常工作,或是來聽 Conference,有幾個議題是在亞洲大家都想學,也比較弱的:

  • TDD
  • Refactoring
  • Object-Oriented Design
  • Performance Tuning

這些議題很難用一兩個 session 講完,而且這些投稿 session 通常也是一些 tips 的集合,聽完也缺乏實作機會,不知所以然。而國外有這些的實戰 Workshop,但學習這些技巧,不僅要自費飛去,而且門票也不便宜(約 700-1500 USD)(還要加上機票約 1200 USD)。

在實際運作社群的時候,我們發現 Workshop 才是有效能夠提升 Developer 技能的活動。因此也希望在這個活動,舉辦 Advanced 級的 Workshop。一舉能拉昇提升亞洲地區普遍的 Rails 實力。

為什麼門票這麼貴?要 5000 NTD

其實,世界各國的 Ruby/ Rails Conference 價格都是都是大概介於 150-750 USD 左右的價格。比如說

  • RailsConf 22500 台幣
  • Reddot Ruby Conf 5000-9000 台幣(按照購買時間)
  • RubyConf PH 6000 台幣
  • RubyConf AU 14000 台幣

我們希望在台灣辦一個讓國際認可的高品質國際研討會。同時藉著這個 Conference 能夠打開台灣的 Rails 國際知名度以及同時提升亞洲地區的開發實力。所以邀請了很多亞洲頂尖的高手來台灣參加這個盛會,想辦好這種等級的 Conf 經費就容易墊高。

而這個價格:含了一天的 Workshop 以及一天的明星級講者演講。說實在 5000 這個價格也並非算高(一個 Workshop 就值回票價了)。

通常如果你要參加這種等級這種講者的活動。往往需要的費用會是: 15000+ (機票),10000+ (住宿),5000+ (Conf 門票 )。

在 7/31 前門票會是 5000, 8/31 前門票會是 6000,之後是 7500。

你們在 Conf 期間還會有什麼活動?

  • 我們會廣邀美國以及亞洲對 Hiring Rails Developer 有興趣的的公司進行 Recruiting 的 Event
  • 期間應該也會有初階的 Workshop 會舉辦

請用力轉帖

希望大家踴躍參與 Rails Pacific 這個年度盛事,以及轉貼給對 Rails 有興趣的 Developer 知道有這個活動,這個講者陣容以及演講內容非常的難得。在亞洲其他國家也幾乎沒有出現過,請把握機會。