over 6 years ago

Hi, 各位, 從今日起,本部落格正式搬家到 Logdown 上 Hosting 了。

Logdown 是我們公司 Rocodev 正式開發維護的一個產品。線上使用 Markdown 寫作文章,支援 Github-Flavored Markdwon, MultiMarkdown, 以及 Latex 數學式, 提供上傳圖片介面以及 Custom Domain。Octopress 與 Wordpress 搬家服務。

正式網址還是 http://blog.xdite.net
Feed 網址還是 http://feeds.feedburner.com/xxddite

兩年前,我決定從 Wordpress 搬家到 Octopress。原因是 Wordpress 無法提供我技術寫作上的需求( Markdown 以及程式碼排版)。我找了很久,發現 Octopress 可以解決這部分大部分的問題,於是我決定轉換平台。

Octopress 在寫作上的確比 Wordpress 順暢非常非常的多。但它也不是沒有缺點。Octopress 必須作者自己尋找使用適合的 Markdown 寫作軟體書寫文章(我是用 Mou 這套軟體),寫完再執行指令 compile 出去。

Octopress 可以進行非常高度的客製化。但是,相較之下它也有一些門檻,比如說你必須略懂技術(安裝 Octopress,以及 compile 文章並發佈,設定域名...等等)。隨時想寫想發時,該台電腦必須要有 Ruby 環境,才能夠發布....貼圖的問題還是半手動,需要自己貼。但最困擾的我的兩個點還是:

  1. 沒有一個線上 / 線下 Markdown 編輯器,能夠好好的支援寫作 Code 排版以及提供 Code 即時排版。(在不干擾寫作的情況下)

  2. 當每次文章一多,Ocotpress compile 文章會變得非常非常慢。(雖然我知道 hack 可以繞過,但是我有時候還是想當作者純寫文章而已,不想解決技術問題)。

世界上也沒有任何一個 Blog Hosting 提供這樣的服務,照顧我們這些只是想專心寫作的人的需求....

重貼當初那篇文章的一段話


Developer Blogger 的需求

其實我們的需求也不多。若是可以:

輕鬆的撰寫 Markdown
輕鬆的貼圖
輕鬆的貼程式碼
改 CSS 超容易
不用煩惱佈署問題
檢視草稿變化,甚至是站台更動變化。

這樣就很開心了!


Logdown 的開發初衷就是只有這樣而已。

Logdown 提供什麼

  • 革命性的 Markdown Editor ( 即時 Markdown 高亮, 在 CJK 下不變形不跑位),程式碼與 Latex 的的即時 preview 。
  • 單篇文章下載(只喜歡 Markdown Editor 也沒關係,我們提供寫完單篇文章下載 Markdown 檔)
  • 超直覺圖片上傳 (支援拖拉上傳,以及各種網路儲存服務、社交服務上的圖片導入)
  • 自訂 Domain 與自訂 網址
  • Octopress 匯入 / 匯出 (無痛搬家)
  • 沒有站方廣告...
  • 一天六次以上的部落格備份

Logdown 未來會提供什麼

  • Multiple Blog
  • Wordpress Import ( 下個禮拜會就會推出)
  • Movabletype Import
  • Google Blogger Import
  • Custom Theme / Custome Pages / Custome CSS

如果你還有其他的需求,歡迎寄信給我們 logdown@rocodev.com,我們也會排入開發清單。

就是這樣,我正式的搬來 Logdown 了。歡迎你也一起搬來。

 
over 6 years ago

真是一個刺激的 Hack 週末。自從 Logdown兩週前推出,得到了不少好評,這股動力讓我們寫起 Feature 更加的賣力。

這個週末(是的。你現在看到這些功能,幾乎都是我們在週末寫的....), Logdown 推出了更多功能以及 Beta Plan:

首先是

Custom Domain ( Beta / Preinum required )

大家期待已久的功能 Custom Domain 功能

Octopres Import ( Beta required )

可以把 原先的 Octopress 文章壓縮打包成 zip 後,無痛匯入 Logdown 裡面。我們預計在接下來的幾個禮拜測試 Wordpress 與 Movable Type 的匯入

Custom Handle & Custom URL

支援原先的 Octopress URL

綜合 Custom Domain / Octopres Import / Custom Handle & Custom URL 這三項。基本上把 Octopress 搬過來應該沒什麼問題了...

File Uploader ( Beta / Preinum required )

很多朋友一直在問的 File 上傳功能,我們在週末也完成了。目前 Logdown 支援 File drag & drop upload, Flickr, Instagram, Facebook Photo, Picasa, Dropbox Upload!!!! (其實還有更多...)

目前暫定 Beta 是 100 mb,Prenium Plan 會是 10GB

單篇 Markdown 下載

如果只喜歡我們的 Editor 也沒關係,我們支援在 Logdown 寫完再下載回家貼到 Octopress,但是如果你可以考慮 搬家 那就更好了。

匯出功能

如果哪一天你不喜歡 Logdown 想搬回 Octopress 了,我們也提供了全站打包下載功能,會把所有的文章打包匯出,郵寄到你的 email 裡面。

目前的打包功能只有 Octopres Zip 匯出。我們預計在接下來的幾個禮拜測試與開發 Movable Type 的匯出。

更多 syntax ( Especially for Hacker and Scienist )

Octopress Style Code Block ...

是的,我們支援了 Octopress 特有的 code block 寫法,會有 Caption...

  ``` css common.css.scss
    @import "reset";

  ```

Octopress old syntax

我們目前 porting 了 codeblockimg ,預計還會再支援下一個更重要的 gist 功能,敬請期待

Latex Support

是的,我們喪心病狂的支援了 Latex 語法。你可以透過加入 mathjax 來顯示 Latex 語法。而且直接可以在預覽裡面看到結果!!!

後續計畫:Beta & Preinum Plan

這兩週我們收到不少朋友的鼓勵與支持,所以我們很認真嚴肅的決定將繼續維護這個產品,而不只是一個 Hackathon 的 pet project。我本人的 blog 部落格也會在近期之內就搬到 Logdown 上。

Logdown 之後將會有 Preinum 收費的計畫。我們預計的收費計畫將會是 49 USD / year。為了感謝這段期間參與測試的朋友,在八月底前升級 Beta Membership 在轉換為 Preinum 時,我們將只會收取 24.95 USD 的費用。

以上宣布的這些 Advanced Feature,你可以在後台中找到升級頁面,Upgrade 成 Beta 後進行使用。

追蹤我們

你可以透過這兩個管道取得 Logdown 的最新消息。我們也會在重大 Feature 推出時,寫信通知大家。

 
over 6 years ago

TL; DR: Rails 4.0.0 有地雷,建議修完所有 depcrapted warning 再從 rc1, rc2 升級,不然會有大災難。

上個禮拜跟同事做了個 Markdown Blog Service Provider : Logdown。介紹請看這裡。Logdown 是用 Rails 3.2.13 寫的。適逢昨日 Rails 4.0.0 釋出,於是手癢癢就想幫 Logdown 升級…

上個月我曾經寫過兩篇文章:

該踩的雷我都中過了,也知道怎麼 patch 常見的地雷,閃過去….

不過我膝蓋還是中了好大一箭…orz

地雷一:強制 raise error

Rails 4 改變最大的有幾個重點:

  1. 拿掉 attr_protected,改用 strong parameters
  2. scope 改用 -> {}
  3. routes 建議大家棄用 match ,而用更精確的 get , post

well, 在 4.0.0 版,如果你還在用 match 的話,Rails 除了 warning message 還會直接 raise error。網站會直接跑不起來,而不是像 beta 的向下相容。而且一些行為也會強制禁掉,如 Logdown 其實有兩個 root :to,其中一個跑 contraint 偵測是否有 user 而導到後台。

Rails 4 是直接禁掉這樣的 syntax 讓你跑不起來。

不過這個還算好的警告手段。直接爛掉雖然有點 annoying,但是你知道 patch 掉就沒有後遺症了....

地雷二:改變行為

這件事我真的覺得最扯....。但也可以預見未來可能有一些災難發生。

Rails 4 beta 建議大家 scope 改用 -> {}。並且有警告 Message 通知你必須改變,但撈出來的 query 還是向下相容,也就是執行結果是正確的。

Rails 4.0.0 版 建議大家 scope 改用 -> {}。並且有警告 Message 通知你必須改變,但撈出來的 query 行為改變,也就是執行結果是錯誤的。

這件事讓到底有多嚴重,我的 post.rb 是這樣設計的:

class Post < AR
  scope :recent, order("id DESC")
end

而在 Logdown 的 Dashboard 裡面,我的後台 index action 是這樣設計的

class Account::PostController < AC
  def index
    @posts = current_users.posts.recent
  end
end

正常的行為,生出來的 query 是這樣的(撈出我本人的所有文章):

Post Load (11.3ms)  SELECT `posts`.* FROM `posts` WHERE `posts`.`user_id` = 3 ORDER BY id DESC LIMIT 50 OFFSET 0

到這邊都沒什麼問題。

本來我改好程式,在 local 測一測看起來沒什麼問題,( Rails 4 最大的改動通常是 update_attributes 會需要修,query 通常不太需要修)…也沒 raise error。還好我今晚是先 deploy 到 staging 去測。deploy 上去差一點噴茶....

我個人的 Dashboard 竟然出現了(全站文章) ……orz…..WTF…

在 local 重新測試才發現:

如果你沒把 scope 改成

class Post < AR
  scope :recent, -> { order("id DESC") }
end

那麼…在後台

class Account::PostController < AC
  def index
    @posts = current_users.posts.recent
  end
end

生出來的 query 會長這樣

Post Load (1.2ms)  SELECT `posts`.* FROM `posts` ORDER BY id DESC LIMIT 50 OFFSET 0

齁齁,所有條件失效,撈全站文章給你。簡單的 query 都這樣,複雜的 query 我不敢想像。( -> { } 的新預設寫法席卷了一大堆設計,而且一堆 plugin 還在用 舊 query … )我已經可以預見這會產生多大的災難了....

重點是,你還不能回報這是 bug,畢竟人家都已經叫你換成 -> {},誰叫你不換勒?

地雷三:管太多…

我在 deploy 的時候,遇到 Asset compile 不過的狀況。sprockets 一直報錯:

Asset logical path has no extension: README

WTF,我從沒在之前的版本看過這個錯誤。在網路上搜尋了一下發現是這個 issue..:

https://github.com/sstephenson/sprockets/issues/347

意思就是 sprockets 連你的 README 有沒有加 .txt 都要管啦 -_-。然後維護者不想修,叫大家自己去找 workround…

所以如果你的 app/assets/javascripts app/assets/stylesheets 下如果有沒有副檔名的檔案,compile 就不會過。你會想說 not big deal,自己改成多加 .txt 或 .md 就好了…

沒這麼簡單。一堆 3rd party 的 css / js ..不僅有 …..README…還有 LICENSE…還有 CHANGELOG….XDD

齁齁齁,感覺很精彩了吧。沒關係,這都可以加 .txt。頂多是 CSS / JS 界的 repo 這陣子會被 Rails developer 群騷擾而已。更精彩的是 Makefile….這到底是要怎麼閃 XD

( 剛剛網路上找 solution 看到一堆慘案 …)

Bower 已經身亡,這裡是解法

Summary

如果你是從 Rails 4.0.0beta1 或者是 Rails 4.0.0rc1 升級,務必停看聽…

Rails 4.0.0 跟你想得很不一樣 …orz

 
over 6 years ago

Logdown 是週末跟三位朋友 zhusee, tonilin, chitsaou, 24hr 做的一個 Hackathon 項目。這是一個新世代的 Blogging Platform using Markdown。

身為 Dev Blogger,最讓我們困擾的一件事,就是難以使用 Wordpress 書寫排版技術文章。在找尋過許多替代方案後,我最後投入了Octopress的懷抱。

只是 Octopress 並不是這個答案的終極解,因為 Octopress 還是有一些自身的小問題在:比如只能在線下使用 Markdown 編輯器寫作,再使用command line 編譯。有時候這變成一件很惱人的事,有個線上的 Web 編輯介面還是必要的。

若要讓某些文章一開始就是草稿模式也不是很容易,等等…

而一些 Non Geek (或者不是 Ruby 界使用者),在他們的電腦上安裝、運行 Octopress 也是不小的技術門檻。

種種原因最後讓我們開發寫出了 Logdown 這個平台。


Logdown 有:

優雅的書寫介面

( 經過長期的研究,我們認為這樣的介面最符合 Markdown 的 preview 寫作)



支援 Markdown ( GFM )

技術寫作者最愛的 Github Flavored Markdown

直結的 Meta 設定

支援 more 標記(繼續閱讀)

支援 Tag

支援 Dirty detect ( 避免寫作中誤觸離開)

漂亮的內建 theme

整合 disqus

完整的 Facebook Opengrah

等等...

Anyway 我們希望 Logdown 的推出,能夠成為解決 Dev blogging 的實際方案。希望各位朋友能夠給我們一些 feedback,thanks。

這個 project 我們也許不久後將會放到 Kickstarter 上,希望變成一個 Longterm support 的項目。

 
over 6 years ago

Rails-101 是我兩年前寫的一本 Rails 教學書,前身是我的 Developer 訓練教材 / 解答本。

不少想出書的朋友這兩年來問過我一些大大小小的相關問題,想一想乾脆趁改版作一次解答。

Q: 這一本書兩年來賣了多少本?

A: 接近 2000 本。

Q: 賺了多少錢?

A: 其實沒有仔細算過。因為這本書有時候賣 9.99,有時候特殊節慶我會特價幾天打對折。但總體來說,乘以最佳銷售狀況的 0.6 應該是個合理的數字吧....

Q: 好像比紙本書好賺?

A: 看你怎麼想?出版社大概都是一刷 2000 本,預付版稅大概 5-7 萬元。技術書一刷也不會賣超過這個數量。看起來收入比給出版社出版高不少。但是你可能要考慮

  1. 書是我自己排版輸出的
  2. 客服信是我自己回的
  3. 購物車系統...(呃,還好不是自己做的,不過月費 9 USD)
  4. 書的網站是我自己做的…

這本書要付 RD xdite, 客服 xdite, 編輯 xdite, blogger xdite 不少錢....所以 Author xdite 應該沒什麼賺。

Q: 自費出版的優缺點你覺得是什麼?

A:

優點:小眾市場的書也能賣

小眾市場導向的書也能賣。通常這種書出版社不願意出。但是卻有讀者願意要買,運氣好挑對主題就其實蠻賺的。我看 Leanpub 上有人寫 Larvel 的書就賣了 6000 多本…

優點:技術書籍載體適合電子發行

而且技術書籍的載體蠻適合電子發行,因為內容有時效性。

缺點:排版技術門檻很高

缺點就是排版系統不好搞。寫一本電子書,幾乎 90% 的時間不是在寫書,而是在搞定「該死」的排版系統(下一段會講到...)。而且當你的書裡面有很多程式碼時,就準備排到死吧 -_-

缺點:書籍內容容易過期

我這本書剛寫成時是 Rails 3.0.3。到下架時 Rails 版本是 3.2.13。

當中 Rails stack 有很多技術架構上的轉變,這些讓我在更新書籍時遇到很多麻煩,因為讀者都會想要我支援最新架構,但是有一些 stack 是很難寫進去的....

(比如 rails 在 10.6, 10.7, 10.8 的安裝方法不一樣..orz)

但是其實更新書籍,排版很容易爆炸,所以我不是沒有寫好需要更新的內容,而是每次排版排到生氣我就想放棄了…orz

缺點:書籍讀者認為「更新」是應當的。

一般紙版的書籍,書一旦印出來了,內容就算過期,讀者會摸摸鼻子就算了。但是在電子書上,讀者會認為作者有需要更新內容的義務....

而且應當是免費的 /_\

缺點:讀者認為作者提供 pdf, epub, mobi 三種版本是理所當然的

嗯....雖然我買書時也希望別人都提供,但實際上,排版實在會搞死人啊 XD

Q: 你曾經用哪一些技術進行排版?

A:

(1) 最初我是用 Mac 的 Pages 寫作,但只能轉成 PDF,而且貼 code 很痛苦。

(2). 第二版我就改用 reStructuredText 重新改寫。貼 code 變得很漂亮了,也有辦法寫一些註解,但是裡面的文字編排反而讓人很頭大…邊寫邊排是一個大挑戰

轉 pdf 需要自己 hack 一些 latex 的支援,因為 reStructuredText 當時並沒有考慮到 UTF-8 排版的問題,所以我花了不少時間在解中文內容輸出問題。

這一個版本我有順利同時轉了一個 epub 出來

(3) 在這中間我有試過幾套軟體(不一定是在 101 這本書上)

個人覺得有用的是 c,d,e

在這當中踢到的鐵板多數是:

  • 軟體喜歡自己發明格式的問題。所以每換一個平台,內容等於要通通重排...
  • 解決 latex 中文與相依性套件問題(轉 pdf 所需要的套件)
  • 讀者靠北為何沒有贈送 .mobi 的問題
  • 為何贈送了 .mobi 卻不支援七吋 kindle 排版的問題....

(我覺得自己真是毅力驚人,要是我不懂寫程式,可能老早就放棄了.....)

Q: 為何這次會選 Leanpub 發行?幹嘛兩年之內搞得這麼累,早用 Leanpub 不就好了...

A:

其實 Leanpub 一出來就想用了。只是兩年前 Leanpub 的問題是,(1) 不支援中文 (2) 不支援排 code (3) 不支援 coding tips。只能排排文學小書,所以很快就被 rule out 了。

這次會進場是因為最近有幾檔強檔 Ruby 新書,特別是 Rails 界聖經 The Rails4 Way 宣布在 leanpub 上發行…

要知道這本書可是 6-700 頁以上的超級程式巨作,如果他們排的動,那就表示應該沒什麼問題了....

這次進場寫作,也發現意外的順手,所以就打算把早前寫完但放棄排版的書稿,開始搬上去了…

撰寫輸入格式接近 markdown,輸出格式則有 pdf, epub, mobi。能夠滿足讀者需求。

一本書賣 10 元,Leanpub 抽我 1 元。我覺得算是個蠻合理的數字。

Q: 你之前用什麼平台收錢?

A :
Digital Delivery + Paypal。這個平台本身不抽交易,但每月使用費 9 USD。所以我的獲利會是每一本書被 paypal 抽的交易稅 + 每個月的使用費。其實算下來跟 Leanpub 其實差不多....

Q: 你不怕電子書被盜版嗎?如何處理買書退費問題?

A:

寫書「真的」就是一半在作功德的事。其實在作者的立場,其實是希望書能被越多人看到越好。收入有個合理回報就好。

我也遇過跟人「借看」的讀者,最後覺得寫得不錯,寫信過來說自己重新補買的。這次雖然改版我送大家 100% 折價卷,但是也有讀者覺得全新內容很不錯,自己重新付錢補買的…誰知道呢?

至於退費問題,在網路上退費的原則通常是 45-60 天內無條件退費原則。不過其實在賣電子書的各位作者,其實都願意讓大家無限時間退費,只是超過了這個時間,paypal 刷退非常麻煩。所以最後大概都限制 45-60 天。

退錢也不會囉唆。反正不合期待大家都能理解。

不過大陸讀者申請退費數量是台灣的 10 倍這我必須在這裡講一下 XDDD

Q: 有沒有下載 PDF, EPUB, MBI 的數據?

A: 第一版沒有。但第二版有,Leanpub 有提供這個功能。直至剛剛,我這本書總已經發出大約 600 本。

數據如下:

Metrics
Book formats downloaded at least once per purchase
97.9% of your readers downloaded PDF format.
60.7% of your readers downloaded EPUB format.
37.6% of your readers downloaded MOBI format.
These numbers won't add up to 100%, as purchases include all formats.

Book formats download profile
34.9% of your readers downloaded PDF only.
1.0% of your readers downloaded EPUB only.
0.5% of your readers downloaded MOBI only.
26.5% of your readers downloaded PDF and EPUB only.
3.9% of your readers downloaded PDF and MOBI only.
0.5% of your readers downloaded EPUB and MOBI only.
32.6% of your readers downloaded all three formats.

我目前能整理出常見的內容和問題大概就是這些。對電子出版有興趣的朋友歡迎留言交流....

 
over 6 years ago

我兩年前寫的 Rails 入門學習書籍 Rails 101,這個月進行改版了。

主要的變動有以下:

  • 以 Rails 4.0.0 rc1 為範例
  • 以 Ruby 2.0.0 為語言版本
  • 全新的範例 ( Group 討論區 )
  • Rails 4.0+ 起內建的新 feature 與 syntax 示範
  • 這次的版本加入了,使用 helper / scope / method 「整理程式碼」
  • Rails 4.0 與主流 plugin 的 Hack 解法 ( devise & strong parameters)
  • 在時尚的寫書平台 Leanpub 上架!
  • 同時支援 PDF、Epub、Mobi 三種版本

目前書籍的進度是完成了 65% 左右。(開發程式碼已完全 complete)

價格一樣維持在 9.99 USD。

慶祝改版 coupon : ruby-taiwan-2013-june ( 5USD 折扣,到 6/15 為止)

其他

 
over 6 years ago

這是我前天在 JSDC 演講「Why F2E should learn Rails」。

http://xdite.github.io/jsdc-2013-slide/

介紹了 Rails 內建哪一些 Feature 可以讓 F2E 工作時更上手。

對於 F2E 來說很重要的幾個工具與原則,其實 Rails 都內建好了。而且還額外提供順手的架構方便 F2E 整理專案。

 
over 6 years ago

TL; DR : 寫測試兩個鐵律:一次只測一件事情、不要自作聰明幫測試碼 DRY。

最近跟著朋友 Kevin Wang,現 Tealeaf (Ruby on Rails 線上教學公司) 教師,前 Hashrocket 工程師,學習寫正統的測試。

找老師直接學下來,果然比自己抄一抄外面的 code ,寫出湊合測試,果然神速許多。

以往寫測試時最讓人迷惑的就是,如何才能測到恰到好處,一段程式碼幾十行,中間有的動作根本不知道要怎麼測,或者是寫了一大堆測試,還是會在某個執行點壞掉,結果測試碼寫到跟程式碼打架。或者是 case 很多,測了 一 在 二 爆炸,測了二,在三爆炸…寫測試寫到火大。

最近才開始領悟到要同時把「程式碼」和「測試代碼」寫好,其實真的很簡單。只是以前沒有機會「好好學」。

其實總歸來說:寫測試只要抓住兩個原則:

  • 「One assertion per test」
  • 「DAMP not DRY」

就可以解決 80% 的問題。

只是我以前從來就不知道這兩條原則不是寫好玩的(指選擇性遵守),而是寫測試的「鐵律」。

只要你嚴格守住第一條線「One assertion per test」,你的程式碼就會變得非常乾淨。守住第二條線「DAMP not DRY」,你的測試碼就會變得非常好維護。

這兩條用得很熟,你寫測試就再也不會迷惑,到底應該怎樣寫才算「測得對」。

One assertion per test

One assertion per test 講的其實是:一個測試必須只驗證一件事。這是什麼意思呢?

這是指就算是你的程式碼只有下面幾行的話

def show
  @post = Post.find(params[:id])
  @comments = @post.comments 
end

你也必須這樣拆開測

describle "GET show" do 
  let(:post) { Fabricate(:post)} 
  let(:comment) { Fabricate(:comment, :post => post) } 
  
  it "assgin @post variable" do 
    get :show, :id => post
    assigns(:post).should == post
  end
  
  it "assigns @comments to @post.comments"  do 
    get :show, :id => post
    assigns(:comments).should == [comment]
  end
  
  it "render show's view" do 
    get :show, :id => post
    response.should render_tempate :show
  end
  
end

而不是擠在一起。如同下面這個測試。

describle "GET show" do 
  let(:post) { Fabricate(:post)} 
  let(:comment) { Fabricate(:comment, :post => post) } 
  
  it "assgin @post variable and assigns @comments to @post.comments and render show's view " do 
    get :show, :id => post
    assigns(:post).should == post
    assigns(:comments).should == [comment]
    response.should render_tempate :show
  end
  
end

為什麼守著這個原則這麼重要呢?因為當你在寫類似以下程式碼時

def create

  @post = Post.new(params[:post])
  
  if @post.save
    urls = URI.extract(@post.content)
    urls = urls.uniq 
    urls.each do |url|
      link = @post.links.build(:url => url)
      link.save
    end
    redirect_to posts_path
  else
    render :new
  end
      
end

就會下意識的改寫成

def create

  @post = Post.new(params[:post])
  
  if @post.save
    @post.extract_links!
    redirect_to posts_path
  else
    render :new
  end
      
end

針對 @post.extrat_links! 再寫一個 unit test,然後在 controller test 中 mock 掉。

一旦不這樣拆,你就會發現「非常難遵守」「One assertion per test」這條定律,更不用說也很難測。當一旦習慣寫 code 拆 method 時,你就會發現程式碼其實會一天一天更乾淨....

而且你會猛然發現,以前那些「很難寫測試的code」,都是那些不喜歡拆 method 拆 class 的 code …

「DAMP not DRY」

DAMP not DRY

  • DAMP 是指 Descriptive And Meaningful Phrases
  • DRY 是指 Don't Repeat Yourself

這是什麼意思呢?

我發現大部分的測試很難改是因為,程式設計師寫 code 寫的最後的一個壞習慣 DRY。

等等?DRY 不是一個好原則嗎?

DRY 在寫程式時是一個很重要的好原則沒錯,它的作用是讓程式儘量好讀好(給人)維護。所以程式師設計在經過良好的寫程式訓練之後,下意識習慣性的在寫任何 code 時都給他 DRY 一下。

很可能就會寫出這樣的測試碼:

describe Post do 
  before do 
    alice = Fabricate(:user) 
    bob = Fabricate(:user) 
    post =  Fabricate(:post, :user => alice )
  end

  it "#xxx" do 
    ...
  end
  
  it "#yyy" do 
    ...
  end
  
  it "#zzz" do 
    ...
  end

end

這,就,慘,了。

為什麼呢?在剛開始第一次寫這些 test case 的時候,你可能覺得這沒什麼問題,測試都會通過…不過當一個月之後,你的老闆叫你改一些功能的時候,比如說改 #xxx 好了,你可能要換掉 alice 這個 sample。這就慘了,一改下去 #xxx 是綠燈了,#yyy#zzz 卻紅燈了。

這時候你就會很幹....要去修一下 #yyy#zzz 裡的變數,但是改著改著你卻發現要讓 #yyy#zzz綠燈,其實有時候可能要連原先 #yyy#zzz 的測試碼也要重寫…

然後你就會相當抓狂:改兩行,然後卻要修 60 行,越寫覺得寫程式碼和寫測試碼的邊界到底在哪裡?好像只有多做工....

DAMP 的原則是要你,在寫測試時 CASE 寫的越清楚越好,甚至「多行重複」也沒有關係。也就是以上的程式碼我們應該改成:

describe Post do 

  describe "#xxx" do 
    let(:alice) { Fabricate(:user) }
    let(:bob) { Fabricate(:user) }
    let(:post) { Fabricate(:post, :user => alice ) } 
    ...
  end
  
  describe "#yyy" do 
    let(:alice) { Fabricate(:user) }
    let(:bob) { Fabricate(:user) }
    let(:post)  { Fabricate(:post, :user => alice ) } 
    ...
  end
  
  describe "#zzz" do 
    let(:alice) { Fabricate(:user) }
    let(:bob)  { Fabricate(:user) }
    let(:post)  { Fabricate(:post, :user => alice ) } 
    ...
  end

end

它的原則是:開發者要儘量讓寫的每一個測試「環境獨立」。不要被其他測試環境變數的改變,也被影響到。

而且用 before,容易隱藏一些該被測試的 host,不容易 debug。這也是另外一個需要小心的地方...


只要這兩條線你守得非常嚴,程式碼和測試碼就會越來越有水準。

至於防守警鐘在哪裡?

  • 只要你在 it "xxxx …. and yyyy" 裡面提到 and 這個字,基本上就表示你在一個 test 裡測兩件事。你應該開個 context 拆開繼續做成兩個 test,或者再拆一個 it 出來再寫一個 test。

  • 只要你想要在 describe 裡面寫 before,可能就要小心你又在不小心 DRY 過頭破壞測試的獨立環境了。

 
over 6 years ago

TL; DR 版本:Linode 是躺著中槍的路人

上個月,Linode 被打下來,洩漏了一堆資訊。逼得很多人不得不換卡和換密碼。幾個小時前,在 HackerNews 的一篇文章揭露 Linode 其實是路邊的那個倒楣鬼,人家不是要揍他,而是揍他的客戶...

以下內容是基於 HN 上的一篇懶人包翻譯,然後加上HTP 雜誌原文裡的資訊。

故事是這樣的:

有個駭客組織叫 HTP,最近有個匿名組織假冒成另一個組織 "ac1db1tch3z" 想要挖他們的底(去挖 HTP 的 botnet)。HTP 非常不爽想要報復,後來他們查到這個匿名組織在用 SwiftIRC 這個 IRC 服務在聯絡。而 SwiftIRC 的 nameserver 放在 Linode..。

所以 HTP 想要把 Linode 打下來,hack 進 SwitftIRC 放後門,然後報復回去。

他們一開始直接打 Linode,結果 1day exploit 被 Linode 防下來了。但是,Linode 的域名註冊商 name.com 被打下來了。所以他們的計畫改成弄一個 transparent proxy,打算從中間攔下 Linode 的帳號密碼...。

=== 題外話 ===

不只 name.com 被打下來了。 Xinnet, MelbourneIT, and Moniker 也被打下來了。
這一波總共有 550 萬的 domain 被打下來..no kidding

=== 題外話結束 ===

本來計畫是這樣的,但是他們發現了一個更棒的洞,直接打下了 Linode ...

這當然很 high 啦。他們當然直接拿下 SwiftIRC 開始種後門。更精彩的是,因為不少站台也放在 Linode,中獎的名單還有: Nmap, Nagios, SQLite, OSTicket,

Phusion Passenger (modrails), Mono Project, Prey Project, Pastie, Sucuri, Hak5, Pwnie Express, Puppet, and oauth.

(都是一些超重要的站...)

但是,HTP 不知道的是,HTP 內部被 FBI 滲透了..因為 nmap.org 是個非常重要的站台(security scanner)。於是 Linode 很快就被 FBI 警告了 nmap.org 被打下來了。

於是,Linode 上其他站被 HTP 打下來的事,很快的也被知道了。這讓 HTP 的報復計畫來不及實現...於是 HTP 決定警告 Linode 至少在 5/1 不准講出去,否則 HTP 就會散佈這些他們拿到的這些敏感資訊(包括客戶資料以及信用卡資料)。如果 Linode 安靜的話,HTP 就會遵守約定刪掉拿到的這些東西。

=== 題外話 ===

敏感資訊包括 : 159000 + 信用卡資料,使用這名稱, $5 (我不知道是多少數量) 筆加密過的密碼,LiSH 使用者名稱,LiSH 密碼 「明碼版」 。還有 Linode 雇員 Login 帳號。

=== 題外話結束 ===

因為 HTP 打 Linode 本來就不是為了拿這些資料,而是想要打仇家。所以他們認為開給 Linode 的 Offer 已經算不錯了。如果他們不聲張,基本上就等於什麼事都沒發生。

但是!!Linode 還是公開了被打下的這件事(因為他們也被 FBI 逼著要公開,FBI 很明顯的不信任 HTP 會守約)。HTP 知道 Linode 其實被逼到一個很難自處的位置,於是也跟 Linode 達成了另一個協議,只要 Linode 在公告上說,經過分析之後發現打下他們的是 HTP。HTP 就會同意刪除當初拿到的這些資料....(很多 Hacker 其實只是想留名)

HTP 被這樣偷搞很不爽,於是他們就在查到底誰是 FBI 的內鬼。最近終於找到了,他們打進了這個內鬼的電腦,並且打開了 webcam。正好清楚拍到了 FBI 正在對某個 HTP 成員背後下指導棋,然後這個人就被踢出了組織...

這是到目前的故事。不過這是 HTP 單方面的故事,信不信就隨你了…

 
over 6 years ago

TL;DR : Rails 4 是一個溫和加強版的 Rails3,而且贈送了很多酷炫 feature,適合進場

上個月花了一點時間直接衝了 Rails 4.0beta1,利用 upgrade project 去熟悉整個 Rails4 新的架構。

若要我形容對於 Rails4 這次升級的感想的話,我會總結為兩句話 New Feature, Better Syntax

相較於 Rails 2 -> Rails 3 幾乎是個毀天滅地的重新大改寫(i.e. 不管是 Rails 本身,還是使用 Rails 開發的 project),Rails 3 -> Rails 4 的升級及變更內容顯得溫和許多。

Better Syntax

Rails 4 這次的改進,許多都是吵了多年以來的折衷方案、或者是許多開發者對如何設計,始終各自有 strong opinion 的主題,都找到 best practices 而被一槌定音了。或者是一些一直以來大家覺得老是被逼著這樣寫,非常智障的設計,也都被改掉了…

Routing

  • 讓 Routing 更安全:新增了以 http verb 為 syntax 的寫法,如 get/post
  • 支援 Rouring concern: 如果要幫不同的 resources 加上如同 :comments 這樣的 nested_resources 就不用一直再重複貼上

ActiveRecord

  • 強迫 scope 的寫法要全面改成 proc / lambda:避免 eager-evaluated 出現的問題。
  • Relation#not:以往要寫出 not 的查詢條件,寫法讓人哭笑不得。
  • Relation#none:以往撈不出集合,是 nil,要回傳 [] 空集合要自己作..
  • Relation#pluck:可以輕鬆只摘出某些欄位,以及要自己手下 select…
  • Relation#unscope:避免 default_scope + order 產生的排序問題。(因為下 except 無法閃過去)
  • update & update_columns:update 會觸發 callbacks, update_column 不會,但是 update_column 無法送多個 params,於是必須只好用 sneaky-save 這個 solution 繞過。現在 4 直接支援 update_columns

ActionController

  • before_filter 更名為 before_action:就是正名...
  • respond_to do |format| 拿掉 xml 以 json 取代:2013 年了,沒人再拿 xml 當 default API...

Security

  • 拿掉 attr_accessible,改用 strong_paraments:去年 Github 被打下的事情鬧很大,Rails 的安全策略重新被檢討,於是最後社群討論出採用 strong_parameters 得這個 best practices。

Other

  • 砍掉 public/index.html : 砍掉愚蠢的 publc/index.html,以往教 Rails 初學者第一課就是記得砍掉這個預設檔案,不然寫的東西都會看不到
  • add_flash_type :以往警告訊息只有 [:notice , :alert, :error ] 三種類型,但是自從有 bootstrap 之後。大家習慣使用的是 [:notice , :warning, :error]。要套版時要一直手加 , :flash => { :warning => "Oh no!" } 是很智障的事,Rails4 開放自定義 flash types。(P.S. 這是我提的...)
  • mem_cache_store 換成 dalli:自從 1.9 出了之後,原先的 :mem_cache_store (memcache-client)會撞到 utf8 問題,於是大家都改用 dalli 作為 backend cache,Rails 4 的 :mem_cache_store 預設將改為 dalli。

New Feature

  • Model Concern / Controller Cern: 重複用到的 method使用 Concern 複用
  • Turboklinks : 無痛自動 pjax。pjax 不難,只要你用 Rails4 …
  • Cache Digest: 採用 Russian Doll Cache Strategy,智能 cache 設計,以前多層 partial cache 的問題讓大家實在很頭大。
  • HTML5 input form helpers: 現在是 HTML5 的時代,開發時自然會使用很多 js plugin,如calendar plugin,但用傳統的 form object 去產生這些 field 實在很痛苦。Rails4 內建了 HTML5 input form helpers。
  • 採用 jbuilder 產生 json : 生 json 可以採用類似生 rss 的方式寫 builder,真是驚訝這個 feature 現在才出現 ….

結論

學 Rails4 最快的方式不是看書,因為總體而言,這次的升級並不是什麼大破壞。改良的 syntax 和好用的新 feature。反而應該會減少不少平常開發上的負擔。而學習 Rails4 最好的方式就是用勇敢在現有的 project 上,大方的開一個 rails4 branch 下去練習升。

不用花很多時間你就能感受到 Rails4 新 feature 帶來給你的好處…

// 警告:以上建議只針對 Senior Rails Developer。目前還有一些 gem 沒有 Rails4 版本。所以 project 升級有時候會遇到必須要自己 fork gem「手動升級/Hack」的狀況,不熟包 gem 者勿輕易嘗試。

這次內建的一些 feature,其實都還蠻有意思的,也許將來還會挑幾篇特別再寫幾篇文章...

資源