tag:blogger.com,1999:blog-95902402024-02-28T23:55:05.153+08:00TCC's Blogtcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.comBlogger31125tag:blogger.com,1999:blog-9590240.post-2809456194971192782016-06-27T07:18:00.000+08:002016-06-27T07:34:23.940+08:00資料流 dataflow<div style="text-align: center;">
<a data-flickr-embed="true" data-header="true" href="https://www.flickr.com/photos/losangelesdistrict/7244057354/in/photolist-c38FSA-c38Rts-c394zy-c38ADm-c391wy-c399fQ-c3972S-bcDFeZ-bcDDZp-bcDmCi-bcDpYr-bcDuEx-bcDAvK-diuqY9-diuzxR-diux65-diuqNf-diurCn-diuxrk-diursk-diuuih-diuz9w-diuxqw-diuvF5-diuwjt-diuuS3-" title="120518-A-AB280-_-30"><img alt="120518-A-AB280-_-30" height="332" src="https://c3.staticflickr.com/9/8167/7244057354_7235949dd2.jpg" width="500" /></a><script async="" charset="utf-8" src="//embedr.flickr.com/assets/client-code.js"></script>
</div>
<div style="text-align: center;">
<br /></div>
即使再愛寫程式, 仍然相信未來的數位應用是不需要寫的。<br />
<br />
如果不用寫, 那會是:<br />
<ol>
<li>程式產生器, 像填寫問卷或描述摘要一般, 再生出對應程式。</li>
<li>強化版 IDE 或 Scratch/Alice 拖拉。</li>
<li>人工智慧 加 對話介面 (Siri+)。</li>
</ol>
前兩項侷限在某些範圍, 最後一項雖然部分已達成, 但普及(廣度/深度)仍然需要時間。<br />
<br />
比較相信的方式是透過資料驅動 (data driven), 雖然這詞已被定義在特定範圍, 這裡以更廣的角度來看 …<br />
<br />
用時事舉例, 偏黑色的例子: 如果一個名字出現在高層的『黑名單』, 不用特別吩咐, 組織裡就會有特別的處理方式。在這情境下, 名字資料, 有機會驅動許多非正規服務的運作。服務的多寡, 端視人心有多黑。<br />
<br />
愈寫愈冷, 換點正常的舉例。<br />
<br />
有一陣子, 在商業/工作流程的產品上開發。流程、表單、管理, 組合得好, 客戶也開心 … 幾乎相信這是數位化的聖杯。直到某年夏天安裝冷氣, 師傅們能在 12 樓凌空裝支架固然讓人驚嘆 (工作加表演, 合法嗎?), 完工後立即用 Line 拍照回報, 才發現之前產品有些地方是到達不了的。整個過程能辨識身分(IM User), 在特定通道(開群組)資料不會亂, 而使用者要準備的資料只有照片 (手機應用的普及又比客製程式優) … 不用專屬產品, 卻綽綽有餘。雖然做功能評比, 產品可能會有優勢, 但實務上是能忽略。<br />
<br />
另外, 豐富的雲端應用, 也消彌客製開發的必要。<br />
<br />
例如, <a href="https://www.google.com/forms/about/">Google Forms</a> 讓問卷填寫、搜集更容易。遇到排班表的需求, 雖然表單難做, 但可直接使用 <a href="https://www.google.com/sheets/about/">Google Sheets</a> 像真實的班表開放給大家填。配合清楚的規則(有填寫紀錄), 以及 Line 即時使用協助, 只要填上姓名資料即可。原本預計幾天才能做完(傳統紙本), 結果不到一個小時就收工。<br />
<br />
這三個範例, 都只有少量且必要資料, 就足以成事。形式上分別類於反應式 (reactive, 資料到服務), 流處理 (stream processing), 以及資料協作 (collaboration) 的例子。前兩者明確定義類等於資料流 (<a href="https://en.wikipedia.org/wiki/Dataflow">dataflow</a>), 最後一項是目前數位化應用的主力之一 。<br />
<br />
從已往開發的角度來看, 會需要採買或打通一些產品, 外加一些寫程式的工作。現在, 依附已有的應用, 在適當規劃下, 都只要一些資料就可達成目標。<br />
<br />
未來利用資料流的方式, 當是愈來愈多。tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-56903278152785123722016-06-20T23:12:00.000+08:002016-06-20T23:12:33.513+08:00應用開發的階段史 - 套包、殼層、木馬<div>
<img alt="How to Draw a Horse by Van Oktop" border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhipg8TNuQfdpOTCphOg_0PYEQWRiNse2fIPqWx73ybqET1IqfA18GLJ4Cq8y2znQlXA_Ej10ubHOLD2Ll3_OivKm9qqELkyZ1Dqld7ftqQJOOzBSGNwKhQXF2vlmUXgtWZcC-8w/?imgmax=1600" style="display: block; margin-left: auto; margin-right: auto;" title="How to Draw a Horse.jpg" width="222" /></div>
<div>
<span style="color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px;"><br /></span></div>
<div>
<span style="color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px;">應用開發有趣的地方, 除了有寫不完的程式, 某種程度必須與時俱進, 不斷的面對改變。再者, 資訊科技在各行各業滲透程度愈來愈高, 自然產生更多應用開發的需求。變化, 擴散, 再加上循環, 形成無窮盡。有人厭倦, 卻也有更多人加入。</span></div>
<div>
<span style="color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px;"><br /></span></div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
經歷一些隨坡逐流的改朝換代, 逐漸也有自己的步調, 去調適需求, 參與人力, 以及處理不同目標。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
從流行的角度, 所謂的階段應該是 web, agile, mobile, serivce, cloud, big data, …。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
這裡從過往經歷不同的嘗試來看:</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
最早著手於開發的基石們, 不斷認識不同的語言, 元件, 工具。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
一直到現在, 用套包 package 解決特定問題, 產品、框架、服務大多以這種方式存在, 相處也愈來愈自然(不見得輕鬆), 不論是著手使用, 或要加加減減。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
再一步是面對人力更迭。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
長久以來, 雖然大家的任務可能不同, 不同工但同具, 甚至同工同具, 讓大家視野皆同, 很多問題時間可解。一旦有客戶的人員要加入開發組, 就成為一項挑戰, 因為整疊工具要上手, 並不是短短時間可解決的。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
雖然主流是大家一起學寫程式, 但有難易、親疏之分, 要把人力拉齊不容易。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
開源常見的腳本語言可解這項難題 … 把落落長的實作, 用更容易表達的方式呈現。對新加入開發組的客戶而言, 更好學習, 更好應用, 也更容易維護。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
原本歸功腳本語言的強大, 後來習得資料流 (dataflow) 手段, 以試算表 (spreadsheet) 搭配某元件解決另一項難題後, 方才體驗到這是殼層 shell 概念在發功。是 linux, osx 使用者的日常, 但放到應用開發 … 可讓需要程式專業的部分開放給更多人參與。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
最後是跳脫循規蹈矩。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
原因是客戶指定基石 .net 加上 m 社的一堆產品。.net 固然是近來完整又與時俱進, 有問題的是搭建在上面 流程、表單 等產品。後來 m 社也宣告 2013 是最後一版, 且在 2023 停止支援。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
實際面臨的問題是, 即使只改一個需求甚至改一個字元, 都得歷經一段超過 10+ 分鐘的特殊工具存檔, 打包 (pack) 與部署 (deploy) 過程。這和主流編纂原碼, 由版本控制系統加持部署的方式大不同。而且它的部署還不時有原因不詳的失敗 … 實際時間是 n 倍計。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
儘管不同平台有不同部署的方式, 但對於資訊應用系統, 以原碼或利用殼層隔出原碼操作, 讓所改即所得, 是較理想的方式。最好的例子是 web 應用, 不論 html/css/js 如何往上擴充, 原碼透明度都高, 找問題並解決才方便。畢竟運算資源提高了, 這種方式對待人力資源是比較友善的。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
改變的契機在一個與 linux 整合的專案, 前端依然是 m 社的產品組合, 後端則帶進開源服務套件。後來順勢把其他專案的後端都取代, 但使用者接觸到的包含 m 社的 web 介面、管理、資料庫保持不變。取而代之的後端可視為木馬, 透過這個木馬讓開發者得以直接變更原碼, 更快更容易達成目標。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
以上回顧了過往開發的三個階段: 套包(package), 殼層(shell), 木馬(trojan)。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
基本上, 對一包包推陳出新的零件保持興趣, 相處得好, 伺機解決疑難雜症。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
這些有的可能是產品, 有的是框架, 有的是服務, 有的是個語言, … 各別自成體系, 學習曲線各自不同。如果需要更多人加入擴展應用系統, 人員程度角色不一的狀況下, 規劃出殼層是種解決方式。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
搭建殼層通常透過腳本語言做簡化和操作 API 以及資料, 如果要非程式人員也能貢獻, 規劃資料流的殼層, 例如試算表則是更佳法門。</div>
<div style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin: 0px 0px 16px;">
然而面對品牌迷思, 教育別人, 不如改變自己, 種子也要扎根才有長大的機會。塞個玻璃般透明的木馬, 成為一種手段, 畢竟開放又方便, 讓人很難拒絕。</div>
<ul style="box-sizing: border-box; color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; margin-bottom: 16px; margin-top: 0px; padding: 0px 0px 0px 2em;">
<li style="box-sizing: border-box;"><a href="http://oktop.tumblr.com/post/15352780846" style="background-color: transparent; box-sizing: border-box; color: #4183c4; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px; text-decoration: none;">How to Draw a Horse</a><span style="color: #333333; font-family: "helvetica" , "arial" , "freesans" , "clean" , sans-serif; font-size: 16px;"> by Van Oktop</span></li>
</ul>
tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-30374406540708752852015-06-01T09:16:00.003+08:002015-06-01T09:19:05.100+08:00打造微服務<p>剛開始並沒有預期是使用微服務。</p><p>在不斷調整的過程, 以及閱讀他人的想法後, 瞭解自己所處的位置。</p><p>推敲起來, 像是在一個只有筷子的用餐環境下, 自然會去使用。雖然不是刻意, 終究殊途同歸的結果。</p><p>主題是替某個研究單位打造內部資訊系統, 將目標和資源透明化的專案管理工具。</p><h3>開始打工, 指定 M 社的 CMS 方案</h3><p>團隊成立, 有不少角色, 大家都在熟悉中。<br>照傳統的方式進行訪談, 分析, 設計, 實作, …<br>光是資料表就討論大半年, 畢竟這是全部的人都認識, 總能談上兩句。</p><p>在 M 社工具(SD/IP/SM/VS四樣)加持, 歷經一番波折後完成。 <br>工具多, 卻有各自的假設。在預給情境下, 拖拉點貼就解決。 <br>然而, 經常面對的是一堵堵高牆, 愉快的滑鼠生涯了結, 開始耕碼長征之路。<br>在 API 叢林穿梭; 也在系統間徘徊。 <br>幸好有許多第三方元件支持, 第一版得以面世。</p><p>棘手的問題在於, 冗長的開發到結果, 是一大包(monolith)。<br>縱使 M 社兵多將廣, 面對複雜的環境, 提供更多工具, 卻更令人左支右絀, 疲於奔命。即使變更一小處字樣, 從修改到配置, 不僅耗工夫, 也費時間。</p><p>如果偏好階級化流程, 有一大撮團隊, 絕對可讓大家都很忙, 每個人都有事情做。</p><div class="separator" style="clear: both; text-align: center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirE-e21XSecW7rbfmVzxViEwwllC1v21RumjL-y3HnMrjUJD-POORKEtuxI0lTta4OSw86quKScHgMSb_ahZj7tFUr72lvGoTT5teYchd7QsbsK-qsKwvcNQJWrB4_dic01Em7CA/"></div><p><br></p><h3>因地制宜, 替系統加一層殼(Shell)</h3><p>當時領域探索的人多, 需求也多; 然而隨時間推衍, 變化也多。<br>按官方手法實作, 必定成為瓶頸。</p><p>為了將 <u>需求</u> 到 <u>實作</u> 的距離拉近, 借鏡 Unix, 在應用系統上加一層 Shell。作業系統的 Shell 通常是一個互動環境, 但在應用系統有不同呈現方式。例如要修改已有的網頁, 用 jQuery 一般比手工刻 JaveScript 好。存取複雜的資料, 透過 ORM 常不如 SQL 直接。而以框架為底、API/程式庫為輔、使用工具打造的應用, 也的敵不過腳本(Script)靈活。</p><p>這個案例是有工具負責資料綱目, 流程/表單, 並用 C# 做擴充。</p><p>最後維持資料綱目, 保留表單, 改為事件驅動(Event driven), 基本上利用 <a href="http://en.wikipedia.org/wiki/Windows_PowerShell" target="_blank" title="Powershell">Powershell Script</a> 在表單變化時更新資料庫, 同時擔任流程處理與擴充功能的任務。 對使用者的結果不變, 但流程的反應較好(原本頓頓的); 擺脫工具大包的束縛, 更快滿足需求。</p><p>從結果來看, 這個技巧是讓需求到方案的流動, 透過新搭建的 Shell, 約 80% 可快速流過; 縱使還有 20% 得經傳統工具, 由於毋需經常打交道, 阻礙自然較低。</p><div class="separator" style="clear: both; text-align: center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSPlGeMwmblVN8W_9hFeMFjKovE8Z0UL6M7xuDKncKGQ_lO56U1mjvPj8yBdKCiteEblijAVihDFjqZJd9atmsalaEtD-6RKjvBYHFOPLFF49-DycbPujDM8u1mVAKy4A27eAK2A/"></div><p><br></p><p><br></p><h3>持續開發, 逐步擴展, 遞加服務</h3><p>完成第二階段, 系統表現稱職, 跑出新題目 … 建立 TLD 服務。兩個子系統 bind/whois 包含 server 和 DB 在 Linux, 使用者介面被期望繼續在 M 社的 SP 上。一般性應用的開發, 會將 DB 連線拉到 SP, 解決跨系統、跨設備的問題。但我們以系統安全的角度, 選擇用訊息傳遞(messaging)來解決, 順勢引入 python 的網路服務引擎 <a href="https://twistedmatrix.com/" target="_blank" title="Twisted">twisted</a>。</p><p>隨著系統擴展, 在 2014 的某個階段, 決定後端服務皆用 twisted。</p><p>這個決定點在於, 綜使之前做了簡化, 但開發的元件散落在各子系統上。加上原廠的方案, 檔案幾乎都是 binary 或是一大串, 版本控管有麻煩, 再在使變更困難或成本驟增。</p><p>所以把在各子系統做的, 除 UI, 權限管理外, 將通訊處理(protocol)、編組/解組(marshalling / unmarshalling)、資料存取、子系統溝通(REST 或 Web Services) … 分層(layered)後做成 twisted 的服務, 全部處理都訊息化, 包含檔案上/下傳。</p><p>這些順勢做的改變, 後來對照 <a href="http://martinfowler.com/articles/microservices.html" target="_blank" title="microservices">microserivces</a> 的要件, 很多地方相似, 甚至一致。</p><p>最明顯的好處是在面對人力多樣化, 經歷過: 原班的開發人員, 甲方組織的員工, 以及最後加入的外包單位。自己組員問題少, 甲方組織要投入前, 備妥環境著實不易, 後來用簡化的虛擬機器(做成 VM), 讓人入手。 到了外包單位加入, 已經有新的架構, 只要把 python 環境建立(難度大概只有 1/20 吧?), 加上源碼儲存庫, 按著符合情境腳本(Scenario)的 nose 測試碼, 就可開拓新的道路。不論開源工具帶來的好處, 新的方式讓開發者在特定區塊(Bounded context)就可完工, 是差異所在。</p><p>按照目前狀況, 應用系統想組合/分散功能, 更換子系統, 包含資料庫與文件管理(DMS), 甚至作業系統(docker?), 都變成策略面的考量, 不會因為技術造成障礙, 或讓開發好的應用鎖在某個地方。嗯, 是鎖在 python 上沒錯, 不過還有幾個選擇 …。</p><p>(待續)<br></p>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.comtag:blogger.com,1999:blog-9590240.post-15481857362441793692012-12-09T19:18:00.000+08:002012-12-09T19:18:00.239+08:00PDF Forms<p>近來關注著表單的相關方案, 除了 Web(眾多框架, <a href="https://github.com/powmedia/backbone-forms" title="backbone-forms">backbone-forms</a>), XML(<a href="http://www.w3.org/MarkUp/Forms/" title="The Forms Working Group">XForms</a>, <a href="http://msdn.microsoft.com/en-us/office/aa905434.aspx" title="InfoPath">InfoPath</a>, <a href="https://developer.mozilla.org/en-US/docs/XUL" title="XUL | MDN">XUL</a>) … 前陣子逛軟體商店, 才發現有處理 <a href="http://en.wikipedia.org/wiki/Portable_Document_Format" title="Portable Document Format">PDF</a> 表單這類 App。</p>
<p>搜尋相關資源, 整理一下 …</p>
<p>雖然系出 <a href="http://www.adobe.com" title="Adobe">Adobe</a>, 卻也不一定需要 Adobe 官方指定工具, 就能從頭到尾、從建立到處理, 完成所有工作。</p>
<h1>特點</h1>
<p>和 Web, XML 方案要一整個系統最大的差別, 在於 PDF 的表單只要單檔就可運作。</p>
<h3>1. 方便移動</h3>
<p>PDF 表單除了只要單檔, 和 PDF 一樣, 不論行動設備或各種常見的作業系統都通行。</p>
<p>在 OS X 上的 <a href="http://support.apple.com/kb/HT2506" title="Mac Basics: Preview">Preview</a> 可直接填寫。</p>
<p>另一個觀點是能離線作業 … 得以各別填妥表單再傳送處理。</p>
<h3>2. 容易讀取</h3>
<p>不論對人與電腦都方便。</p>
<p>PDF 可輸出的樣式彈性很大, 幾乎是報表方案的代名詞。好讀自然不再話下, 只要有適當的設計規劃。再加上一些欄位就成為 PDF Forms, 立即讓人填寫。</p>
<p>讀取表單內容, 可利用 <a href="http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/" title="The PDF Toolkit">pdftk</a> 直接讀出資料, 毋須寫程式也可使用 … 在下一段介紹用法。</p>
<h1>實作</h1>
<p>很多介紹, 是以寫程式來產生 PDF 表單, 後續處理表單資料也要額外程式 … 其實不一定需要, 這些工作不寫程式也能達成。</p>
<h3>1. 建立表單 PDF Forms</h3>
<p>在 OS X 有 <a href="http://smilesoftware.com/PDFpenPro/index.html" title="Create PDF Forms, PDF Table of Cotents">PDFpenPro</a>, <a href="http://sintraworks.com/index.php/sintraworks/pdfclerk_home" title="PDF Editor for Mac OS X">PDFClerk Pro</a>, <a href="http://sintraworks.com/index.php/sintraworks/pdfnomad_home" title="PDF Editor for Mac OS X">PDF Nomad</a> 可替 PDF 加上表單欄位。</p>
<p>開放源碼 <a href="http://www.openoffice.org" title="The Free and Open Productivity Suite">OpenOffice</a>(使用版本 3.4.1), 則可在各平台直接建立 PDF 表單。步驟大致如下:</p>
<p><em>a. 新增 XML 表單</em></p>
<img style="display:block; margin-left:auto; margin-right:auto;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM_hbUHC9kBCuPiMlsV-9phjaGqxok2UlZc1e5kbWVV2DDUeLvscGPqevMPmhBs4PepSB94kFCvoqgoYWOVUb1gWASuo4IOq0VCUM0stcKQsnWUW2Nz4BWSTnQbkx3EDQiG89ZVQ/?imgmax=800" alt="11 New XML Form" title="11_New_XML_Form.png" border="0" width="500" height="235" />
<p><em>b. 建立表單項目</em></p>
<p>在下面的範例, 塞一張圖檔、加一些欄位, 額外使用淡紅色標示<strong>欄位名稱</strong>。</p>
<img style="display:block; margin-left:auto; margin-right:auto;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtwkK6v50eDxpyE-n2V9dGJXIlUeOk8f4MxV6j6klmB2gHu5eVTl3mDRSwIxE9jZ9mkYN8dpD0VthAN7DYEkHtPCZ2eARvVw8H2t0Qi2EzCvq6O9Ajnsljzy-JTQNfiJLOGKgQbg/?imgmax=800" alt="12 Construct Form" title="12_Construct_Form.png" border="0" width="500" height="480" />
<p>建妥表單, 再到下一步。</p>
<p><em>c. 輸出 PDF 表單</em></p>
<img style="display:block; margin-left:auto; margin-right:auto;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAZXQyhk1DAtTbh4HnLjyZKvdOcCL5SqNB9lpcveuWy6a13gftlhAlqiRfHAoLx7EM0VSnV1ireiI7KG9Celt1fr9vzOVC1qQgHPlNgP3EMmhroyXK-jfgOgqN70av1H6ohDJn5Q/?imgmax=800" alt="13 Export PDF" title="13_Export_PDF.png" border="0" width="350" height="420" />
<p><em>d. PDF 表單選項</em></p>
<img style="display:block; margin-left:auto; margin-right:auto;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikRhl5ey-TKb5O0QeJBLcwNk4G_w-sXDdYLF0Ydv3TE0AIywq-QB3JWM92-tUXv448WEdPsLO-8GYQolTRr-GyYFmbAPEqmfDUv0iOnEvD3cGmgjFmTVrz592F0NpojbkSVxzo5A/?imgmax=800" alt="14 Export PDF Options" title="14_Export_PDF_Options.png" border="0" width="350" height="530" />
<p><em>e. PDF 表單檔名</em></p>
<img style="display:block; margin-left:auto; margin-right:auto;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEeA6p_78d2gYilJN3a5gQ8A-bEAN43lgnf3PPuNeBjzSatNWnHFD1wwxJcBz1enk79sjrJU-6aJIvQcX2BuvLH7wBPCpZV93U2NWsGe4z_sQSnM2C0sl0t9rv__5JcuhU_4AhEA/?imgmax=800" alt="15 Export PDF Filename" title="15_Export_PDF_Filename.png" border="0" width="350" height="188" />
<p>完成以上步驟, 應該能順利產生 PDF 表單: <code>fruit_order.pdf</code> 檔案。</p>
<p>下載: <a href="https://docs.google.com/open?id=0B4MEOq8szFL2UndETVFOM2pUdFk" title="Fruit Order - OpenOffice file">fruit_order.odt</a>(無法預覽, 請選擇下載), <a href="https://docs.google.com/open?id=0B4MEOq8szFL2a0NxZHU5bGU0OE0" title="Fruit Order - PDF file">fruit_order.pdf</a>(線上看有點怪, 下載後 ok)。</p>
<h3>2. 取出資料</h3>
<p><em>a. 填寫表單資料</em></p>
<p>使用 <a href="http://support.apple.com/kb/HT2506" title="Mac Basics: Preview">Preview</a> 按上面 PDF 表單給定欄位, 填入各項資料。</p>
<img style="display:block; margin-left:auto; margin-right:auto;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-kbzFCtfimibyOv-ATLrXkTpPae3ncCfCbVIa5T05MR9RM2v8EitihlDU-MZWWX3KKk9wdazATYfSUOBQOc5KIk63Czq7z0O4CAtvZbNCMYOevodyLa4LlxSp0vOLfNFo4E5gAQ/?imgmax=800" alt="21 Fill PDF" title="21_Fill_PDF.png" border="0" width="500" height="400" />
<p>填入的資料會存入該 pdf 檔案中。</p>
<p><em>b. 讀取表單資料</em></p>
<p>使用 <a href="http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/" title="The PDF Toolkit">pdftk</a>, 如果檔案放在 ~/Desktop/fruit_order.pdf, 執行如下指令:</p>
<pre><code>$ pdftk ~/Desktop/fruit_order.pdf dump_data_fields_utf8 output -
</code></pre>
<p>就可將表單資料輸出到 <code>stdout</code>, 或把 <code>-</code> 改為檔名, 選擇輸出到特定檔案。</p>
<img style="display:block; margin-left:auto; margin-right:auto;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVZNUYwVDz3wSVh3-FSpCUfrx_EKlhYPxrvlE47z6ZXrJwa7Z-YVUbrKSWa-FSp11GRFPQpECP8M57C-2qq-H71lwfq13mbOV3lV5Ns6Ak1N1HB1AYDJxe0aH1YJOTLMGyfNdOdg/?imgmax=800" alt="22 Use pdftk" title="22_Use_pdftk.png" border="0" width="385" height="600" />
<p>和先前 <strong>b. 建立表單項目</strong> 步驟比較, 可看出 <em>欄位名稱</em> (FieldName) 和 <em>填寫資料</em> (FieldValue) … 很容易對上。</p>
<h3>3. 佈置 PDF 表單</h3>
<p>從上面的介紹, 瞭解 PDF 表單 <strong>建立</strong>, <strong>填寫</strong>, <strong>讀取</strong> 方式, 接下來看看怎麼安置這些 PDF 表單檔案。</p>
<p><em>a. 電子郵件</em></p>
<p>PDF 放在網站上提供下載, 或以電子郵件傳給需要填表單的人。</p>
<p>在 PDF 表單裡頭標注, 填寫完寄給 foo@jia-side.org … 即可完成表單發送、接收的程序。</p>
<p>只是收到 PDF 檔案後會怎樣被處理, 全取決於經辦人員。</p>
<p><em>b. 檔案分享</em></p>
<p>適合組織內區域網路中檔案共享, 或使用網際網路檔案服務的方式 … 也就是特定群組內的檔案分享。</p>
<p>在檔案相關系統中, 安排 PDF 表格處理方式的各種<strong>目錄</strong>。例如: 所有表單的 <strong>樣板目錄</strong>, <strong>處理中目錄</strong>, <strong>完成目錄</strong>, 以及最後流入按年份分門別類的 <strong>庫存目錄</strong>, …</p>
<p>使用大部份人都熟悉的方式, 不同<strong>工作</strong>在不同<strong>目錄</strong>間流動, 即可完成許多原先紙本的工作。</p>
<p><em>c. 內容管理 + 流程系統</em></p>
<p>基本上, 是前個項目 <em>b. 檔案分享</em> 的進階版 … 概念相同, 但所有動作自動化。</p>
<ul>
<li><strong>樣板目錄</strong> 中, 各表單的版本由<strong>內容管理</strong>區分。</li>
<li>新填表單送入 <strong>收件目錄</strong>, 由<strong>流程系統</strong>分派給經辦人員。</li>
<li>表單處理的特定過程, 皆由<strong>流程系統</strong>安排。(可考慮資料檢核)</li>
<li>處理完成, 按<strong>流程</strong>安排的步驟放入 <strong>完成目錄</strong> 中, 供相關人員瀏覽。</li>
<li>老舊檔案的時間屆存檔年份, <strong>內容管理</strong>負責移到 <strong>庫存目錄</strong> 備查。</li>
</ul>
<h1>用途</h1>
<p>表單是許多組織行動的基礎, 單純表單的角色, 卻常被使用<strong>系統</strong>與<strong>人力</strong>資源所左右。</p>
<p>複雜的系統, 其本身往往就需要很多專業人士來維持。</p>
<p>從頭打造的應用系統, 建立/維護也是個問題, 總不成每每來個衝刺。</p>
<p>使用 PDF 表單, 有機會突破這些罩門。</p>
<ul>
<li>能操作文書軟體, 就能建立/維護表單。</li>
<li>不需 Web 專業, 也可在表單中盡量放入必要訊息。(參考高鐵<a href="http://www.thsrc.com.tw/tc/transfer/transfer.asp" title="高鐵轉乘服務">轉乘服務</a>的PDF檔)</li>
<li>讀取表單內輸入項目的資料, 只要工具, 不用寫程式。</li>
</ul>
<p>使用方面 PDF 表單也近似紙本表單, 能<strong>高亮</strong>(Highlight)標示、張貼<strong>備忘</strong>(Note) …</p>
<img style="display:block; margin-left:auto; margin-right:auto;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiai6IkfxnQqPkcXeIe0iT1CKqIXd2DK2zKb373vUFK5xBt4KjS93wJMAbUp8ifP9T7J_j7CzF4XTu1gd58bMjr1gmV5Nq5vB3YwKukC1ihjghvwsAj-CVkE_IUETAPi7tiUoqbvA/?imgmax=800" alt="31 Preview PDF Note" title="31_Preview_PDF_Note.png" border="0" width="500" height="320" />
<p>再者, 若打通檔案的流通, 透過智慧手機、平板設備處理 PDF 表單, 會更接近真實填寫表單, 包括<strong>簽名</strong>。</p>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-42512698760965409312012-09-18T19:18:00.000+08:002012-09-18T19:18:00.553+08:00PyHUG 2012/09 <p><a href="http://www.meetup.com/pythonhug/events/67461922/">PyHUG</a> 九月份主題是 BBS Crawler(<a href="https://github.com/buganini/bsdconv">bsdconv</a>) 和 <a href="http://plone.org">Plone</a>。</p>
<p>bsdconv 在萬碼奔騰的年代, 處理多種 codecs 和多樣 encodings 是很好的方案。</p>
<p><a href="http://marrtw.blogspot.tw">marr</a> 帶來 Plone 這個 <a href="http://en.wikipedia.org/wiki/Content_management_system">CMS</a>
的簡介和近況。早先我學習 <a href="http://python.org">Python</a> 是想用 Plone, 它是一個有感情基礎的 CMS XD</p>
<p>在討論的過程中, 有人對客製強化功能有興趣, Plone 也提供很方便的工具, 我過去也是
跟著既定的脈絡走。但最近使用 <a href="http://en.wikipedia.org/wiki/Microsoft_SharePoint">SharePoint</a> 和
<a href="http://en.wikipedia.org/wiki/Microsoft_InfoPath">InfoPath</a> 執行一個中大型屬於
CMS 的案子, 所以有其它想法。</p>
<p>首先, 在資料規劃上 … 大量, 多欄, 關聯的資料, 最好的歸宿還是資料庫。CMS
適合擺放目錄式, 多樣(圖檔, pdf, xls, doc, …), 和多版本(v1, v2 的 doc) 的資料。</p>
<p>概念上, 前者適合應用程式(Application), 後者配合流程(Process)。</p>
<p>應用程式處理資料的方式千變萬化, 通用的資料庫仍舊是好選擇。特別是商用資料,
對資料有各種使用方式, 避免瞻前顧後的話, 資料就放在成熟的方案裡頭。</p>
<p>如果說資料庫中表格(Table)的上位是 ERD, CMS 中內容(Content)的上位就是內容型態
(Content Type, CT)。不論 Plone, SharePoint, 或 <a href="http://jackrabbit.apache.org">Jackrabbit</a>
都有相同的概念。通常在 CMS 以檔案系統的概念來做高階規劃 … 建立目錄結構,
接下來就是在目錄下分配使用 CT。一個目錄可使用多個 CT, 也就是先前提到的
多樣性, 而 CT 有不同版本對應不同 Content, 即多版本也順利在 CMS 中成立。
拿程式語言來比擬, CT 像是 Class, Content 是 Object, Folder 是 Collection。</p>
<p>再加上 CMS 對 CT, Folder, Content 有良好權限管理 (Plone 強項, 可類比成
檔案系統的權限設定)。基本上放在 CMS 的資料, 不會被不相干的人取得, 竊認為這是
和資料庫最大區別。</p>
<p>試想 … 流程有多樣電子資料要附帶著, CMS 就是一個很好的載體, 要區分存取權限
也容易。流程若有調整, 造成電子資料的差異, CT 多版本能順利解決這類問題。</p>
<p>應用程式當然也可以做, 但中間規劃, 設計, 與元件 … 太多是重複問題。有些框架有元件,
先不論功能適用, 能像 marr 所言: 最新的 Plone 4 最新版還照顧到 7,8 年前的 Content
就是個門檻了 XD</p>
<p>而許多事務流程系統, 重視流程的彈性, 卻忽略實際工作的要務 … 讓整合困難重重。</p>
<p>說到這裡, 有個題目是 … 表單 (Form) 適合資料庫, 還是 CMS?</p>
<p>不用說很多 MVC 以資料庫為主, 很多 View 概念上就是表單, 甚至 HTML 都有 form 標籤。
考慮實際流程發生的安全問題, 檔案管理, 流程變更要兼容並蓄(新/舊版本), 雖然有各式
各樣的解決方案, 但這些問題放在 CMS … 很自然就被解決掉了。</p>
<p>但在 CMS 裡頭做表單, 問題是 … 簡單的很快, 複雜的費工又很痛(會的人不多)。</p>
<p>我忽略 CMS 的角色有一段時間, 直到用過 InfoPath …</p>
<p>簡單來說 InfoPath 可直覺且快速完成複雜的表單(免除魔術師養成), 然後在 SharePoint
做為一個 CT。安排在特定目錄下, 表單資料存成一個純 XML 檔案, 取得也是一個 XML 檔案。</p>
<p>這種方法接下來的問題是, 要把資料放在資料庫 … 現在資料庫處理 XML/Json 都很<a href="https://github.com/fdr/plv8js">強大</a>,
都可以直接吃 XML, 或輸出 XML … 省卻中間的 App Server 或魔術師用的框架, 只要有
SQL 經驗, 輔以一些 XML 的操作就可上手。</p>
<p>整個過程大致是:
</p>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiAIuagYOAoRxiyE5yKX_hmjCfGtGDP0cI0CvNk9RslFbefMcf9EboYe-f5dezz7rAjZrYayOWuqWcxBX2hLTqPHaffQYEzcC1RBoY09UsU_nQ4xQtY6mWJUpmFCrUha7vbbOKrw/s1600/cms_form_db.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="240" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiAIuagYOAoRxiyE5yKX_hmjCfGtGDP0cI0CvNk9RslFbefMcf9EboYe-f5dezz7rAjZrYayOWuqWcxBX2hLTqPHaffQYEzcC1RBoY09UsU_nQ4xQtY6mWJUpmFCrUha7vbbOKrw/s320/cms_form_db.jpg" /></a></div>
<p>基本上, 在 CMS 的加持下, 免除了表單與資料庫千絲萬縷的關係, 變成有必要才做。</p>
<p>而 OSS 在這方面 … 目前看到的方案還是與資料庫緊密結合 orz</p>
<p>除了一些以 JavaScript 加重瀏覽器負荷的專案, 例如 <a href="https://github.com/powmedia/backbone-forms">Backbone-form</a> … 這也是最近嘗試瞭解的題目。</p>
<p>以上是從 Plone 這 CMS 角色延伸想到的 ... 整理下來。從服務式架構的角度, 各組合的角色要清楚, 避免把太多東西塞到某個元件裡。很多時候, 應用開發沒有問題, 畢竟很多功能的差異都可透過努力去彌補, 但清楚的角色有助於系統維護, 另一方面考慮元件的生命週期, 要升級/替代也才能較順利的進行。</p>
<p>另外, 會後聊到 Gmail 保密問題, 我有時會用 GnuPG 套件 … 如果收信人願意的話 XD</p>
<p>組合是 <a href="http://www.postbox-inc.com">Postbox</a> + <a href="http://www.postbox-inc.com/extensions">Enigmail</a>, Postbox 對 Gmail 的支援良好, 又吃 Mozilla based 的 add-ons (Enimail 提供 GnuPG 功能)。</p>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-57782388914839109512012-09-11T19:18:00.000+08:002012-09-11T19:18:00.420+08:00嘗試 Require + LiveScript + Backbone最近想利用 <a href="http://backbonejs.org/">Backbone</a> 的某個套件來做東西, 於是開始摸索 Web 前端。
<br />
<br />
原先打算用 <a href="http://coffeescript.org/">CoffeeScript</a> 撰寫 Backbone 相關程式碼, 只是
<a href="https://speakerdeck.com/u/clkao/p/livescript-tax-free-javascript">半路</a> 看到更加
有趣的 <a href="http://gkz.github.com/LiveScript/">LiveScript</a> … 馬上改弦易徹。
<br />
<br />
對 LiveScript 新手, 最初的挑戰 … 不確定寫的是對還是錯。 LiveScript 有個方式是
轉成 JavaScript 來確認 … 雖然有 <a href="https://github.com/paulmillr/LiveScript.tmbundle">LiveScript.tmbundle</a>
可為 TextMate/<a href="http://www.sublimetext.com/">Sublime Text</a> 加持, 由於挺偏好 <a href="https://github.com/Xavura/CoffeeScript-Sublime-Plugin">CoffeeScript-Sublime-Plugin</a>
透過 <a href="http://thecrumb.com/thecrumb/2011/11/03/sublime-command-palette/">Command Palette …</a>
選擇 <i>CoffeeScript: Run JavaScript</i> 的方式, 把 CoffeeScript 轉成 JavaScript。於是
混合 LiveScript.tmbundle 和 CoffeeScript-Sublime-Plugin 建立 <a href="https://github.com/tcc/LiveScript-sublime">LiveScript-sublime</a>
專案, 加強 Sublime Text 對 LiveScript 的支援。
<br />
<br />
接下來是程式碼模組化, CoffeeScript 有 <a href="https://github.com/jrburke/require-cs">require-cs</a> 擴充
<a href="http://requirejs.org/">Require</a> 載入 CoffeeScript 能力, 但 LiveScript 沒有。因此參考 require-cs
建立 <a href="https://github.com/tcc/require-ls">require-ls</a>, 方便 LiveScript 切分模組。
<br />
<br />
最後試著把這些組合起來, 以 Backbone 原本的 <a href="https://github.com/documentcloud/backbone/tree/master/examples">範例</a> 改寫
為 LiveScript 加上 Require 的版本 … 建立一個 <a href="https://github.com/tcc/require-ls-backbone">require-ls-backbone</a> 專案記錄這些嘗試。tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-84613778711273905182012-08-13T11:52:00.000+08:002012-08-13T11:52:01.690+08:00集中/聚眾/集眾開發一直從事軟體開發工作, 其中不論參與產業, 各類技術, 團隊規模, 時間長短, 雖有各有不同, 皆是解決客戶問題為主, 也都是專案的型態 … 而專案執行方式也各有不同, 從古早到近年流行的, 或多或少都參與過。總的來說, 都是由外而內的驅使著開發者, 必須針對客戶的需求做處理, 做回應。<br />
<br />
從剛開始是廠商, 標準, 或方法的傳聲筒, 到現在能夠提出各式各樣的<s>嘴砲</s>意見。這是 … 馬齒徒長!!??<br />
<br />
由外而內的改變, 雖然邊拉距邊有進展, 但聽說真正的成長是由內而外。因此, 開始思考在執行專案時, 發生衝突到最後調和的事件。嗯, 這篇不是談技術, 因為技術最好的歸宿就是被消滅; 也不是談業務, 因世代更迭的業務, 總是來來去去。目標是整理一下開發大環境的差別, 及相關的影響。最後歸納為, 開發者正經歷集中開發(Central), 聚眾開發(Clustered), 與集眾開發(Crowded)的不同世代。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDLrglaGqx8nldWYVH9rQOFCi7N16YA_MbLCwrpquG6mPeM6rN0yKexg_FCuV-godf979Kg69JvnkU75Ut9NMk_-mqWwDBJVu4YyyvTNJOl-61UBcP0UZoW2IogOIctw4SLv4CkA/s1600/3c_dev.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDLrglaGqx8nldWYVH9rQOFCi7N16YA_MbLCwrpquG6mPeM6rN0yKexg_FCuV-godf979Kg69JvnkU75Ut9NMk_-mqWwDBJVu4YyyvTNJOl-61UBcP0UZoW2IogOIctw4SLv4CkA/s400/3c_dev.jpg" width="400" /></a></div>
<div style="text-align: center;">
<br /></div>
<br />
把紅點視為一開發單位, 紅點散落位置區分了不同的方式:<br />
<ul>
<li>集中開發: 紅點集中在一起, 為共同目標而努力。</li>
<li>聚眾開發: 紅點聚落各有長處, 分工聚落各有發揮, 但聚落合作才能完成目標。</li>
<li>集眾開發: 當群體進展到某個程度, 個別單位縱使降低對資源的要求, 還是能達成目標。</li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYLf-Mn0OadR9kFp0J0MztTnzw7I0qO1v4bRPeRSLFjvA22f9tj0BOjORooJtGqcpxKmH7YuBFTqUnRr1pzdOj8K298ND1WJOZ-dnVqVmB2klaxQulKQ1EydqEU_pYRDxDMl7V7g/s1600/3c_ex.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYLf-Mn0OadR9kFp0J0MztTnzw7I0qO1v4bRPeRSLFjvA22f9tj0BOjORooJtGqcpxKmH7YuBFTqUnRr1pzdOj8K298ND1WJOZ-dnVqVmB2klaxQulKQ1EydqEU_pYRDxDMl7V7g/s320/3c_ex.jpg" width="320" /></a></div>
<div style="text-align: center;">
<br /></div>
<br />
從硬體, 軟體, Java 舉例來說:<br />
<ul>
<li>硬體: 古早到現在 IBM 的角色, 毋庸置疑; 台灣著名的就是電腦組件聚落; 蘋果則近年來讓電腦取代寵物的地位方面功績卓著。</li>
<li>軟體: Oracle 專長打造資料的家; MS 建立的聚落嚴有許多 … 作業系統, 企業應用, 遊戲; SF 雖然漸漸被取代, 但卻是讓大眾發表分享源碼, 方便交流的起點。</li>
<li>Java: Sun 早先前集中資源打造出跨世紀的 JVM, JDK; Apache 以 Web, Services 甚至雲端著名, 近來常做撫養托孤業務; Hadoop 是 Apache 其中一個聚落, 但更能表現集眾開發, 為此獨立出來。 </li>
</ul>
先看 Apache 與 Sourceforge, A 和 S 都是開放源碼的重鎮, 但 A 是會員制, S 則隨開隨用。Apache 能到頂層(top level)的專案, 幾乎都可視為一個聚落, 聚集著對專案有興趣的公司或個人。開始先在論壇, 事例追蹤上參與, 被認同後才賦予擔負工作的身份。A 要去瞭解, 要去參與, 而 S 只要名稱不同, 很快就能開個專案, 我還是我。在早期 S 能聚集的是本身具備吸引力的專案, A 透過組織方式更能推動發展。<br />
<br />
發展到一個階段, 開發不只著重開發者的角色。以社群類處理的使用者數量來說, 是早先集中式商業公司嘗試以高規格軟硬解決而失敗的題目。流行的方式是將問題分解, 個別強化, 捨棄不需要的部份, 組合成因應需求的系統。例如, 連線數量(MINA), 訊息處理(Camel), 計算能力(Hadoop), 資料存取(Cassandra), 內容管理(Jackrabbit), … 全部都可以分解, 組合, 不需要一個全能的應用伺服器(Application Server)。<br />
<br />
更重要的是, 個別專案都經過不斷使用的驗證, 也持續被使用。例如: A 賣場, F 聯誼社, G 廣告商參與的 Hadoop, Cassandra, … 要集中資源或指定聚落開發類似的功能, 都難以負荷。但從滿足大眾市場, 回頭灌溉成的專案, 就能因此受惠。<br />
<br />
所以集眾開發必須加上, 個別經營大眾的觀點:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3KhOZf6FwkXfD7rnA_wWdD34bZmlq46BrUijO5MMH5u2ZrZSK6lX-FnigA2rsykeAD3NTVfbX-X8DhT0Y1HNV93607R5TzFRD1zvcflu5fXEkEXjP7ZZOZTgNGgdPfCe3D9rNLQ/s1600/3c_crowded_g.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="166" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3KhOZf6FwkXfD7rnA_wWdD34bZmlq46BrUijO5MMH5u2ZrZSK6lX-FnigA2rsykeAD3NTVfbX-X8DhT0Y1HNV93607R5TzFRD1zvcflu5fXEkEXjP7ZZOZTgNGgdPfCe3D9rNLQ/s200/3c_crowded_g.jpg" width="200" /></a></div>
<div style="text-align: center;">
<br /></div>
<br />
在以上前題成立的狀況, 個別開發也成為可能:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhV4TSijxRccuh2v9_gQtITWh9zvX6U26I30RI2Yk0GvDILJ1A5NcNECBgUpbtr6gnsqQJ38ynl7m5EWURGEzDpJ15fRVrXltEpbZyAeNNSTVjs58qZGuJU_fJ6SLbwzkw1iRQ04w/s1600/3c_crowded_s.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhV4TSijxRccuh2v9_gQtITWh9zvX6U26I30RI2Yk0GvDILJ1A5NcNECBgUpbtr6gnsqQJ38ynl7m5EWURGEzDpJ15fRVrXltEpbZyAeNNSTVjs58qZGuJU_fJ6SLbwzkw1iRQ04w/s200/3c_crowded_s.jpg" width="177" /></a></div>
<div style="text-align: center;">
<br /></div>
<br />
回頭看過去執行專案使用新技術, 會不斷被勸阻, 因為總是增加風險。但最後化險為夷, 是這些新技術總是進展到一個難以預估的地步, 不論是功能或穩定方面, 這些都不是古早開源專案可以想像的。唔, 大約十年前。最後的結果 … 除了組員肯定, 也被客戶讚許(多次廠商競賽, 都協助客戶拔得頭籌) :-)<br />
<br />
那些都是隨波逐流的好處, 卻也可能遇到 … 使用協力的專案被腰斬, 功能不如預期, 整合障礙, …。竊認為是技術問題, 調和正正負負的項次, 就不在這裡細細討論。<br />
<br />
最後記下一個開放問題: Scrum 方法用在何種開發情境(集中, 聚眾, 集眾)合宜?tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-50109220310483694902011-12-14T22:17:00.001+08:002011-12-14T22:17:14.777+08:00OFBiz Go<p>App 很紅, 主要在行動設備上, 上下游都很火紅。要談的 App 是現在不太紅的 Ent App (Enterprise Applications), 或是說已經紅過了, 但仍然是每個公司, 組織都會用到的。</p>
<p>App 多是產品, 而 Ent App 是種社會(<a href="http://lists.canonical.org/pipermail/kragen-tol/2005-April/000772.html" title=""Enterprise software" is a social, not technical, phenomenon">Social</a>), 俗名是江湖, 充滿交流與妥協, 大多以專案形式進行。就算從產品開始, 後面也會帶專案, 常見區分出軟體, 硬體, 開發, 維護, … 各個階段。 </p>
<p>由於 Ent App 牽涉層面通常既廣又深, 以技術角度來看, 擴散方式(銷售, 安裝)一直沒太大改變。現在雖然服務導向, 雲端喊得震天嘎響, 但除了網路基礎服務(信件,檔案), Web應用或特殊應用, 要把 Ent App 放上去, 應該還有些東西要準備好。用雲端的榜樣電與水比擬, 水除了自來水, 還有各式來源; 電除了公共設施, 也有可移動型的, 或私人備援。因此資料的移動能力要具備, 否則還是有些不足。</p>
<p>開放源碼讓技術普及, 加上硬體設備的大幅提升, 過去得詳加規劃, 才能執行的 Ent App, 現在只要在雲端或筆電開個 VM (虛擬機器) 就行開工。再者, 小公司不需要 24 小時運轉的系統, 功能有的話, 需要時再開啟。甚至中型單位, 只要合宜的環境及配套規劃, 也能朝這方面努力。</p>
<p>首先, 要面對的問題是 … 怎麼去開始?</p>
<p>在 <a href="http://ofbiz.apache.org" title="Apache OFBiz, The Apache Open For Business Project - Open Source E-Business / E-Commerce, ERP, CRM, POS, SCM, MRP, CMMS/EAM">OFBiz</a> <a href="http://ofbiz.apache.org/download.html">下載</a>頁面中, 寫明只要有 JDK(Java 1.6 SDK), 下載 zip 後解開壓縮檔, 執行指令就可以開始。</p>
<p>似乎還算容易?</p>
<p>但每個平台準備 JDK 其實都不太一樣, 更不用說如果發生衝突的話要怎麼辦, 例如在 Linux 上用 OpenJDK。這些說明字句雖少, 看起來簡單, 毫無疑問是寫給工程人員看的。再加上 Ent App 的社會屬性是有機成長, 如果要修改, 要調整, 按照慣例就得靠自學, 或找人助拳。</p>
<p>以整個過程來看, 愈到後面, 障礙愈高, 的確是不太容易推動。</p>
<p>之前在<a href="http://blog.tcchou.org/2011/04/blog-post.html">一種應用源碼管理的實作</a>討論過 <strong>可短小</strong>, <strong>可長久</strong>, <strong>可分享</strong> 的客製化方式。路雖然通了一小段, 但想想, 比原來 OFBiz 官方的安裝方式還要複雜, 素人要開始, 會有不小的障礙。</p>
<p>因此做了 <a href="https://bitbucket.org/tcc/ofbiz-go/src" title="tcc / ofbiz-go / source - Bitbucket">OFBiz Go</a> 用一個步驟完成 <em>所有</em> 繁瑣的準備工作。</p>
<p>準備工作有:</p>
<ol>
<li>下載必須的 <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" title="Java SE Downloads">JDK</a>, <a href="http://python.org/" title="Python Programming Language – Official Website">Python</a>, <a href="http://subversion.apache.org/" title="Apache Subversion">Subversion</a>, <a href="http://mercurial.selenic.com/" title="Mercurial SCM">Mercurial</a> 以及相關工具(<a href="http://savannah.gnu.org/projects/patch/" title="GNU patch">patch</a>, <a href="http://www.gnu.org/software/diffutils/diffutils.html" title="Diffutils - GNU Project - Free Software Foundation">diff</a>, <a href="http://curl.haxx.se/" title="cURL and libcurl">cURL</a>, 或 <a href="http://www.gnu.org/software/wget/" title="GNU Wget">Wget</a>), Windows 要再加 <a href="http://www.mingw.org/" title="MinGW | Minimalist GNU for Windows">MinGW</a>。</li>
<li>安裝妥上面這些東西, 做好設定 … 例如系統變數, <a href="http://mercurial.selenic.com/" title="Mercurial SCM">Mercurial</a> 的設定, 與 <a href="http://www.virtualenv.org/en/latest/index.html" title="virtualenv - virtualenv 1.7 documentation">virtualenv</a> 的環境。</li>
</ol>
<p>當然如果機器上已經有的軟體項目, 就略過不下載, 也不安裝。</p>
<p>寫上一篇的時候, 略過這些步驟。對熟悉這些工具的人, 早就備妥; 但不熟悉的人, 繁瑣且容易漏東漏西的過程, 反而造成困擾。即使自己做, 將這些裝到 Linux, 也碰上不少問題。</p>
<p>想做個 VM 來用, 但每次要把數 GB 的東西搬來搬去, 還得搬進雲裡頭, 舉重若輕恐怕也不太容易辦到。</p>
<p>在支援 Windows 前提下, 也考慮 <a href="http://puppetlabs.com/" title="Puppets Labs: The Leading IT Automation Software Solution">Puppet</a>, <a href="http://wiki.opscode.com/display/chef/Home" title="Home - Chef - Opscode Open Source Wiki">Chef</a>, 或老牌 <a href="http://cfengine.com/" title="Configuration Management for Agile System Administrators - CFEngine">CFEngine</a> 這類 <a href="http://zh.wikipedia.org/wiki/組態管理">組態管理</a> 工具。但即便輕如 <a href="http://cfengine.com/" title="Configuration Management for Agile System Administrators - CFEngine">CFEngine</a> 都必須做額外的安裝設定, 所以這工具還是留給 <a href="http://blog.tcchou.org/2011/02/blog-post.html">應用系統</a>, 做為其中的組件。</p>
<p>剩下可用的大概就是系統腳本語言(Shell Script)。</p>
<p><a href="https://bitbucket.org/tcc/ofbiz-go/src" title="tcc / ofbiz-go / source - Bitbucket">OFBiz Go</a> 是先在 OS X 上寫個 .sh 做完上述工作。然後找到 Windows 2008 用 Powershell 寫個 .ps1。最後用 VMWare 開啟 Ubuntu 11.10, 原本認為 OS X 小改就可以用, 但還是改了不少。 </p>
<p>比較特別是 Powershell 挺有 Power 的 … 要正確合法下載 JDK, 需使用者同意。Powershell 可控制 IE 瀏覽器帶出正確下載網頁, 當使用者點選同意後, 繼續腳本的工作。</p>
<p>目前在 OS X 10.6, Windows 2008R2 / 7, 還有 Ubuntu 11.10 測試過。OS X 可能會不太行, 因為環境不乾淨。;-)</p>
<p>只要腳本的下載, 安裝, 驗證的工作做完, 就可和 <a href="http://blog.tcchou.org/2011/04/blog-post.html">應用程式源碼溝通</a>。把繁瑣的過程, 劃分成兩個階段, 方便入門者, 也方便自己。</p>
<p>由於大部份工具和 <a href="http://python.org/" title="Python Programming Language – Official Website">Python</a> 相關(<a href="http://fabfile.org" title="Fabric - Fabric 1.3.3 documentation">Fabric</a>, <a href="http://mercurial.selenic.com/wiki/MqExtension" title="MqExtension - Mercurial">MQ</a>), 下週三(2011/12/21) 晚上 19:30 在新竹的 <a href="http://www.meetup.com/pythonhug/" title="Python Hsinchu User Group (Hsinchu) - Meetup">PyHUG</a> 會描述 <strong>配置方式</strong> 與 <strong>應用客製</strong> 兩階段的安排, 及運作細節。除了 Ent App, 很多類似的狀況, 也可用相同方式處理。歡迎參加, 和我們一起討論。</p>
tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-37595327223690099872011-10-31T10:12:00.001+08:002011-10-31T10:13:40.151+08:00數位中樞今年初(2011)在考慮資料問題, 腦中閃過一個字詞 "data hub", 而後 data 範圍擴大, 改為 digital。在網路搜尋 "digital hub", 赫然發現 10 年前已在某個場合上<a href="http://www.youtube.com/watch?v=9046oXrm7f8">提出</a>。<br />
<br />
賈伯斯先生當時提出 digital hub 是 Mac, 圍繞 hub 周圍的是音樂播放器, 手機, 數位相機/攝影機, 影音播放, PDA, ... 等等設備。<br />
<br />
<img alt="Digial Hub" border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGIHHbsARWTaZLAtCK9Icl3wqesqu2HMX-vBv6QGsqHIxY6qKw6c6QbUidMQl8Gt636WYcckcRpewpO0FDUTLguJWLWc7yyGY3_VDUO88HF7xYNJAtgj0Tr63furr5KlutVtomAg/?imgmax=800" style="display: block; margin-left: auto; margin-right: auto;" title="digialhub.png" width="400" /><br />
<br />
看了一會, 難免感嘆即使同個字詞, 在不同背景產生的意義與結果是完全不同。特別是 hub 旁邊的設備已被征戰過一輪, 圖片的戰略意義更能凸顯出來。<br />
<br />
上禮拜和某長輩聊到創業的話題, 提到 digital hub。再搜尋一次, 果然有人把該圖視為<a href="http://www.cultofmac.com/27810/the-dawn-of-apples-dominance-digital-hub-strategy-revisited">霸業的開端</a>, 而在今年中 digital hub 向雲端<a href="http://techcrunch.com/2011/06/06/icloud-digital-hub">轉進</a>。<br />
<br />
另外, 也看到我們的 B 社, 相隔 2 年, 在 2002 年末就追上驥尾, 推出<a href="http://ctimes.com.tw/news/ShowCols.asp?O=HJMBQAMM25BSA-0PN2">產品</a>, 其實算快了。但和韓國的 S 社比較, 就很堪玩味。<br />
<br />
最後心得是 ... 如果常留意業界資訊, 應該就不會去想 digital hub 這組字詞。tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-83110602760760233932011-10-02T00:20:00.002+08:002011-10-02T00:20:27.683+08:00泛 Markdown 編輯器<p><a href="http://markdown.tw/" title="Markdown 語法說明">Markdown</a> 專治滑鼠過動, 加持文件檔案撰寫。主要功效是運鍵如飛, 也能有好看好編的文件。</p>
<p>即便使用 <a href="http://markdown.tw/" title="Markdown 語法說明">Markdown</a> 只要能輸入文字的編輯器都行, 然後再加工處理。先前找相關軟體, 只有少數編輯器, 網誌特用編輯器, 還有就是深具實驗性但得常重開程式的佛心開源類。現在相關應用已遍地開花, 這幾天在更新一些軟體, 就發覺 <a href="http://markdown.tw/" title="Markdown 語法說明">Markdown</a> 被普遍支援且種類繁多, 也因此補入一些工具 …</p>
<table>
<colgroup>
<col style="text-align:center;"/>
<col style="text-align:center;"/>
<col style="text-align:center;"/>
<col style="text-align:center;"/>
<col style="text-align:center;"/>
<col style="text-align:center;"/>
<col style="text-align:center;"/>
<col style="text-align:center;"/>
<col style="text-align:center;"/>
</colgroup>
<thead>
<tr>
<th style="text-align:center;"></th>
<th style="text-align:center;"><a href="http://www.barebones.com/products/bbedit/" title="Bare Bones Software | BBEdit 10">BBEdit</a></th>
<th style="text-align:center;"><a href="http://macromates.com/" title="TextMate - The Missing Editor for Mac OS X">TextMate</a></th>
<th style="text-align:center;"><a href="http://macrabbit.com/espresso/" title="MacRabbit - Espresso - The Web Editor">Espresso</a></th>
<th style="text-align:center;"><a href="http://www.red-sweater.com/marsedit/" title="MarsEdit 3 - Desktop blog editing for the Mac">MarsEdit</a></th>
<th style="text-align:center;"><a href="http://brettterpstra.com/project/nvalt/" title="nvALT 2.1 - Notational Velocity Fork">nvALT</a></th>
<th style="text-align:center;"><a href="http://www.literatureandlatte.com/scrivener.php" title="Literature and Latte - Scrivener">Scrivener</a></th>
<th style="text-align:center;"><a href="http://bywordapp.com/" title="Byword - A Simple Text Editor for Mac">Byword</a></th>
<th style="text-align:center;"><a href="http://markedapp.com/" title="Marked: MultiMarkdown preview, everywhere">Marked</a></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center;">格式</td>
<td style="text-align:center;">MD</td>
<td style="text-align:center;">MD/MMD</td>
<td style="text-align:center;">MD</td>
<td style="text-align:center;">MD</td>
<td style="text-align:center;">MMD</td>
<td style="text-align:center;">MMD</td>
<td style="text-align:center;">MMD</td>
<td style="text-align:center;">MMD</td>
</tr>
<tr>
<td style="text-align:center;">預覽</td>
<td style="text-align:center;">即時</td>
<td style="text-align:center;">手動</td>
<td style="text-align:center;">手動</td>
<td style="text-align:center;">即時</td>
<td style="text-align:center;">即時</td>
<td style="text-align:center;">批次</td>
<td style="text-align:center;">手動</td>
<td style="text-align:center;">唯讀</td>
</tr>
<tr>
<td style="text-align:center;">用途</td>
<td style="text-align:center;" colspan="3">通用編輯器</td>
<td style="text-align:center;">網誌庫</td>
<td style="text-align:center;" colspan="2">文件庫</td>
<td style="text-align:center;">專寫<br/>(M)MD擋</td>
<td style="text-align:center;">專看<br/>(M)MD擋</td>
</tr>
<tr>
<td style="text-align:center;">特色</td>
<td style="text-align:center;">老牌</td>
<td style="text-align:center;">現代</td>
<td style="text-align:center;">網頁</td>
<td style="text-align:center;">網誌</td>
<td style="text-align:center;"><a href="http://simplenoteapp.com/" title="Simplenote. An easy way to keep notes, lists, ideas, and mor.">Simplenote</a><br/>同步</td>
<td style="text-align:center;">寫作</td>
<td style="text-align:center;">好看</td>
<td style="text-align:center;">方便</td>
</tr>
<tr>
<td style="text-align:center;">$</td>
<td style="text-align:center;">$$</td>
<td style="text-align:center;">$$</td>
<td style="text-align:center;">$$$</td>
<td style="text-align:center;">$$</td>
<td style="text-align:center;">0</td>
<td style="text-align:center;">$$</td>
<td style="text-align:center;">$</td>
<td style="text-align:center;">$</td>
</tr>
</tbody>
</table>
<ul>
<li>MD = <a href="http://markdown.tw/" title="Markdown 語法說明">Markdown</a></li>
<li>MMD = <a href="http://fletcherpenney.net/multimarkdown/" title="MultiMarkdown">MultiMarkdown</a></li>
</ul>
<p>這樣看下來, 剛開始入門的首選非 <a href="http://brettterpstra.com/project/nvalt/" title="nvALT 2.1 - Notational Velocity Fork">nvALT</a> 莫屬, 有看到不少都是 <a href="http://bywordapp.com/" title="Byword - A Simple Text Editor for Mac">Byword</a> + <a href="http://markedapp.com/" title="Marked: MultiMarkdown preview, everywhere">Marked</a> 組合搭配使用。個人是習慣所有文件與工作日誌都放在 <a href="http://www.literatureandlatte.com/scrivener.php" title="Literature and Latte - Scrivener">Scrivener</a>, 因為分門別類/關聯/搜尋/輸出都便利。檔案編寫原本用 <a href="http://www.barebones.com/products/bbedit/" title="Bare Bones Software | BBEdit 10">BBEdit</a>, 正試用 <a href="http://bywordapp.com/" title="Byword - A Simple Text Editor for Mac">Byword</a> + <a href="http://markedapp.com/" title="Marked: MultiMarkdown preview, everywhere">Marked</a>。另外 <a href="http://brettterpstra.com/project/nvalt/" title="nvALT 2.1 - Notational Velocity Fork">nvALT</a> 和 <a href="http://simplenoteapp.com/" title="Simplenote. An easy way to keep notes, lists, ideas, and mor.">Simplenote</a> 同步的特性, 方便文件跨平台與透過瀏覽器分享, 也置入工作流程中 …</p>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-59490513616818122582011-04-28T19:18:00.024+08:002011-04-29T07:06:10.353+08:00一種應用源碼管理的實作這是之前 <a class="link" href="http://blog.tcchou.org/2010/11/blog-post.html" shape="rect" target="_top">應用系統的版本管理</a> 一文的實作, 目的是開源應用系統的版本管理。嘗試解決應用系統的客製化部份, 除了快速跟隨主要版本的提升, 同時也方便系統的繁殖 ... 預防<a class="link" href="http://www.ec2disabled.com/" shape="rect" target="_top">天災</a>(?)<br />
<br />
這裡以 OFBiz r1096871 為例, 檔案有 {java:1436, xml:2626, groovy:454, properties:103, js:451, css:101, jar:391}, 它一直保持在更新的 <a class="link" href="https://cwiki.apache.org/confluence/x/xAhkAQ" shape="rect" target="_top">狀態</a>。<br />
<br />
面對必要的客製化, 過去常用上游分支 (vender branch) 手法處理, 以固定目錄版本管理為主, 實務上要面對許多細節。現在流行的分散式版本管理, 加上 rebase 大大改善舊有的方式。但分支有版本相依的特性, 而 OFBiz 的版本存檔 (snapshot) 就有 215mb 之譜 ... 要保存和轉移都負擔。<br />
<br />
利用補丁管理(<a class="link" href="https://git.wiki.kernel.org/index.php/PatchManagement" shape="rect" target="_top">Patch Management</a>)是不錯的主意, Mercurial 的 <a class="link" href="http://hgbook.red-bean.com/read/managing-change-with-mercurial-queues.html" shape="rect" target="_top">MQ</a> 到 1.8 已經相當成熟。唯一問題是 OFBiz 使用 Apache 官方版本管理 Subversion, 由於版本存檔太大導致 hg-svn 掛點, 不得不生出對策。<br />
<br />
因此, 題目變成上游是 svn (原本用 git, 簡化問題還是用 svn 示範), 實際處理用 hg 加 mq。<br />
<br />
以自己流通的 mq 版本存檔為例, 大小約 100kb 左右(zip), svn 與對應 hg 則依需要而建。在 hg 功能的協助下, 能快速跟隨 trunk 版本更新, 而 mq 存檔小也利於保存和繁殖。(OFBiz 的 mq 範例放在 <a class="link" href="https://bitbucket.org/tcc/ofbiz-mq/src" shape="rect" target="_top">bitbucket</a> )<br />
<br />
但是實際運作起來, 操作有些瑣碎, 對象也繁多 ... 還好有 <a class="link" href="http://fabfile.org/" shape="rect" target="_top">Fabric</a> 加持簡化成三種操作, 得以省略一堆指令。<br />
<h2><span class="Apple-style-span" style="color: #3d85c6;">三種操作</span></h2><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">初始 (init)<br />
拿到 mq 存檔, 加上 OFBiz Apache 上的 zip 檔 (附帶 .svn)。先把 OFBiz zip 檔解開有了 svn 儲存庫 (repository), 再更新與 mq 相同的 svn rev. 版本, 接著複製到 hg 儲存庫。<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3roZw1peutnYNAx2Fo4PdZnAg1NpniPsFmACxT6Dpe82O0TVwwYb7zb3b-6m2RsE7cgn0Ch774h_F3YRs26cPhfFp7ZuLGjJC4AXxeLsu4EBH4ihqcz5EgX9PY2hsFs1FHq_Dcg/s1600/p4vc_fab_init.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3roZw1peutnYNAx2Fo4PdZnAg1NpniPsFmACxT6Dpe82O0TVwwYb7zb3b-6m2RsE7cgn0Ch774h_F3YRs26cPhfFp7ZuLGjJC4AXxeLsu4EBH4ihqcz5EgX9PY2hsFs1FHq_Dcg/s320/p4vc_fab_init.png" width="320" /></a></div><br />
</li>
<li class="listitem">更新 (update)<br />
因應上游 trunk 更新, 把 svn 儲存庫與上游同步, 再更新 hg 儲存庫, 最後把 mq 做 rebase 處理。需要留意 OFBiz 會更新 *jar, 是不在 svn diff 服務範圍, 得由外部 diff 助拳。而後, 視情況對 mq 進行提交 (mqcommit), 或上送(mqpush)。<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZyMviZNAtEHK7_xi95Xc3qJID3YFC3HpTRyIqKNjujZwigTQUP6gD2AVJLtCXFW6m9zY-4ra_HP34ThzACOw4tJm7XQC4b6pIAKZ15FIXpn59xf-1NZyXj8JvqZnXgUYlBHH99g/s1600/p4vc_fab_update.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZyMviZNAtEHK7_xi95Xc3qJID3YFC3HpTRyIqKNjujZwigTQUP6gD2AVJLtCXFW6m9zY-4ra_HP34ThzACOw4tJm7XQC4b6pIAKZ15FIXpn59xf-1NZyXj8JvqZnXgUYlBHH99g/s320/p4vc_fab_update.png" width="320" /></a></div><br />
</li>
<li class="listitem">mq變更 (mqpull)<br />
上游版本變更與驗證已完成, 並上送 bitbucket (第二個操作)。這時要對運作端進行更新, 先把新的 mq 取下, 依據新 mq 更新 svn 儲存庫, 同時更新對應 hg 儲存庫。<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnmSo7ZezIxBYYH-D0Ev0_-oYQZTDl4uWlxYd5dZe2Lg9uinE6e_rvvl440SX6kOHOeONTyV9PVcod_w3lc_cls68EbxNMVaoRq_W5iOchYDyjpb_QCR2JPPqHb14bqoDhkXrjnw/s1600/p4vc_fab_mqpull.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="261" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnmSo7ZezIxBYYH-D0Ev0_-oYQZTDl4uWlxYd5dZe2Lg9uinE6e_rvvl440SX6kOHOeONTyV9PVcod_w3lc_cls68EbxNMVaoRq_W5iOchYDyjpb_QCR2JPPqHb14bqoDhkXrjnw/s320/p4vc_fab_mqpull.png" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><br />
</li>
</ol></div>一般使用只要用 <span class="bold"><strong>初始</strong></span> 和 <span class="bold"><strong>mq變更 </strong></span>就能保持版本換新, 僅在開發與測試需要 <span class="bold"><strong>更新</strong></span>(mq commit/push) 的機制。<br />
<br />
常見方式是: 只有開發與測試使用版本管理工具, 運作端用 rsync 之類工具同步, 符合標準 <span class="bold"><strong>開發</strong></span>,<br />
<span class="bold"><strong>測試</strong></span>, <span class="bold"><strong>正式環境 </strong></span>分階段的開發週期。<br />
<br />
用 svn-hg-mq 的好處是可從容面對應用系統會遇到的因地制宜 ... 如果不時在 <span class="bold"><strong>正式環境 </strong></span>被要求改一點顯示文字或邏輯, 用此法就放手去改。然後以 mq commit 保存差異並列管, 之後再看看要怎麼處理, 同時也可放心進行上游版本更新(如果有的話)。<br />
<br />
假使開發語言單一, 系統規模在一定範圍之內, 人力還是可以處理。而像 OFBiz 有 java, xml, groovy, ... 子系統多, 關連又盤根錯節, 就最好有固定的方式處理。<br />
<br />
<h2><span class="Apple-style-span" style="color: #3d85c6;">實際操作</span></h2>在 OS X 10.6 + macports 與 Ubuntu 10.10 測試過。<br />
<br />
要有 gcc, python, virtualenv, apple/sun jdk 6 (openjdk 6 還是無法使用 OFBiz)。因為 mercurial 1.8 和 fabric 1.0.1 都要用新版, 習慣用 virtualenv 來建, 這時得有 gcc 相關工具備著。<br />
<span class="bold"><strong><br />
</strong></span><br />
<span class="bold"><strong><span class="Apple-style-span" style="color: #3d85c6;">環境建立:</span></strong></span><br />
<pre class="programlisting" xml:space="preserve">@ /w/proj
$ virutalenv --no-site-packages fab
$ cd fab
$ source bin/activate
(fab) $ pip install mercurial
...
(fab) $ pip install fabric
...
(fab) $ curl -O https://bitbucket.org/tcc/ofbiz-util/raw/38e378fef189/fabfile.py</pre><span class="bold"><strong><br />
</strong></span><br />
<span class="bold"><strong><span class="Apple-style-span" style="color: #3d85c6;">準備 ~/.hgrc:</span></strong></span><br />
<pre class="programlisting" xml:space="preserve">[ui]
username = jia@side.org
[extensions]
pager =
hgext.mq =
[pager]
pager = LESS='FSRX' less</pre><br />
注意 username, pager, mq 都要有 ... fabfile.py 會用到。<br />
<span class="bold"><strong><br />
</strong></span><br />
<span class="bold"><strong><span class="Apple-style-span" style="color: #3d85c6;">執行:</span></strong></span><br />
假設主要目錄是 /w/proj/fab/ofbiz, 會在下面自動建立 svn/, hg/, zip/ 三個目錄 ...<br />
<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">svn/ 目錄為 svn 儲存庫, 和遠端 svn 同步。</li>
<li class="listitem">hg/ 目錄為 hg 儲存庫, 用來執行應用系統。和本地 svn/ 同步, 並且以 hg-mq 進行客製化處理。</li>
<li class="listitem">zip/ 目錄存放 ofbiz-trunk-current.zip 檔案, 只在 "初始" 步驟有用, 之後可刪除。</li>
</ol></div><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">進行<span class="bold"><strong>初始</strong></span>儲存庫:<br />
<pre class="programlisting" xml:space="preserve">@ /w/proj/fab
$ source bin/activate
(fab) $ fab init:/w/proj/fab/ofbiz
...</pre>就會進行, 由於部份操作挺費時間, 或須備妥網路, 像下載 ofbiz-trunk-current.zip 會停下來詢問, 若要執行到底:<br />
<pre class="programlisting" xml:space="preserve">(fab) $ fab init:/w/proj/fab/ofbiz,auto=Y
...</pre>加上參數 auto=Y 即可。</li>
<li class="listitem">當 mq@bitbucket 有新版本要<span class="bold"><strong>更新</strong></span>:<br />
<pre class="programlisting" xml:space="preserve">(fab) $ fab mqpull:/w/proj/fab/ofbiz,sync=Y
...</pre>若沒有 sync=Y 就得手動進行 sync:<br />
<pre class="programlisting" xml:space="preserve">(fab) $ fab sync:/w/proj/fab/ofbiz
...</pre></li>
</ul></div>目前 mq@bitbucket 沒有開放更新, 得自行建立 mq repository ... 修改 fabfile.py:<br />
<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">註解第 31 列 hg_mq_url = 'https://bitbucket.org/tcc/ofbiz-mq'。</li>
<li class="listitem">打開第 32 列 hg_mq_url = 'file:///w/proj/ofbiz/mq2' 做必要修改。</li>
</ol></div>然後<span class="bold"><strong>與 trunk@OFBiz 同步</strong></span>:<br />
<pre class="programlisting" xml:space="preserve">(fab) $ fab update:/w/proj/fab/ofbiz
...</pre>接著提交寫入, 並上送:<br />
<pre class="programlisting" xml:space="preserve">(fab) $ fab mqcommit:/w/proj/fab/ofbiz,push=Y
...</pre>若沒下 push=Y, 要手動進行上送:<br />
<pre class="programlisting" xml:space="preserve">(fab) $ fab mqpush:/w/proj/fab/ofbiz
...</pre><br />
全部操作就這樣了。<br />
<br />
建置 OFBiz 前先置入 hg-mq:<br />
<pre class="programlisting" xml:space="preserve">@/w/proj/fab/ofbiz/hg
(fab) $ hg qpush -a
...</pre><br />
然後按 <a class="link" href="http://blog.tcchou.org/2010/11/ofbiz.html" shape="rect" target="_top">OFBiz 安裝</a>進行:<br />
<pre class="programlisting" xml:space="preserve">(fab) $ ./ant clean-all
...
(fab) $ ./ant run-install-extseed
...
(fab) $ ./ant create-admin-user-login
...
(fab) $ ./startofbiz.sh
...</pre><br />
如果要建立另一份系統做開發, 把目錄 /w/proj/fab/ofbiz/ 改為其他的, 例如 /w/proj/yi/side/ ... 依據客製 hg-mq 很快就能建立一套新的應用系統。不用辛辛苦苦裝完系統, 再逐一做客製相關設定。<br />
<br />
試試看, 或許有更好的做法 :)tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-38131825323784946342011-04-20T13:30:00.002+08:002011-04-20T13:41:55.288+08:00oXygen XML 中文 PDF 輸出<p>一直用 oXygen 編輯器來處理 XML 相關檔案, 後來發覺寫文件的功能日益強大, 但輸出 PDF 有些障礙。也不是太大問題, 需要一些設定, 這裡的說明將包含 FO, Docbook, DITA。此外, 索引方面以 DITA 輸出為例, 示範更換 FO 處理器為 XEP 個人版。</p><p>以下環境是 OS X 10.6 加上 oXygen XML Editor 12.1。 請留意檔案位置, Windows 下注意 TTF 檔的差異。</p><p>另外, FO, Docbook, DITA 都有自由軟體套件, 協助編寫文件, 沒有 oXygen 編輯器也能運作。</p><h2 class="title">FO 設定</h2><ol class="orderedlist" type="1"><li class="listitem"><p>產生字型規格檔, 參考: <a href="http://xmlgraphics.apache.org/fop/0.95/fonts.html">http://xmlgraphics.apache.org/fop/0.95/fonts.html</a></p><p>假定把 FOP 1.0 安裝在 /w/j/x/fop-1.0 目錄。執行下列指令, 產生字型規格檔:</p><pre class="programlisting">$ export CL=/w/j/x/fop-1.0/build/fop.jar:/w/j/x/fop-1.0/lib/avalon-\
framework.jar:/w/j/x/fop-1.0/lib/commons-logging.jar:/w/j/x/fop-\
1.0/lib/commons-io.jar
$ java -cp $CL org.apache.fop.fonts.apps.TTFReader \
/Library/Fonts/Arial\ Unicode.ttf ArialUnicode.xml</pre><p>產生 ArialUnicode.xml, 放在 <span class="underline">/w/proj/xml/fo/ArialUnicode.xml</span>。</p></li>
<li class="listitem"><p>建立 FOP 設定檔 userconfig.xml, 放在 /w/proj/xml/fo/userconfig.xml</p><pre class="programlisting"><strong class="hl-tag" style="color: #000096"><fop</strong> <span class="hl-attribute" style="color: #F5844C">version</span>=<span class="hl-value" style="color: #993300">"1.0"</span><strong class="hl-tag" style="color: #000096">></strong>
<strong class="hl-tag" style="color: #000096"><base></strong>.<strong class="hl-tag" style="color: #000096"></base></strong>
<strong class="hl-tag" style="color: #000096"><renderers></strong>
<strong class="hl-tag" style="color: #000096"><renderer</strong> <span class="hl-attribute" style="color: #F5844C">mime</span>=<span class="hl-value" style="color: #993300">"application/pdf"</span><strong class="hl-tag" style="color: #000096">></strong>
<strong class="hl-tag" style="color: #000096"><filterList></strong>
<strong class="hl-tag" style="color: #000096"><value></strong>flate<strong class="hl-tag" style="color: #000096"></value></strong>
<strong class="hl-tag" style="color: #000096"></filterList></strong>
<strong class="hl-tag" style="color: #000096"><fonts></strong>
<strong class="hl-tag" style="color: #000096"><font</strong> <span class="hl-attribute" style="color: #F5844C">metrics-url</span>=<span class="hl-value" style="color: #993300">"file://</span><span class="underline">/w/proj/xml/fo/ArialUnicode.xml</span>"
embed-url="file:///Library/Fonts/Arial Unicode.ttf"
kerning="yes">
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"ArialUnicodeMS"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"normal"</span>
<span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"normal"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"ArialUnicodeMS"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"normal"</span>
<span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"bold"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"ArialUnicodeMS"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"italic"</span>
<span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"normal"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"ArialUnicodeMS"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"italic"</span>
<span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"bold"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"any"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"normal"</span> <span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"normal"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"any"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"normal"</span> <span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"bold"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"></font></strong>
<strong class="hl-tag" style="color: #000096"></fonts></strong>
<strong class="hl-tag" style="color: #000096"></renderer></strong>
<strong class="hl-tag" style="color: #000096"></renderers></strong>
<strong class="hl-tag" style="color: #000096"></fop></strong></pre><p>其中字型名稱 name="<span class="underline">ArialUnicodeMS</span>" 從 <span class="underline">/w/proj/xml/fo/ArialUnicode.xml</span> 裡頭的名稱參考而來。</p></li>
<li class="listitem"><p>修改 oXygen 設定 Preferences ➠ XML ➠ XSLT-FO-XQuery ➠ XQuery ➠ FO Processors</p><p>找到 Configure file 項目改為 <span class="underline">/w/proj/xml/fo/userconfig.xml</span>。</p></li>
</ol><h2 class="title">中文 FO 測試</h2><ol class="orderedlist" type="1"><li class="listitem"><p>編修原 oxygen/samples/fo/Miscellances/helloWorld.fo 改為 helloWorld-u8.fo:</p><pre class="programlisting"><span class="hl-directive" style="color: maroon"><?xml version="1.0" encoding="</span><span class="underline">utf-8</span>"?>
<em class="hl-comment" style="color: silver"><!-- Example from: http://www.renderx.net
Copyright © 2004 RenderX, Inc.--></em>
<strong class="hl-tag" style="color: #000096"><fo:root</strong> <span class="hl-attribute" style="color: #F5844C">xmlns:xsi</span>=<span class="hl-value" style="color: #993300">"http://www.w3.org/2001/XMLSchema-instance"</span>
<span class="hl-attribute" style="color: #F5844C">xmlns:fo</span>=<span class="hl-value" style="color: #993300">"http://www.w3.org/1999/XSL/Format"</span><strong class="hl-tag" style="color: #000096">></strong>
<strong class="hl-tag" style="color: #000096"><fo:layout-master-set></strong>
<strong class="hl-tag" style="color: #000096"><fo:simple-page-master</strong> <span class="hl-attribute" style="color: #F5844C">master-name</span>=<span class="hl-value" style="color: #993300">"my-page"</span><strong class="hl-tag" style="color: #000096">></strong>
<strong class="hl-tag" style="color: #000096"><fo:region-body</strong> <span class="hl-attribute" style="color: #F5844C">margin</span>=<span class="hl-value" style="color: #993300">"1in"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"></fo:simple-page-master></strong>
<strong class="hl-tag" style="color: #000096"></fo:layout-master-set></strong>
<strong class="hl-tag" style="color: #000096"><fo:page-sequence</strong> <span class="hl-attribute" style="color: #F5844C">master-reference</span>=<span class="hl-value" style="color: #993300">"my-page"</span><strong class="hl-tag" style="color: #000096">></strong>
<strong class="hl-tag" style="color: #000096"><fo:flow</strong> <span class="hl-attribute" style="color: #F5844C">flow-name</span>=<span class="hl-value" style="color: #993300">"xsl-region-body"</span><span class="underline"> font-family="ArialUnicodeMS"</span>>
<strong class="hl-tag" style="color: #000096"><fo:block></strong>Hello, world!<span class="underline"> 大家好!</span><strong class="hl-tag" style="color: #000096"></fo:block></strong>
<strong class="hl-tag" style="color: #000096"></fo:flow></strong>
<strong class="hl-tag" style="color: #000096"></fo:page-sequence></strong>
<strong class="hl-tag" style="color: #000096"></fo:root></strong></pre></li>
<li class="listitem"><p>產生 PDF: 選單 Document ➠ Transformation ➠ Apply Transformation Senario 產生。</p><p>或按 cmd + shift + T, 選擇 PDF (第一次要選 FO PDF)。</p></li>
</ol><h2 class="title">Docbook 設定</h2><p>做妥上面 FO 設定。修改 oxygen/frameworks/docbook/xsl/fo/docbook_custom.xsl 在 </xsl:stylesheet> 前, <!-- end oXygen patch. --> 之後, 加上:</p><pre class="programlisting"><em class="hl-comment" style="color: silver"><!-- Traditional Chinese patch --></em>
<strong class="hl-tag" style="color: #000096"><xsl:param</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"body.font.family"</span><strong class="hl-tag" style="color: #000096">></strong>ArialUnicodeMS<strong class="hl-tag" style="color: #000096"></xsl:param></strong>
<strong class="hl-tag" style="color: #000096"><xsl:param</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"body.font.size"</span><strong class="hl-tag" style="color: #000096">></strong>12<strong class="hl-tag" style="color: #000096"></xsl:param></strong>
<strong class="hl-tag" style="color: #000096"><xsl:param</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"monospace.font.family"</span><strong class="hl-tag" style="color: #000096">></strong>ArialUnicodeMS<strong class="hl-tag" style="color: #000096"></xsl:param></strong>
<strong class="hl-tag" style="color: #000096"><xsl:param</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"title.font.family"</span><strong class="hl-tag" style="color: #000096">></strong>ArialUnicodeMS<strong class="hl-tag" style="color: #000096"></xsl:param></strong>
<em class="hl-comment" style="color: silver"><!-- end Traditional Chinese patch --></em></pre><h2 class="title">中文 Docbook 測試</h2><ol class="orderedlist" type="1"><li class="listitem"><p>修改 oxygen/samples/docbook/v5/sample.xml。Author 模式下, 在文字後加入中文, 例如:</p><pre class="programlisting"><strong class="hl-tag" style="color: #000096"><sect1></strong>
<strong class="hl-tag" style="color: #000096"><title></strong>Inline Markup and Images<span class="underline"> 大家好</span><strong class="hl-tag" style="color: #000096"></title></strong></pre></li>
<li class="listitem"><p>產生 PDF, 同 FO 方式 ... cmd + shift + T 選擇 PDF (第一次要選 Docbook PDF)。</p></li>
</ol><h2 class="title">DITA 設定</h2><ol class="orderedlist" type="1"><li class="listitem"><p>修改 oxygen/frameworks/dita/DITA-OT/demo/fo/cfg/fo/font-mappings.xml</p><p>找到以下字樣:</p><pre class="programlisting"><strong class="hl-tag" style="color: #000096"><physical-font</strong> <span class="hl-attribute" style="color: #F5844C">char-set</span>=<span class="hl-value" style="color: #993300">"Simplified Chinese"</span><strong class="hl-tag" style="color: #000096">></strong>
<strong class="hl-tag" style="color: #000096"><font-face></strong>AdobeSongStd-Light<strong class="hl-tag" style="color: #000096"></font-face></strong>
<strong class="hl-tag" style="color: #000096"></physical-font></strong></pre><p>增加類似段落(共三處):</p><pre class="programlisting"><strong class="hl-tag" style="color: #000096"><physical-font</strong> <span class="hl-attribute" style="color: #F5844C">char-set</span>=<span class="hl-value" style="color: #993300">"Traditional Chinese"</span><strong class="hl-tag" style="color: #000096">></strong>
<strong class="hl-tag" style="color: #000096"><font-face></strong>ArialUnicodeMS<strong class="hl-tag" style="color: #000096"></font-face></strong>
<strong class="hl-tag" style="color: #000096"></physical-font></strong></pre></li>
<li class="listitem"><p>複製 oxygen/frameworks/dita/DITA-OT/demo/fo/cfg/fo/i18n/zh_CN.xml 成為同目下新檔 zh_TW.xml</p><p>修改此 zh_TW.xml 內容, 把 <alphabet char-set="Simplified Chinese">...</alphabeat> 改為:</p><pre class="programlisting"><strong class="hl-tag" style="color: #000096"><alphabet</strong> <span class="hl-attribute" style="color: #F5844C">char-set</span>=<span class="hl-value" style="color: #993300">"Traditional Chinese"</span><strong class="hl-tag" style="color: #000096">></strong>
<strong class="hl-tag" style="color: #000096"><character-set></strong>
<strong class="hl-tag" style="color: #000096"><character-range></strong>
<strong class="hl-tag" style="color: #000096"><start</strong> <span class="hl-attribute" style="color: #F5844C">include</span>=<span class="hl-value" style="color: #993300">"yes"</span><strong class="hl-tag" style="color: #000096">></strong>&#x0100;<strong class="hl-tag" style="color: #000096"></start></strong>
<strong class="hl-tag" style="color: #000096"><end</strong> <span class="hl-attribute" style="color: #F5844C">include</span>=<span class="hl-value" style="color: #993300">"yes"</span><strong class="hl-tag" style="color: #000096">></strong>&#xff00;<strong class="hl-tag" style="color: #000096"></end></strong>
<strong class="hl-tag" style="color: #000096"></character-range></strong>
<strong class="hl-tag" style="color: #000096"></character-set></strong>
<strong class="hl-tag" style="color: #000096"></alphabet></strong></pre><p>很偷懶的方式, 需要修正。</p></li>
<li class="listitem"><p>修改 oxygen/frameworks/dita/DITA-OT/demo/fo/fop/conf/fop.xconf</p><p>在 fop ☞ renderers ☞ renderer mime="application/pdf" ☞ fonts 下增加:</p><pre class="programlisting"><strong class="hl-tag" style="color: #000096"><font</strong> <span class="hl-attribute" style="color: #F5844C">metrics-url</span>=<span class="hl-value" style="color: #993300">"file://</span><span class="underline">/w/proj/xml/fo/ArialUnicode.xml</span>"
embed-url="file:///Library/Fonts/Arial Unicode.ttf" kerning="yes">
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"ArialUnicodeMS"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"normal"</span> <span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"normal"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"ArialUnicodeMS"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"normal"</span> <span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"bold"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"ArialUnicodeMS"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"italic"</span> <span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"normal"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"ArialUnicodeMS"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"italic"</span> <span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"bold"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"any"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"normal"</span> <span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"normal"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"><font-triplet</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"any"</span> <span class="hl-attribute" style="color: #F5844C">style</span>=<span class="hl-value" style="color: #993300">"normal"</span> <span class="hl-attribute" style="color: #F5844C">weight</span>=<span class="hl-value" style="color: #993300">"bold"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"></font></strong></pre></li>
<li class="listitem"><p>建立 zh_TW 必要檔案, 在 oxygen/frameworks/dita/DITA-OT/demo/fo/cfg/common/ 下要有三個檔案:</p><ul class="itemizedlist" type="disc"><li class="listitem"><p>index/zh_TW.xml</p><p>複製 zh_CN.xml 修改, 先將 <language>zh-TW</language> 改為正確對應。下半部所有中文的 index.group 改為只有(也是需要修正):</p><pre class="programlisting"><strong class="hl-tag" style="color: #000096"><index.group></strong>
<strong class="hl-tag" style="color: #000096"><group.key></strong>中文<strong class="hl-tag" style="color: #000096"></group.key></strong>
<strong class="hl-tag" style="color: #000096"><group.label></strong>中文<strong class="hl-tag" style="color: #000096"></group.label></strong>
<strong class="hl-tag" style="color: #000096"><group.members></strong>
<strong class="hl-tag" style="color: #000096"><char.set</strong> <span class="hl-attribute" style="color: #F5844C">start-range</span>=<span class="hl-value" style="color: #993300">"一"</span> <span class="hl-attribute" style="color: #F5844C">end-range</span>=<span class="hl-value" style="color: #993300">"龤"</span><strong class="hl-tag" style="color: #000096">/></strong>
<strong class="hl-tag" style="color: #000096"></group.members></strong>
<strong class="hl-tag" style="color: #000096"></index.group></strong></pre></li>
<li class="listitem"><p>properties/zh_TW.properties</p><pre class="programlisting">chm.native.encoding=big5
chm.project.language=0x404 Traditional Chinese</pre></li>
<li class="listitem"><p>vars/zh_TW.xml</p><p>複製修改, 可能必要的是 "Product Name"(顯示在 PDF 上方頁角), 其他隨意。</p></li>
</ul></li>
<li class="listitem"><p>修改 oxygen/frameworks/dita/DITA-OT/demo/fo/build.xml 增加:</p><pre class="programlisting"><strong class="hl-tag" style="color: #000096"><property</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"document.locale"</span> <span class="hl-attribute" style="color: #F5844C">value</span>=<span class="hl-value" style="color: #993300">"zh_TW"</span><strong class="hl-tag" style="color: #000096">/></strong></pre><p>在 <property name="customization.dir ...> 上即可。</p></li>
</ol><h2 class="title">中文 DITA 測試</h2><ol class="orderedlist" type="1"><li class="listitem"><p>開 oxygen/dita/ 下某 DITA 專案, 開專案下的檔案在 Author 模式下修改, 增加中文字, 例如:</p><pre class="programlisting"><strong class="hl-tag" style="color: #000096"><title></strong>Changing the oil in your car 測試看看<strong class="hl-tag" style="color: #000096"></title></strong></pre></li>
<li class="listitem"><p>產生 PDF, 同 FO/Docbook 方式 ... cmd + shift + T 選擇 PDF (第一次要選 DITA Map PDF)。</p></li>
</ol><h2 class="title">安裝 XEP 個人版</h2><p>FOP 1.0 還不支援索引(indexing)功能, 請參考 <a href="http://xmlgraphics.apache.org/fop/compliance.html#fo-object-indexing-section">http://xmlgraphics.apache.org/fop/compliance.html#fo-object-indexing-section</a>。</p><p>XEP 個人版非商業用可取代 FOP 產生索引 <a href="http://www.renderx.com/download/personal.html">http://www.renderx.com/download/personal.html</a>。</p><ol class="orderedlist" type="1"><li class="listitem"><p>下載, 安裝到 /w/j/x/XEP/。</p></li>
<li class="listitem"><p>修改 /w/j/x/XEP/xep.xml 增加 (搜尋到 font-group):</p><pre class="programlisting"><strong class="hl-tag" style="color: #000096"><font-group</strong> <span class="hl-attribute" style="color: #F5844C">xml:base</span>=<span class="hl-value" style="color: #993300">"file:/Users/tcchou/Library/Fonts/"</span>
<span class="hl-attribute" style="color: #F5844C">label</span>=<span class="hl-value" style="color: #993300">"Windows TrueType"</span> <span class="hl-attribute" style="color: #F5844C">embed</span>=<span class="hl-value" style="color: #993300">"true"</span> <span class="hl-attribute" style="color: #F5844C">subset</span>=<span class="hl-value" style="color: #993300">"true"</span><strong class="hl-tag" style="color: #000096">></strong>
<strong class="hl-tag" style="color: #000096"><font-family</strong> <span class="hl-attribute" style="color: #F5844C">name</span>=<span class="hl-value" style="color: #993300">"ArialUnicodeMS"</span><strong class="hl-tag" style="color: #000096">></strong>
<strong class="hl-tag" style="color: #000096"><font></strong><strong class="hl-tag" style="color: #000096"><font-data</strong> <span class="hl-attribute" style="color: #F5844C">ttf</span>=<span class="hl-value" style="color: #993300">"Arial Unicode.ttf"</span><strong class="hl-tag" style="color: #000096">/></strong><strong class="hl-tag" style="color: #000096"></font></strong>
<strong class="hl-tag" style="color: #000096"></font-family></strong>
<strong class="hl-tag" style="color: #000096"></font-group></strong></pre><p>把 Arial Unicode.ttf 複製到個人字型目錄, 因為還有其他字型 ...</p></li>
<li class="listitem"><p>oxygen 增加 XEP</p><p>Preferences ➠ XML ➠ XSLT-FO-XQuery ➠ XQuery ➠ FO Processors</p><p>點選 "If you have a custom XEP installation ..." 旁的 Browse 按鈕, 選擇 /w/j/x/XEP/xep 。</p></li>
<li class="listitem"><p>點選 "Configure Transformation Scenario", Duplicate "DITA Map PDF" 選擇 Processor: XEP 。</p></li>
<li class="listitem"><p>選擇 DITA 下專案(it-book 有 indexing 範例), 產生 PDF ... cmd + shift + T 。</p></li>
</ol>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-79391924483452514672011-03-28T20:45:00.000+08:002011-03-28T20:45:13.460+08:00OSDC.TW Tabledown 演講資料與問答週日(27) 在 OSDC.TW Tabledown 演講的投影片:<br />
<br />
<div id="__ss_7401487" style="width: 425px;"><strong style="display: block; margin: 12px 0 4px;"><a href="http://www.slideshare.net/tcchou/tabledown-7401487" title="Tabledown">Tabledown</a></strong><object height="355" id="__sse7401487" width="425"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=2011-osdctw-tabledown-110326182728-phpapp02&stripped_title=tabledown-7401487&userName=tcchou" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse7401487" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=2011-osdctw-tabledown-110326182728-phpapp02&stripped_title=tabledown-7401487&userName=tcchou" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><br />
<div style="padding: 5px 0 12px;">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/tcchou">T.C. Chou</a>.</div></div><br />
利用一些時間把範例整理上傳到 <a href="http://code.google.com/p/tabledown/source/browse/osdctw2011/">Google code</a>。<br />
<br />
除了把 Tabledown 修完, 有個 pip 的 req. 檔案能協助把演講提到的 twill, scotch, mechanize, Beautiful Soup, Tabledown 都給裝妥。先將 python, pip 裝完, 接著再參考 00README.txt。<br />
<br />
範例要執行, 可能有困難的地方是將 OFBiz 裝起來。而 User 的 Id 預設為數值累加, 不太方便。附上一個修補使 Id 能和 UserName 相同 (試過今天的 trunk)。得事先裝好 Java 6, 接下來再花些時間建系統 ... 有問題的話也請提出 :-)<br />
<br />
另外, 把當天遇到的 Q & A 整理如下:<br />
<ol><li>在某頁從資料庫到試算表的做法為何?<br />
⇒ 投影片的試算表是以 "人" 的角度建立資料表達的方式, 都是手工建立的。僅示範從試算表到 Web App 單向, 主要是跨越資料關連,多個畫面,細節這些煩瑣與難度。從資料庫到試算表要自動達成更接近人需要的, 應該是另一個題目。</li>
<li>如何執行?<br />
⇒ 目前範例都是寫死的, 在命令列下執行 XD 日後考慮有無更彈性的做法, 像提供 plugin, 只要準備好試算表加上 plugin 就能處理妥。</li>
<li>接受的試算表格式? 雲端?<br />
⇒ 目前沒有能力處理雲端試算表, 只有 python-excel 專案能接受的 .xls 檔案。</li>
<li>能否即時執行, 和後端同步?<br />
⇒ 範例中時間表(Timesheet)有想過直接與 Web App 同步, 有點這種味道? 但要考量資料同步問題 … 沒直覺的解法, 暫時擱著。([事後] 先解 Q1 問題, 再為 collections 做 diff, 或許類似 git snapshot 做法)</li>
<li>問題加密 (POS?) … 和 Td 無關, 所以加密 XD<br />
⇒ 回覆加密 (POS!)</li>
<li>範例中 Master 與 Detail 關連?<br />
⇒ 簡單版: 沒有關連; 真相版: Master 是鍵值式資料, Detail 是條列式資料 … 原則上都可以多個。而資料的關連由開發者(程式)決定, 例如在專案 Master 有人員 ID 以逗號隔開, 實際上在專案資源畫面有多筆資料。</li>
</ol>後來看了 <a href="http://sleepnova.blogspot.com/">sleepnova</a> 推薦的 Prezi, 另外想到試算表與 XML, Json, Yaml, … 相比, 雖然個個都能記錄資料, 但使用者愛用的原因, 該是較能掌握東西放在哪裡, 即使只有列和行。<br />
<br />
感謝四方大德惠予討論, 也謝謝 <a href="http://hcchien.org/">hcchien</a> 與 OSDC.TW 工作人員的辛勞 :-)tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-52552999975511617672011-02-18T19:18:00.037+08:002011-02-18T19:18:00.690+08:00開放源碼資訊應用系統的開發觀點<u>資訊應用系統</u>較開放的定義: 公司、組織所需要的應用系統, 下面縮減為<u>企業應用</u>(Ent App), 與當下常見移動 (Mobile) 和 Web 應用有所區別。開放源碼顧名思義即可。身處在公司組織中, 資訊系統所涵蓋的可能是有什麼用什麼, 或依需要採買。企業應用則依公司組織的需求, 所打造的應用 … 有些是獨立系統, 或某個系統的擴充。常要與不同單位, 甚至跨公司組織的各系統聯繫以協同作業。<br />
<br />
去年 2010 接觸一個國外頗具規模組織的企業方案導入, 從基礎設施開始到應用系統的那種。儘管方案已落入 M 社手中, 仍有許多可深入思考借鏡之處。<br />
<div><br />
</div><div>這個需要方案的組織, 雖然考慮過開放源碼方案, 對技術有想像, 對未來有憧憬, 最後還是回到踏實的 … 支援問題。</div><div><br />
</div><div>按捺支援問題, 整理過程中一些溝通討論的部份。</div><div><br />
</div><div>從頭開始的組織, 討論的觀點有多高? 大概有太空那麼高。平常較常用的辭彙字眼, 鮮少在此時派上用場。與非開發者進行討論, 還是得用流行 … 呃, 太空的觀點來溝通, 也難怪不斷有人創造一些東西來滿足。在其中討論的議題有目錄服務, 檔案分享搜尋, 管理監控, 入口網站, 工作流程, 應用系統, … 等。前三個題目, 一般公司組織都給 M 社綁住, 接下來似乎 M 社都把東西都準備好, 都可一次夠足儘管用。</div><div><br />
</div><div>曾被詢問: 如果不用 M 社方案, 這些問題如何解? 兜幾家公司產品才解決又沒參考案例, 說服力自動下降。能否找到適當資源滿足這些要求, 就成了給自己的寒假作業。</div><div><br />
</div><div>選擇以 <span class="Apple-style-span" style="background-color: #ffe599;">Java</span>, <span class="Apple-style-span" style="background-color: #ffe599;">Python</span> 為基礎, 避免對作業系統的依賴太深。</div><div><br />
</div><div>把問題劃分幾個區塊, 否則以系統/應用分太簡略, 純以開發觀點來看又太複雜: </div><br />
<div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7K5uHmGjOtj8qVVinFycE79X9WUYce9c2JXsrhdSXSi73um0uvdQj4ztR9OO14BPhCI5g7TMMaWf5XCGnh9Pw9X9K2tQE8upy29Ubvng7dljf6E7n14v6l8nRduhAcuEDe97qYg/s1600/entapp_overview.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5574963356774128370" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7K5uHmGjOtj8qVVinFycE79X9WUYce9c2JXsrhdSXSi73um0uvdQj4ztR9OO14BPhCI5g7TMMaWf5XCGnh9Pw9X9K2tQE8upy29Ubvng7dljf6E7n14v6l8nRduhAcuEDe97qYg/s320/entapp_overview.png" style="cursor: hand; cursor: pointer; display: block; margin: 0px auto 10px; text-align: center;" /></a></div><div><ul><li><span class="Apple-style-span" style="background-color: #9fc5e8;">應用系統</span>: 這是已經存在並使用的應用。ERP, B2B, 入口網站, 網購平台, 生產系統, … 甚是以套件存在的論壇, 而開發成果也在此區塊。</li>
<li><span class="Apple-style-span" style="background-color: #9fc5e8;">基礎系統</span>: 不需要應用也存在的系統。例如電子郵件, 資料庫, 網站網路服務(Web/FTP), …。</li>
<li><span class="Apple-style-span" style="background-color: #9fc5e8;">工具</span>: 基本上是支援開發相關工具。像源碼的版本管理, 記錄工作的事例追蹤, 負責測試建置, 文件產生, 資料處理, …</li>
<li><span class="Apple-style-span" style="background-color: #b6d7a8;">開發作業</span>: 可以是獨立的應用, 但通常除了基礎系統, 也與其他應用系統打交道。現在複雜環境, 選適當語言外, 更需要適當框架加持。</li>
</ul></div><div><br />
</div><div>這些區塊的涵蓋面是否恰當, 以流行的 Web 框架來檢視: 資料庫/網站在基礎系統; 編輯器/版本管理在工具區; 開發框架本身在開發作業區; 如果套在入口網站裡, 就看成在應用系統區。</div><div><br />
</div><div>再來把之前討論議題在放進來:</div><div><ul><li><span class="Apple-style-span" style="background-color: #9fc5e8;">目錄服務</span>: 有名的 OpenLDAP 使用過一陣子, 那時要編得安全一點不太容易。現在 ApacheDS, 有 Java 環境就能很快上手。雖沒 M 社搭配其作業系統的特異功能, 但具備 Kerberos, DNS, NTP, DHCP。另有 Directory Studio 處理綱目和資料都便利, 而單一簽入(SSO)可交給 CAS 處理或 PicketBox。這些放到基礎系統區。</li>
<li><span class="Apple-style-span" style="background-color: #9fc5e8;">檔案分享搜尋</span>: 從歷史來看, M 社把之前拳王 N 社撂倒後就一直雄據著, 不過移動設備和 Web 普及應該稍有機會推動一下這板塊 … 內容管理交互服務(CMIS)。實作不少, 偏好的是 Nuxeo, 實際選擇視需求而定。也放到基礎系統區。</li>
<li><span class="Apple-style-span" style="background-color: #9fc5e8;">管理監控</span>: 之前做都是一兩個系統加上數個服務, 要求是把自己做的管好就好, 沒從組織觀點來看。這方面有許多成熟產品, 例如 SpringSurce 有併入 Hyperic。會考慮的是 Zenoss, 畢竟現在有各式各樣服務, 彈性大一些會比較好。而 Java 在開發作業考量與 Zenoss 搭配, 執行記錄方面從 log4j 著手走 syslog 即可。還是放到基礎系統區。</li>
<li><span class="Apple-style-span" style="background-color: #9fc5e8;">入口網站</span>: 已經流行過好一陣子的題目, 或許每個人都有自己的一套, 就略過。分類的話, 由於依使用方式不同而有差異, 所以放應用系統區。</li>
<li><span class="Apple-style-span" style="background-color: #9fc5e8;">工作流程</span>: 推薦的是原 jBPM 開發人員從 jBoss 離開, 在 Alfresco 支持下做的 Activiti 專案。從 2010 年底釋出 5.0 以來, 2011 的前兩個月都按表操課, 穩定釋出新版本 5.1, 5.2。具備彈性流程工具外, 比較特別的是考慮開發人員甘苦, 不會一昧討好商務端人員。Activiti 可考慮嵌入與應用共存, 但從服務獨立、聯合管理的角度, 應該是單獨存在的系統, 因此放到基礎系統區。</li>
<li><span class="Apple-style-span" style="background-color: #9fc5e8;">應用系統</span>: 從開發觀點來看, 只要一個語言就可做任何事, 然而任何人能完成的事情都是有限。現成開源應用系統也不少(ERP, CRM), 加上在雲端的就更多。但能否存活, 像後者在 2010 收了好幾家, 特別讓人有疑慮。因此期望把關鍵資料放在自己可以掌握的地方, 彈性/好用是必需的, 但也不會因為開發專案的公司策略調整或併購而影響。因此選擇 OFBiz 來擔任企業核心的應用系統。</li>
</ul></div><div><br />
</div><div>回頭看各區塊, 應用系統依實際狀況而定, 基礎系統補上即時訊息(IM) Openfire 做即時通訊, 另外以通用伺服器 Felix, Karaf, Camel, ServiceMix 統籌日漸增長的服務。工具區塊比較被熟悉, 也常見許多討論個人、團體開發過程中面對的問題與解決方式。這裡對之前 <a href="http://blog.tcchou.org/2009/05/it-programming-in-near-future.html">近未來 IT 開發</a> 一文做補充, 成為開發作業區塊:</div><div><ul><li><span class="Apple-style-span" style="background-color: #9fc5e8;">穩定層</span>: 包含應用系統與基礎系統, 有穩定的界面。例如 ERP 財務的界面, 或像檔案傳輸的方式也固定。</li>
<li><span class="Apple-style-span" style="background-color: #b6d7a8;">動態層</span>: 原本以樣板打造動態層, 要含括一般且普遍的情況下, 得選用框架。以 Web 來說, 會用 Grails, 他和原本 Java 與企業大宗資源 DB 溝通方式非常的 … 一脈相承, 能快速且彈性建立 Web 應用或服務。在 Web 應用方面, 加上 ZK 協助能使用先進的 Web 技術, 卻毋需太煩惱衍生的問題。而面對複雜的服務與模組, 有更強力的 Scala/Akka 組合以函數編程與靜態語言協助建立穩定的服務。</li>
<li><span class="Apple-style-span" style="background-color: #b6d7a8;">領域層</span>: 有了上面分門別類的區塊提供各式的服務, 接下來在 grails 與 akka 下, 開發領域相關的東西。</li>
</ul></div><div><br />
</div><div>整理如下圖:</div><div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDt1vQNv8NWmX8SFqlzkOD1Iu_HJjGxWlU-YW_3aRU5aTwJrEemdNP1trE7-to3jCIZ6ykPS8O34Xp2BjcpgPYPVGxHDlSPap9Qqkyo1r2lWcXtoS3Z3ArS5oFi0O0WpHaWvhFEA/s1600/entapp_details.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5574965532069294818" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDt1vQNv8NWmX8SFqlzkOD1Iu_HJjGxWlU-YW_3aRU5aTwJrEemdNP1trE7-to3jCIZ6ykPS8O34Xp2BjcpgPYPVGxHDlSPap9Qqkyo1r2lWcXtoS3Z3ArS5oFi0O0WpHaWvhFEA/s400/entapp_details.png" style="cursor: hand; cursor: pointer; display: block; height: 194px; margin: 0px auto 10px; text-align: center; width: 400px;" /></a></div><div><br />
</div><div>歡迎指教與補充。 :)</div><div><br />
</div><div>參考連結:</div><div><ul><li>Activiti: <a href="http://www.activiti.org/">http://www.activiti.org/</a></li>
<li>Akka: <a href="http://akka.io/">http://akka.io/</a></li>
<li>ApacheDS & Directory Studio: <a href="http://directory.apache.org/">http://directory.apache.org/</a></li>
<li>Camel: <a href="http://camel.apache.org/">http://camel.apache.org/</a></li>
<li>CMIS: <a href="http://en.wikipedia.org/wiki/Content_Management_Interoperability_Services">http://en.wikipedia.org/wiki/Content_Management_Interoperability_Services</a></li>
<li>Felix: <a href="http://felix.apache.org/site/index.html">http://felix.apache.org/site/index.html</a></li>
<li>Grails: <a href="http://www.grails.org/">http://www.grails.org/</a></li>
<li>Groovy: <a href="http://groovy.codehaus.org/">http://groovy.codehaus.org/</a></li>
<li><a href="http://tcchou.tumblr.com/post/2807539910/log4j-syslog-settings">log4j 搭配 syslog</a></li>
<li>Jasig CAS: <a href="http://www.jasig.org/cas">http://www.jasig.org/cas</a></li>
<li>JBoss PicketBox: h<a href="http://www.jboss.org/picketbox">ttp://www.jboss.org/picketbox</a></li>
<li>Karaf: <a href="http://karaf.apache.org/">http://karaf.apache.org/</a></li>
<li>Nuxeo: <a href="http://www.nuxeo.com/en">http://www.nuxeo.com/en</a></li>
<li><a href="http://blog.tcchou.org/2010/11/ofbiz.html">OFBiz 完全中文安裝教學</a></li>
<li>Openfire: <a href="http://www.igniterealtime.org/projects/openfire/index.jsp">http://www.igniterealtime.org/projects/openfire/index.jsp</a></li>
<li>Scala: <a href="http://www.scala-lang.org/">http://www.scala-lang.org/</a></li>
<li>ServiceMix: <a href="http://servicemix.apache.org/home.html">http://servicemix.apache.org/home.html</a></li>
<li>Zenoss: <a href="http://www.zenoss.com/">http://www.zenoss.com/</a></li>
<li>ZK: <a href="http://www.zkoss.org/">http://www.zkoss.org/</a></li>
</ul></div>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-8661594263490529582011-01-09T23:38:00.006+08:002011-01-09T23:46:58.265+08:00Tabledown目前資訊技術兩股趨勢: 一個是普及的行動設備, 一個是數大的雲端計算。在兩者激盪之下, 各種應用遍地開發。從 TIOBE 索引排名, 以及陸續開張的軟體商店, 就可看出百家(?)爭鳴, 且各家皆各自擁有龐大的支持群眾。<br /><br />普及的行動設備會演變成為一個人擁有多個設備, 但不連線(不連續)就會造成的問題。Dropbox 解決了檔案問題, 讓檔案同步因此大受歡迎。而雲端運算到後面各個服務的連結也會造成不連續, 簡單舉例: 金流可連續完成, 但物流就不可能。<br /><br />從結果來推論需求, 如果生產, 金流, 物流都上雲端了, 那在手上(設備)要掌握什麼資訊?<br />(嗯 … 產品的規劃設計是另一件事。)<br /><br />要掌握的資訊, 可能人人不同, 也可能隨客戶的客戶而不同(B2B)。<br /><br />雖然流行的腳本語言(Scripting)能因應快速的變更, 大部分時候在程式碼與資料間是有清楚的界線。這個界線是 … 使用者(或客戶)非常在意資料, 而程式員則關注程式碼。即便可選擇的開發工具很多, 也都很強大, 但幾乎是建立 MVC 下, 類似 rails 模式, 或者是說與資料庫關係密切, 這些都屬於連線(連續)的形式。<br /><br />最好能夠做到『碼即資料, 資料即碼』(code is data, data is code), 由使用者在掌握資料即能驅動後頭的雲端, 即使不連接也可讓服務運作下去。<br /><br />不論如何, 資料還是需要載體(Container), 最好的載體應該是試算表。它除了能放置資料, 還能兼顧人們視覺操作的慣性, 可將資料的顯示位置, 存在與否, 還有排列做調整。如果沒有應用程式, 這種方式應該是首屈一指的資料載體。<br /><br />主角都現身, 可想像一下: 透過試算表來連接各種後端的服務(雲端)。資訊服務業能透過試算表輸入資料(例如使用者需求), 再批次進入報價服務, 每月產生報價單寄送給客戶。至於損溢, 現金流量, 庫存也可定時同步到試算表 … 並竟不是每個人都每秒十萬上下。<br /><br />基於這樣的出發點, 建立了 Tabledown 專案。簡單來說, 是能夠讓試算表與集合資料(lists, hashes)做雙向資料交換, 透過一個對映集合設定(mapping collections configuration, MCC)來轉換。<br /><br />已完成的是概念雛形的驗證, 就是在 google code 頁面的範例。陸續會做一些修正, 使用雲端試算表, 以及與 ERP, BPM 連接。<br /><br />Tabledown 目前是組 Python 的程式庫, 希望有機會改頭換面成為一般工具。而 Tabledown 命名的點子是從 Markdown 而來。<br /><br /><hr><br /><div>參考</div><div><ul><li><a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">TIOBE 索引排名</a></li><li><a href="http://www.propylon.com/news/ctoarticles/code_data_030311.html">Code is data, and data is code</a></li><li>Tabledown: @<a href="http://pypi.python.org/pypi/tabledown/">pypi</a> @<a href="http://code.google.com/p/tabledown/">googlecode</a></li></ul></div>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-50139203589471973872010-11-27T21:52:00.001+08:002010-11-27T21:52:37.210+08:00OFBiz 完全中文安裝教學OFBiz 是 ERP, CRM, eCommerce, SCM, MRP, … 以 Apache 授權的企業自動化軟體。之前可能不太容易上手, 一方面這種軟體需要關注的層面太多, 另一方面沒有中文化(有簡體中文)。<br /><br />以上在這兩週有些改變。上週(11/18) Bakker 先生提供了<a href="http://bit.ly/gWqQVN">快速設定的方式</a>(r1036323), 包含: 公司, 倉儲, 商店, 電子商務網站, 第一位客戶, 第一筆產品 … 只要走過幾個 Web 畫面就可完成 OFBiz 基本資料設定。而這週中文化進入 trunk (r1039574), 應該能降低語言的隔閡。<br /><br />大部分這類軟體要設定 網站伺服器,資料庫以及系統本身。而 OFBiz 由於 Java 語言的優勢, 嵌入了網站伺服器與資料庫, 只要一個指令就可啟動, 假使需要也可用常見的網站伺服器或資料庫替代。除了降低入門門檻, 同時也具備擴充性。<br /><br />更多的 OFBiz 介紹可參考: <a href="https://cwiki.apache.org/confluence/x/wghkAQ">什麼是 OFBiz</a>, <a href="https://cwiki.apache.org/confluence/x/3wZxAQ">專案概觀</a> (各模組介紹), <a href="https://cwiki.apache.org/confluence/x/xghkAQ">OFBiz 適合我嗎?</a><br /><br />下面把 OFBiz 在 Windows 完整安裝過程 (從下載檔案開始), 包含必要的修正, 並簡單示範了銷貨訂單, 採購訂單的建立與使用 … 做成影片放到 Youtube 頻道中 ... <a href="http://www.youtube.com/view_play_list?p=3EC38FAD430643E2">OFBiz 線上教學</a>。tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com1tag:blogger.com,1999:blog-9590240.post-78957335942565085262010-11-13T23:01:00.008+08:002010-11-13T23:27:21.483+08:00應用開發的簡化<h3><span class="Apple-style-span" style="color:#333399;">容易的方式</span></h3>雖然常把實用新穎的技術簡化, 想辦法放入既有系統中, 讓夥伴、客戶都能上手使用, 但現實中卻還是不夠。<br /><br />前幾天幫客戶除錯, 看問題時, 才知道他們做了什麼 … 有點類似 Web Services (偽), 卻是用 PHP。他們在生產過程中, 要把某個事件記錄在另一個資料庫。當然用 PHP 沒什麼問題, 只是把所有執行相關工作都寫在一個檔案裡頭的做法, 很明顯是從書上抄下來的範例, 再改一改的成果。<br /><br />對許多人來說, 書上有類似的範例, 能照本宣科就拿來用就好。這大概是某些語言長年佔據 <a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">排行榜</a> 的原因, 但時至今日這股『只要能動』的風潮漸漸改變。在 Web 時代大部分拿 SQL 就直接用, 到了 Web Services 時代, 分工愈來愈細, 要求愈來愈多, 許多程式的運作都以物件為基礎。並非談物件的優劣, 而是評估現實中若使用物件比 SQL 方便, 比如資料的呈現(xml, json), 處理(鷹架), 以及檢核這些作業, 自然而然趨勢也跟著改變。<br /><br />這裡還有一個關鍵點, 以上面出問題的 PHP 來說, 不管怎樣只要一個檔案就做完收工。原有系統在程式方面雖然也能簡單做到, 但要連到他們內部使用的資料庫(MySQL)這種配置就不太容易。因為原系統採 N 階層架構, 要多接個資料庫, 雖然可做到, 但得更動不少層。<br />或許從仿 PHP 單一檔案開發起個頭, 比較容易些。<br /><br /><h3><span class="Apple-style-span" style="color:#333399;">簡單的實現</span></h3>PHP 帶領 <a href="http://en.wikipedia.org/wiki/LAMP_(software_bundle)">LAMP</a> 的風潮, 在 <a href="http://zh.wikipedia.org/zh-tw/%E7%BA%A6%E5%AE%9A%E4%BC%98%E4%BA%8E%E9%85%8D%E7%BD%AE">約定優於配置</a> 之前, 受到許多開發人員喜愛。著重四個方面: 簡單編寫, 簡單散佈, 本機開發, 便宜且到處可託管。除了最後一個外, 前三項直接讓開發的人獲得好處。預設與 MySQL 搭配(以 5.3.3 來說, 還有 PostgreSQL, Oracel, Sqlite), 因此只要資料庫能夠運作, 程式就能寫, 能動, 能測。程式執行後, 也能立即從資料庫看看結果是否正確。<br /><br />再複雜些的系統, 除了語言本身, 還得準備更多暖身課程。<br /><br />在今天之前, 也一直覺得 PHP 劃下簡單的境界, 是無法挑戰的。原本的 Groovy 知識, 只想做到很接近, 但查了查資料, 發現結果還不錯。<br /><br />前提是有個 MySQL 在正常運作, 假設有資料庫 mydb 以及表格 mytbl 如下:<br /><div style="text-align:center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqy1Pf-sPCUXRfKWB293RESYtz7wFeIi_96QBGycH0jxPaOWcdXQw-3_2_VPUoA77crLuPd5A32PgLafggZlr-3RwhoDRGjuY-3i2m4Lrr2-s7k244xsAP70-YVMMl1md5zmnisA/?imgmax=800" alt="simp_mysql.png" border="0" width="450" height="334" /></div><br />有兩欄(name, tel), 以及兩列資料。<br /><br />先確定裝妥 JDK 1.6 以上版本, 再到 <a href="http://groovy.codehaus.org/">Groovy 首頁</a> 下載 1.7 之後版本, 然後執行 bin/ 目錄下的 groovyConsole 能直接寫程式。<br /><br />拷貝、貼上程式碼:<br /><br /><pre name="code" class="java"><br />@Grapes([<br />@Grab('mysql:mysql-connector-java:5.1.13'),<br />@GrabConfig(systemClassLoader=true)<br />])<br />import groovy.sql.Sql<br /><br />def dbUrl="jdbc:mysql://localhost/mydb?useUnicode=yes&characterEncoding=UTF-8"<br />def driverClass="com.mysql.jdbc.Driver"<br />def sql=Sql.newInstance(dbUrl,"root","root",driverClass)<br />sql.eachRow("select * from mytbl") {<br />println it<br />}<br /></pre><br /><br />注意, 資料庫位置 localhost, 名稱 mydb, 帳號/密碼 root/root, 還有表格名稱 mytbl 可能需要置換。然後選擇執行, 可用工具列右邊屬來第二個圖示, 或選單裡頭 Script/Run。第一次可能久一點, 因為缺少連接 db 的程式庫(不像 PHP 有附加), 要花些時間下載, 之後就正常。LAMP 要義的第一項簡單編寫, 第三項本機開發, 可順利達成。整個結果, 應該和下圖差不多:<br /><div style="text-align:center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA3ffc7yv1ii5dciD01Q_vmNZzHgha_xj1-uayPE9rDNPld14eGh7JzR0eFLUqeTybrhv4_7nnOahoxn2DEwyOVRkERgx67IK3j6C-mdM9zRKTzVwJq-87ryTrINyEkYqyGSExkA/?imgmax=800" alt="simp_groovy.png" border="0" width="480" height="391" /></div><br />除了讀取資料庫, 其它新增、更新、刪除的 SQL 也都有, 請參考 Groovy SQL。確定沒問題, 就存檔保留。<br /><br />不過這時候或許有人會問: PHP 在命令列(command line)下執行很快的, Groovy 那能比? 那請試試 GroovyServ, 雖然有點作弊, 但就像 IE 比其他瀏覽器快, Office 比其他工具快, 差不多就是那種的方式 …<br /><br />換不同資料庫, 應該只要改上面截圖中第 2 列程式庫, 第 7 列連接資料庫網址, 第 8 列資料庫套件名稱, 可能再加上第 9 列的帳號、密號, 其它步驟類推即可。<br /><br />以上示範, 算真正的單一檔案寫完收工, 也簡單到少有的地步。<br /><br />那放到網站是否很複雜?<br /><br />在 Java 使用 <a href="http://tomcat.apache.org/">Tomcat</a> 會比 LAMP 中 Apache 容易。相同方式 tomcat 5, 6, 7 版本可通用, 這裡以 tomcat 6.0.29 示範。下載後解開, 把長長的目錄改為 tomcat6/。<br /><br />在 tomcat6/ 下的 webapps/ 裡頭建 groovy/ 目錄, 再建 WEB-INF/。<br /><br />把 Groovy 1.7 的 lib/ 複製到 WEB-INF/ 裡頭。<br /><br />在 WEB-INF/ 增加 web.xml 檔案, 內容如下:<br /><br /><pre name="code" class="xml"><br /><web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"><br /><display-name>Groovy Web Apps</display-name><br /><br /><servlet><br /><servlet-name>Groovy</servlet-name><br /><servlet-class>groovy.servlet.GroovyServlet</servlet-class><br /></servlet><br /><br /><servlet-mapping><br /><servlet-name>Groovy</servlet-name><br /><url-pattern>*.groovy</url-pattern><br /></servlet-mapping><br /></web-app><br /></pre><br /><br />而把上面讀取資料庫的 groovy 程式, 前幾列 @Grab 改一些 (有點尷尬, 之前寫法在 Web 不能用), 不過下列是通用的。(日後應該會針對此點修補 @Grab 才是)<br /><br /><pre name="code" class="java"><br />ClassLoader.systemClassLoader.class.name = 'groovy.lang.GroovyClassLoader'<br />groovy.grape.Grape.grab(classLoader:ClassLoader.systemClassLoader<br />,group:'mysql', artifact:'mysql-connector-java', version:'5.1.13')<br />import groovy.sql.Sql<br /><br />def dbUrl="jdbc:mysql://localhost/mydb?useUnicode=yes&characterEncoding=UTF-8"<br />def driverClass="com.mysql.jdbc.Driver"<br />def sql=Sql.newInstance(dbUrl,"root","root",driverClass)<br />sql.eachRow("select * from mytbl") {<br />println it<br />}<br /></pre><br /><br />整個做法的結果應該和下圖相同:<br /><div style="text-align:center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb6Sb6axH3FpH1SvLXDqA49AFhI6wnRNebe3HKCWyc2fex7iilQ5IZALl4fx-tRLjeJ0KGFN_KFgfQ5TBueXgnpXWJhBM064c-7-47O9bkqe87Zmc7-nWK62G3nXUyUQV7UAmlEg/?imgmax=800" alt="simp_tomcat.png" border="0" width="480" height="261" /></div><br />以上方法做完, 執行 tomcat 6 … 一般用 bin/catalina.sh run 即可。<br /><br />此時瀏覽器看到結果如下:<br /><div style="text-align:center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOI-YUcl7jstobPQE_YJk_CICLG43HZHd-tmU9VT3mk2fBw_2pxfrSJls3TamhwnKtENwePaoU3SI9YgFWSO-Ws8Z5laUAoC6BBdHscZKEHX4mjBkNaUm6qu-e5txXGv0AXN4wqw/?imgmax=800" alt="simp_web.png" border="0" width="450" height="231" /></div><br />單機寫完應用程式, 執行驗證完後, 隨即放上網站目錄去, LAMP 要義第二項的簡單散佈也可達陣。<br /><br /><h3><span class="Apple-style-span" style="color:#333399;">簡單還要更簡單</span></h3>原先想寫關於資料庫程式遷徙到 <a href="http://www.grails.org/">grails</a> 的方式, 因為客戶的問題轉到另一個題目上, 與 PHP 的某種(通用?)做法比劃一下。<br /><br />除此之外, 還有更積極的意義 … PHP 固然是寫資料庫和網頁程式的主流, 其相關資源可略窺一二。但 Java 連接的 IT 資源更廣泛, 像負責生產管理的 MES, 或財務處理的 AIS, 都由於加上 Groovy 的協助, 讓原本的系統有更大彈性, 也讓部份客製門檻降低, 例如一些報表、檢核的作業讓更多 IT 人員參與。可以想像一下 … 上面 SQL 資料讀入與 Web 輸出部份, 換成來自不同系統流程的資料, 以及 csv, xml, xls 或 pdf 輸出, 輔以適當的權限與稽核, 就可讓原本要獨立開發的程式變成簡單的腳本擋。<br /><br />且如同 PHP 一般即改即用, 很簡單的滿足許多需求。<br /><br /><h3><span class="Apple-style-span" style="color:#333399;">參考</span></h3><ul><li>石頭閒語的 <a href="http://blog.roodo.com/rocksaying/archives/11157957.html">軟體開發之建置風險的故事</a></li><li><a href="http://docs.codehaus.org/display/GROOVY/Tutorial+6+-+Groovy+SQL">Groovy SQL</a> 用 Groovy 寫 SQL 程式也可以行雲流水</li><li><a href="http://tcchou.tumblr.com/post/997325784/groovyserv">GroovyServ</a> 加速 Groovy 程式執行</li><li><a href="http://groovy.codehaus.org/Groovlets">Groovy Servlet</a> 把應用程式放上網站</li><li><a href="http://groovy.codehaus.org/Grape">Groovy Grape</a> 對程式庫做了一些神祕的事情</li></ul>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-20316546603641100202010-11-08T19:18:00.012+08:002010-11-09T05:57:29.970+08:00應用系統的版本管理<span class="Apple-style-span" style="font-size: x-large; color: rgb(51, 51, 153); font-weight: bold; ">一段歷史</span><br /><br /><div>經過幾年軟體版本管理工具爆炸性的競合, 如果不考慮控制的問題, 我們可以自由選用 subversion(svn), mercurial(hg) 以及 git。svn 存在時間最早, 在有一些歷史的專案和中小公司比較常見; hg 由於簡單明確, 大型源碼社群如 sourceforge, codeplex, google code 普遍接受; 而 git 強大穩定, 則是技客首選。<div><br /><div>這三者陸續在用, 雖然深淺各有不同, 從歷史角度來看: 最早通用的 cvs 是管理檔案版本, 所以會有 v1.0, v1.1, v1.2, ….。svn 側重整個專案版本, 標示版本以整個儲存庫為準 r123, r223, r323, … (r=revision)。大概是 cvs 時期一個檔案就可做完一件事, 到了 svn 得靠一堆檔案 … 請參考『軟體工程師的進化』一文。</div><div><br /></div></div><div>到了 dvcs(hg, git) 回歸功能面管理, 版本像是 229a46966a72, 13a7d2806d50, 64d88c389b67, … 的 uuid。意義不再是檔案版本編號(v1.0), 或由儲存庫變更序號(r123)做認定。應該沒有人可從 dvcs 裡版本號碼看出任何意義。一方面在每次提交版本(commit)輔以適當註解, 而整體來看, 端視儲存庫擁有者認定版本的意義。因為是 dvcs … 只要有心, 人人都可以是儲存庫擁有者 … peace!</div><div><br /></div><div>對一個專案來說, 針對檔案變更追蹤是過小, 像流行的 MVC (Model-View-Controller)在概念上就跨了三層。若針對儲存庫變更追蹤又太大, 變更頻繁的話, revision 就如同雪片般, 好看是好看, 但一般也只是好看。因此, dvcs 當是比較符合趨勢的選擇。</div><div><b><br /></b></div><div><div style="font-weight: bold; "><span class="Apple-style-span" style="font-size: x-large; color: rgb(51, 51, 153); font-weight: bold; ">一種問題</span></div><div style="font-weight: bold; "><br /></div><div>交待完歷史, 回頭看主題。假設專案有源碼要管理, 這個應用系統是承上啟下, 也就是依據上游源碼為基礎, 提供下游客戶穩定、加強、或客製的版本。是種常見模型:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEhBiLp-7K81sqCKTyCyvjVm2_MQRR4jJaCGgH8WXXCCWpbY4Y29oP2W1wj8qyiDzxZyd-5nDZi01lLjOt1FhMiIHd9CxRZbb7viXou-VGMblEA3t5cCH8_kyAwtbFhXQSbP8c4Q/s1600/ascm_basic.png"><img style="text-align: left;display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; cursor: pointer; width: 320px; height: 94px; " src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEhBiLp-7K81sqCKTyCyvjVm2_MQRR4jJaCGgH8WXXCCWpbY4Y29oP2W1wj8qyiDzxZyd-5nDZi01lLjOt1FhMiIHd9CxRZbb7viXou-VGMblEA3t5cCH8_kyAwtbFhXQSbP8c4Q/s320/ascm_basic.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5537138115439348242" /></a><span class="Apple-style-span" style="font-size: x-small;"><div style="text-align: right;">上游儲存庫 UR - Upstream Repository</div></span></div></div></div><div style="text-align: right;"><span class="Apple-style-span" style="font-size: x-small;">我的儲存庫 MR - My Repositroy</span></div><div><br /></div><div><div>源碼儲存庫畢竟是技術人員才會接觸到, 大部分狀況以策略解決: 有時將上游源碼設定為程式庫, 簡化問題; 或以廠商分枝(Vendor Braches)將上游源碼納入專案; 而產品類專案, 可忽略 n 個客戶問題。</div><div><br /></div><div>但如果使用開放源碼 CMS, CRM 或 ERP 這類應用為主的系統, 上游持續加強版本, 下游因應需求不斷變更 … 會爆炸的點大概就是位居中間的儲存庫。</div><div>在網路上, 看到相關問題討論有:</div><div><ol><li><a href="http://bitbucket.org/segv/hg-website/wiki/Workflows">非官方 hg 流程</a> 中 Offsite working on dynamic websites。其中『Upgrading Drupal with Git』(部落格已落幕, 可參考 <a href="http://web.archive.org/web/20080515142001/http://versioncontrolblog.com/2007/08/02/upgrading-drupal-52-with-git/">archive.org</a> 資料)。</li><li>也是 drupal 開發, 教學視訊 <a href="http://www.larks.la/training/git-with-drupal-7">Git With Drupal 7</a>。</li><li>opentaps(ERP) 的建議 <a href="http://www.opentaps.org/docs/index.php/Managing_Customizations_with_Upgrades">Managing Customizations with Upgrades</a>, 大抵是分為四個層次: a. 瞭解現有的, 將異動最小化 b. 貢獻源碼, 免除版本差異, 透過社群改進 c. 獨立應用程式在特定目錄下 d. 若修改核心及社群不接受的源碼, 得注意合併問題。最末項不建議, 因容易出包。</li></ol></div><div>上面第三項 "在特定目錄下" 放應用程式, 是大部分應用系統普遍的做法, 像 SugarCRM 也有類似的機制。</div><div><br /></div><div>通常專案會設定上游的版本, 但長期提供服務, 必然會面對上游版本變更。而下游的需求, 投入行業時間夠久, 一般也會有共通方式解決, 例如提供一個檔案上傳或流程整合的功能, 應該也不希望一家處理過版本提升後, 還得要處理其他家客戶相同問題。</div><div><br /></div><div>技術上, 沒有通用做法的話, 能抑制爆炸的源碼就大概只有爆炸的肝。(以爆制爆?)</div></div><div><br /></div><div><span class="Apple-style-span" style="font-size: x-large; color: rgb(51, 51, 153); font-weight: bold; ">一項解法</span></div><div><br /></div><div><div>如果著眼於儲存庫, 所有問題都成為一團。首先區分上游變更, 與下游需求這兩個變動的來源。其他像共通功能的開發, 問題的修正, … 先納入下游需求。</div><div><br /></div><div>再來, 如版本管理的演化(csv → svn → dvcs), 因時制宜般, 上游變更以分枝(branches)處理, 下游需求以變更佇列(patchs queue)對付, 再建立一個儲存庫負責照拂需求的變更佇列, 是為『變更儲存庫』。<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVAMZHTZ7GTRkzafzl9C3y96E_Ti0kf5xwXf6VIBDRFLuF3S7D6HxoXXkR84ncyKL2Qp8SF2mBANRbAKGxTncyzrsYF4Mi2ouLoFmgLl9c0mt1PK1C48Ps2xK3FYskF-BEyKp4HA/s1600/ascm_mq.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 191px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVAMZHTZ7GTRkzafzl9C3y96E_Ti0kf5xwXf6VIBDRFLuF3S7D6HxoXXkR84ncyKL2Qp8SF2mBANRbAKGxTncyzrsYF4Mi2ouLoFmgLl9c0mt1PK1C48Ps2xK3FYskF-BEyKp4HA/s320/ascm_mq.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5537140265121533394" /></a><span class="Apple-style-span" style="font-size: x-small; "><div style="text-align: right;">變更儲存庫PR - Patch Repository</div></span></div></div><div><div>變更佇列在 git 中有外掛 <a href="http://www.procode.org/stgit/">stgit</a>, <a href="http://savannah.nongnu.org/projects/quilt">quilt</a>, 至於 hg 是內建 mq (mercurial queues)。</div><div><br /></div><div>在手上實際 ERP 案例中, 上游儲存庫每個月大約有 800kb 左右的差異檔(diff), 而變更佇列除了中文化有 5mb 的差異檔, 其他加起來不到 300kb。每月同步上游儲存庫後, 再更新變更佇列, 也就是 UR 與 PR 會有版本對應的關係。只要 UR 與 PR 同步後, 就可一體適用其他相同系統的客戶。節省下的資源可專注差異化部份。</div><div><br /></div><div>一方面是變更的大小與不同機制的搭配, 另一方面是變更佇列對每項修補差異的處理, 比分枝來得直覺。例如把中文化和其他修補一起放入同一個分枝中, 當上游版本更新, 要合併到分枝時, 假使自動合併無效, 要看到檔案才能處理, 同時可能也要處理 API 差異之類的。簡單來說, 就是要有經驗的工程師才能處理版本合併的事務。如果是以變更佇列處理的規劃, 就很方便分工, 中文化部份安排通中/英文, 細心的工程助理打點即可。</div></div><div><br /></div><div><span class="Apple-style-span" style="font-size: x-large; color: rgb(51, 51, 153); font-weight: bold; ">參考</span></div><div><ul><li><a href="http://blue.lins.fju.edu.tw/mao/va/jokes.htm">軟體工程師的進化</a> (原文: http://www.infiltec.com/j-h-wrld.htm)</li><li><a href="http://www.infoq.com/articles/dvcs-guide">Distributed Version Control Systems</a></li></ul></div><div><br /></div>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-35765249496614713382010-08-31T09:30:00.002+08:002010-08-31T09:33:30.864+08:00Bonjour 你好<a href="http://en.wikipedia.org/wiki/Bonjour_(software)">Bonjour</a> 是 <a href="http://www.apple.com/support/bonjour/">蘋果</a> 版 <a href="http://www.zeroconf.org">zeroconf</a> 免設定網路產品, 協助使用者更容易用網路。<br/><br />雖然 Bonjour 與 zerconf 目標是各種網路服務, 這裡的範圍限制在網頁。免設定網路目前解決三個問題: 設備(名稱)的IP(網路位置)指定, 自動取得名稱與IP關連(廣播法 mDNS), 自動取得網路服務(dns-sd)。<br/><br />技術上有點繞口, 實務上就如同一個 Wiki 工具 <a href="http://flyingmeat.com/voodoopad/">Voodoo Pad</a> 寫妥許多內容, 要分享只要點選 Start 按鈕:<br /><div style="text-align:center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY0dfR9RBkdWBdl98VIchzdayDo3Lq0cIw2FQXpA_bsP6_HT-Z4ChVPA_QUfVaQNW3-2z_F0wCTlfPPA8RAXEctDpjyRoIzdxxrCF3KfI2zazyN9Pw-A5slT1wIPn3FWQSxOlLHw/?imgmax=800" alt="voodoopad_web.png" border="0" width="560" height="290" /></div><br />其他人利用 Safari 的書籤頁就可以看到:<br /><div style="text-align:center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicQKwrX5GgXuvMxp46w9xJxZS7BVCl-iNMV7dJ8eDPSUYeg5dk1jDpO4-QaYePYZUdxkUCzq8Vk9vCw651Z4vkbgI0lFmTTCvaYwKoALwItjSXpTBaOY0P4YJN3U2DYvSFGehp2g/?imgmax=800" alt="safari_bonjour.png" border="0" width="400" height="130" /></div><br />不用網址、埠號、目錄, 看到名稱點下去, 立即瀏覽網頁。<br/><br />除 Safari 外, Firefox 的 <a href="http://www.bonjourfoxy.net/">BonjourFoxy</a> Plug-in 有相同功能, 目前支援 Windows 與 OSX。(Windows 安裝前須先裝妥 Apple Bonjour 套件)<br /><div style="text-align:center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9oDLB1OUc5hY4qRct_rwoLD4mCueJWBT-0VB9c7WvU1U2l6D0lWbiq7W7CTHq8sy7g-kmvwNWaU16DORZm3mbdQHIrbkmUGEOtoNWwhsfiPgJ2uoJNLwTeIVrQ0dU1nZuMwL2zw/?imgmax=800" alt="bonjourfoxy.png" border="0" width="275" height="100" /></div><br />BonjourFoxy 另附有 Bonjour Browser 可觀察 dns-sd 詳細內容:<br /><div style="text-align:center;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirfbNwEXy6FYJ3UnZWJMn59lPdF4lfGwJdAnr-SrWFSJDlF9xi_g22lRv7JSfLEBjBsvktCIp5WWVBAa-KhoW0WYxaG_WKT6aBRS9F_Ehp-m3Mku0IuKPvEjvJTBaWe8L7n6OegQ/?imgmax=800" alt="bonjour_browse.png" border="0" width="400" height="305" /></div><br />寫到這裡都是使用者操作面上。手上也有許多各式各樣網頁, 是否能建立 Bonjour 項目瀏覽資料?<br/><br />最簡單方法大概利用 OSX 中 /usr/bin/dns-sd (Bonjour 套件) 在 Terminal 下指令:<br/><br /><pre name="code" class="shell">$ dns-sd -R "Plone" _http._tcp "" 7070 "Plone 4 Here"<br /></pre><br />會佔住 Terminal, 要結束就直接按 ctrl-C。<br/><br />dns-sd 除了為本機建立 Bonjour 服務項目, 也可代理(Proxy):<br/><br /><pre name="code" class="shell">$ dns-sd -P "Zoo Keeper" _http._tcp local 80 hadoop.apache.org "" path=/zookeeper "你好 Zoo Keeper"<br /></pre><br />注意 path 可指定 URL 主機、埠號後的部份。<br/><br />分享網址除了剪貼、美味書籤、社群工具, Bonjour 也是個方式, 而且是立即的。tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-61104041779852498762010-08-27T12:11:00.001+08:002010-08-27T12:24:19.532+08:00ZKFuse 與 macfusezkfuse 可能會被歸在玩具類, 是網路控制中心 <a href="http://hadoop.apache.org/zookeeper/">ZooKeeper</a> 把資料暴露在 <a href="http://fuse.sourceforge.net/">FUSE</a> 下。但與 <a href="http://code.google.com/p/macfuse/">macfuse</a> 不符(API 差異), 就游進去解決一下 ...<br/><br />參考網誌 <a href="http://leemoonsoo.blogspot.com/2009/04/howto-mount-zookeeper-using-fuse.html">HowTo Mount ZooKeeper using FUSE</a> 的做法。<br/><br />zkfuse 需要 fuse(macfuse 2.0.3), boost, log4cxx ... 都用 macports 裝妥。<br/><br />取得 <a href="http://www.apache.org/dyn/closer.cgi/hadoop/zookeeper/">zookeeper-3.3.1.tar.gz</a> 解開到 <zookeeper3>。<br/><br />按照 <zookeeper3>/src/c/README 編 zookeeper:<br /><pre name="code" class="shell">$ cd zookeeper3<br />$ ant compile_jute<br />$ cd src/c/<br />$ ./configure<br />$ make<br />$ sudo make install<br />(預設安裝到 /usr/local/include/ 與 /usr/local/lib/)<br /></pre><br />到 zkfuse/ 目錄下:<br /><pre name="code" class="shell">$ cd ../contrib/zkfuse/<br />$ autoreconf -if<br />$ export LDFLAGS="-L/usr/local/lib -L/opt/local/lib"<br />$ export CXXFLAGS="-I/opt/local/include -I/usr/local/include"<br />$ export LIBS="-lzookeeper_mt"<br />$ ./configure<br /></pre><br />由於 macfuse 與 fuse 差異, 修改 src/mutex.h:<br /><pre name="code" class="shell">--- mutex.h.original 2010-08-27 10:38:10.000000000 +0800<br />+++ mutex.h 2010-08-27 10:38:20.000000000 +0800<br />@@ -34,7 +34,7 @@<br /> public:<br /> Mutex() {<br /> pthread_mutexattr_init( &m_mutexAttr );<br />- pthread_mutexattr_settype( &m_mutexAttr, PTHREAD_MUTEX_RECURSIVE_NP );<br />+ pthread_mutexattr_settype( &m_mutexAttr, PTHREAD_MUTEX_RECURSIVE );<br /> pthread_mutex_init( &mutex, &m_mutexAttr );<br /> }<br /> ~Mutex() {<br /></pre><br />修改 src/zkfuse.cc:<br /><pre name="code" class="shell">--- zkfuse.cc.original 2010-08-27 10:28:37.000000000 +0800<br />+++ zkfuse.cc 2010-08-27 10:30:01.000000000 +0800<br />@@ -27,7 +27,7 @@<br /><br /> extern "C" {<br /> #include <fuse.h><br />-#include <ulockmgr.h><br />+// #include <ulockmgr.h><br /> }<br /> #include <stdio.h><br /> #include <string.h><br />@@ -4171,16 +4171,17 @@<br /> int zkfuse_lock(const char *path, struct fuse_file_info *fi, int cmd,<br /> struct flock *lock)<br /> { <br />- (void) path;<br />- return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner,<br />- sizeof(fi->lock_owner));<br />+ return 0;<br />+// (void) path;<br />+// return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner,<br />+// sizeof(fi->lock_owner));<br /> }<br /><br /> static <br /> void init_zkfuse_oper(fuse_operations & fo)<br /> {<br />- memset(&fo, 0, sizeof(fuse_operations));<br />+// memset(&fo, 0, sizeof(fuse_operations));<br /> fo.getattr = zkfuse_getattr;<br /> fo.fgetattr = zkfuse_fgetattr;<br /> // fo.access = zkfuse_access;<br />@@ -4204,7 +4205,7 @@<br /> fo.open = zkfuse_open;<br /> fo.read = zkfuse_read;<br /> fo.write = zkfuse_write;<br />- fo.statfs = zkfuse_statfs;<br />+// fo.statfs = zkfuse_statfs;<br /> fo.flush = zkfuse_flush;<br /> fo.release = zkfuse_release;<br /> fo.fsync = zkfuse_fsync;<br /></pre><br />改完繼續做出 zkfuse:<br /><pre name="code" class="shell">$ make<br /></pre><br />產生 src/zkfuse ... 然後繼續: (開始用 zkfuse 前要先啟動 zookeeper)<br /><pre name="code" class="shell">$ mkdir 123<br />(要 mount 的入口點)<br />$ src/zkfuse -z localhost:2181 -m 123 -d<br />(要加 -d, 否則不能用 ... 但終端機會被佔住)<br /></pre><br />開另一個終端機看 123/ 目錄內容:<br /><pre name="code" class="shell">$ ls zookeeper3/src/contrib/zkfuse/123<br />zookeeper<br /></pre>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-23269089019523815172010-08-25T10:40:00.001+08:002010-08-25T10:45:40.007+08:00Avro 的使用與 Groovy Builder<a href="http://avro.apache.org">Avro</a> 是動態型別的資料序列化工具, 協助資料存放保留, 主要是讓網路化的應用程式有效率的溝通。如同使用語言設計模組溝通一般會透過界面方式, 在網路的服務常有著不同語言的實作, Avro 提供這些服務溝通的方式。<br /><br />定義網路溝通的是通訊協定(Protocol), Avro 利用 JSON 定義通訊協定。<br /><br />協定內包含有若干具名(name)的訊息(Protocol.Message), 每個訊息含有 3 種型態內容: 要求(Requst), 回覆(Response), 還有錯誤(Errors)。這些內容都以綱目(Schemas)定義內容的組成。<br /><br />Avro 協助按綱目組成傳送的訊息。這裡有兩個關鍵: 一是組成, 一是傳送。<br /><br /><strong>組成</strong>部份請參考 <a href="http://people.apache.org/~phunt/">Patrick Hunt</a> 先生的快速開始使用 Avro <a href="http://github.com/phunt/avro-rpc-quickstart">範例</a> 中可看出 python 與 ruby 都用語言本身的 collection 組成; 而 Java 則用 GenericData 套件。<br /><br />而<strong>傳送</strong>方面 Avro 有 HTTP 與 Socket 兩種通用方式, 服務端是 Server, 使用端是 Transceiver。如果用訊息服務(MOM)或搭配既有SOA,ESB系統, 就得抓訊息產生結果來操作。(在 Java 用 GenericRequestor, GenericResponder 中的 read/write 方法)<br /><br />以 Groovy 與上面 Python 範例對連:<br /><pre name="code" class="java">import org.apache.avro.Protocol<br />import org.apache.avro.util.Utf8<br />import org.apache.avro.ipc.HttpTransceiver<br />import org.apache.avro.generic.GenericData<br />import org.apache.avro.generic.GenericRequestor<br /><br />def avpr = """<br />......<br />"""<br /><br />def proto = Protocol.parse(avpr)<br /><br />def trans = new HttpTransceiver(new URL('http://localhost:8080'))<br />def req = new GenericRequestor(proto, trans)<br />def message = new GenericData.Record(proto.getType('Message'))<br />message.put('to', new Utf8('wei'))<br />message.put('from', new Utf8('tcc'))<br />message.put('body', new Utf8('Hello 123'))<br />def params = new GenericData.Record(proto.messages.send.request);<br />params.put('message', message)<br />def ret = req.request('send', params)<br />println "Result: " + ret<br /></pre><br />其中 import 群下的 def avpr = """......""" 是把 src/avro/mail.avpr 定義的通訊協定拷貝進去。<br /><br />如果不想用嵌入式, 可改為類似 python 範例中的:<br /><pre name="code" class="java">def proto = Protocol.parse(new File('../avro/mail.avpr'))<br /></pre><br />再做 Groovy 的 Server:<br /><pre name="code" class="java">import org.apache.avro.Protocol<br />import org.apache.avro.util.Utf8<br />import org.apache.avro.ipc.HttpServer<br />import org.apache.avro.generic.GenericData<br />import org.apache.avro.generic.GenericResponder<br /><br />def avpr = """<br />......<br />"""<br /><br />def proto = Protocol.parse(avpr)<br /><br />class MyResponder extends GenericResponder {<br /> public MyResponder(Protocol proto) {<br /> super(proto)<br /> }<br /> public Object respond(Protocol.Message msg, Object req) {<br /> return new Utf8("""Sent message ${req.message['to']}<br /> from ${req.message['from']}<br /> with body ${req.message['body']}""")<br /> }<br />}<br />def res = new MyResponder(proto)<br /><br />new HttpServer(res, 8080)<br /></pre><br />其中 respond(Protocol.Message msg, Object req) 的 req 為 GenericData.Record 在 Groovy 利用 GPath 直接操作相當便利。但客戶端用 GenericData 組成看起來頗辛苦, 想改用 Groovy <a href="http://groovy.codehaus.org/Builders">Builder</a> 式:<br /><pre name="code" class="java">avro_builder.send { request {<br /> message(to:'wei', from:'tcc', body:'Hello 123')<br />}}<br /></pre><br />寫個 AvroGroovyBuilder.java 放在 <a href="http://github.com/tcc/clippings/blob/master/AvroGroovyBuilder.java">github</a>。 (注意: 目前沒處理 List)<br /><br />使用端就可簡化成為:<br /><pre name="code" class="java">import org.apache.avro.Protocol<br />import org.apache.avro.ipc.HttpTransceiver<br />import org.apache.avro.generic.GenericRequestor<br /><br />def avpr = """<br />......<br />"""<br /><br />def proto = Protocol.parse(avpr)<br /><br />def trans = new HttpTransceiver(new URL('http://localhost:8080'))<br />def req = new GenericRequestor(proto, trans)<br />def avro_builder = new org.tcchou.groovy.AvroGroovyBuilder(proto)<br />avro_builder.send { request {<br /> message(to:'wei', from:'tcc', body:'Hello 123')<br />}}<br />def ret = req.request('send', avro_builder.params)<br />println "Result: " + ret<br /></pre>tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-20447308827265927062010-08-10T16:36:00.003+08:002010-08-10T16:41:04.280+08:00Jailer 的使用經常與資料庫為伍的開發者來說, 雖然 ORM 的普及解決大部分與 DB 溝通的問題, 但屬於型態上的。特別是常見的資訊系統, 很多工作直接與資料相關, 缺少實際資料根本是無以為繼。<br /><br />以生產系統為例, 產品料表、流程定義與處置資料分由不同部門負責, 即便開發新的或調整 B2B, 缺乏這些資料還是無從下手。縱使 SA/SD 幾個單位走完, 最末還是要這些資料才好開工。<br /><br />經歷過專案時程是上游廠商壓下游, 雛型只做一個段落就直接在正式環境運作 ... 邊進行、邊修程式、邊改資料的歲月真是折磨人。<br /><br />前一陣子瀏覽到 <a href="http://jailer.sf.net">http://jailer.sf.net</a> 就看它閃耀著光輝。與資料整合(Data Integration)或 ETL 工具相比較, 這些傢私可能過大而不合用。<br /><br />因為 jailer 只要關注兩件事: 首先定義表格(Tables)的相關性; 再來是抽取資料的條件。至於表格本身的定義 jailer 可抽取出來, 關連性雖然原則上可由鍵值決定, 但 jailer 也提供人工設定關連, 這點相當符合一般需求。<br /><br />舉例來說 Order(1) -> Batch(N) ... 訂單關連到投產批是 1:N 關係; Batch(1) -> Job(N) ... 投產批與生產批也是 1:N 關係。其他與流程、處置、記錄相關資料零零總總, 這些關連都事先定義妥(大約有 10+ 個表格的關係)。日後只要指定投產批號, 就可拿到所有相關表格資料, 相當方便。<br /><br />拿到資料的方式, 可選擇 SQL 直入測試資料庫; 或產生 Flat XML 與 <a href="http://www.dbunit.org">http://www.dbunit.org</a> 搭配使用。tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-4205544803620074622010-05-06T21:28:00.001+08:002010-05-06T21:28:28.419+08:00Closure under Groovy<pre name="code" class="java"><br /> // using closure under groovy <br /> // to display all contains in directory<br /> def getFiles = { dir, rtn -><br /> dir.listFiles().each { file -><br /> if (file.isDirectory()) {<br /> getFiles(file, rtn)<br /> } else {<br /> rtn.call(file) // action<br /> }<br /> }<br /> }<br /><br /> <br /> getFiles(new File('/Users/tcchou/Desktop/ewtek'), { file -><br /> println file.getAbsolutePath()<br /> })<br /></pre><br />tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-9153935577793132492009-05-13T02:35:00.000+08:002009-05-13T02:36:46.821+08:00近未來 IT 程式開發今年初(2009)看到 InfoQ 上匯集 <a href="http://www.infoq.com/news/2008/12/Top-InfoQ-News-2008">2008 年度文章</a>, 其中一篇 JRuby 開發者之一 <a href="http://olabini.com/blog/">Ola Bini</a> 先生的相關文章 "<a href="http://www.infoq.com/news/2008/01/languages-in-future-systems">Programming languages in future systems</a>" , 將應用系統用到的語言類型分為三層, 印象很深刻 ... 因為幾乎花整個 2008 年的時間打造這樣的系統 ... 在讀到文章之前, 做起來不盡相同。在案子完成之際, 借用相似標題記錄一下這個過程。<br /><br />大多數 IT 相關系統, 都是處理資料 ... 絕大部分的人都會同意這是領域(domain)主導, 不是技術主導。在一些廠商強力運作下, 開發人員近乎被催眠在執行一些固定工作 ... 選用主流技術(沒人喜歡意外), 然後踏上規劃, 分析, 設計, 實作, 測試, ... 的履帶。<br /><br />在專案執行之前, 有 IT 主要廠商已下海幾年宣告失敗 ... 就不得不審視一些基本問題:<ol><li>這是一個財務資訊系統 (AIS, Accouting Information System) 主要得完成 "成本系統" ... 屬資料市集 (Data Mart) 規模, 資料變異不大但資料量大。</li><br /><li>使用者都全天候使用, 需求經常性改變 ... 使用角色的人數約開發者的 5 倍。</li><br /><li>之前系統是 dbase 系, 因為原廠不支持, 決定換 Java。要接手的 IT 部門沒人有經驗 ...</li></ol><br />審視第一點 ... 之前也習慣用 ORM, 但時薪較我日薪還高的廠商都搞不定的資料量 ... 立馬決定透過 SQL 把資料處理的問題都丟給資料庫, 捨棄物件導向方式。<br /><br />關於第二點 ... 全天候使用, 帶給系統更大的壓力。而需求改變, 更是許多系統不穩定的致命一擊。但揉合這兩個問題, 使用腳本(Scripting)語言達成快速變更, 測試就交給使用者(與開發人員關係良好) ... 原則上是這樣, 還有一些方式, 下段再述。<br /><br />而最末一點 ... 要從頭學習 Java, 並好好發揮不是每個人都辦得到。但主要是匯入/匯出、維護/查找資料、檢核、計算、報表、傳票 ... 這幾件事,大致就是 SQL 加上個別功能就收工。後來都是 SQL 測試完成後, 再用樣板(template)套入功能 ... 大約可完成八、九成工作。<br /><br />以技術拆解來看是: SQL + 腳本語言 + 功能模組樣板 ... 有人認為 Java 可達成, 的確也是。但 Java 的問題在於, 直接放 SQL 勢必會分段(SQL 都是長得誇張), 再加上變數會更亂; 而做成獨立檔案(iBatis 做法), 或 Stored Procedure 或 View, 造成非功能性分割, 竊認為是修改應用程式不易的禍首。<br /><br />使用腳本語言就一個功能一個檔, 很直覺, 清清處處 ... 開發過程曾有 SQL 部份算式要改, 還是使用者(只會 SQL 查資料)直接指出哪邊要改。<br /><br />專案開始(2007年中), 就決定使用<a href="http://groovy.codehaus.org/">Groovy</a>, 即便用過 jython, 當時也較成熟; 而 jruby 如日中天 ... 但偏好 Groovy 補 Java 不足的角度, 特別是支援類似 python 三引號(triple-quotes)的樣板字串(template string), 可直接寫 SQL 再加上需要的變數、函式都很容易 ... 除了 Groovy 本身支援的 SQL, 後來也嵌入<a href="http://en.wikipedia.org/wiki/Extended_Backus-Naur_form">EBNF</a> 的語法描述, 再來做 DSL 處理也很方便。<br /><br />回頭看打造的系統與 Ola Bini 先生宣告三層類型的對應:<ol><li>穩定層(Stable layer): 沒與應用太多相關, 以靜態語言打造 ... Groovy 程式的載入、執行都是用 Java 寫的。</li><br /><li>動態層(Dynamic layer): 與應用相關, 以動態語言打造 ... 功能模組樣板(匯入/匯出, 檢核, 計算, ...), 都是用 Groovy 寫的 ... 像報表小計方式百百種, 都一一解決。</li><br /><li>領域層(Domain layer): 與應用相關, 以領域語言打造 ... 使用 SQL + Groovy 方式, 大抵 SQL 能動就了結。</li></ol><br />其文中提到的 Drools 也有用到, 因為決策表格(Decision Table)對使用者更容易使用 ... 也在此做證言 :-)tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0tag:blogger.com,1999:blog-9590240.post-31638813627174686242009-04-16T06:58:00.000+08:002009-04-16T09:13:39.761+08:00OmniOutliner to BloggerOOblogger 沿自 <a href="http://www.omnigroup.com/applications/omnioutliner/extras/">Helpify</a>, 讓 OmniOutliner 的文章轉成 Blogger 可收的格式。<br /><br />自從把網誌搬來 Blogger, 遇到一些撰寫障礙 ... 雖然原本產量就很低 ...<br /><br />只是要寫有圖、連接的文章, 即便 Blogger 線上編輯器功能完備。但放在別人家裡, 沒什麼安全感。試了一些方式:<ol><li>網誌專用編輯器 ... 寫條列式, 轉到 blogger 都會變得很糟, 多幾階就全亂了。</li><li>書寫工具轉 HTML 檔 ... 大多附 CSS 或轉成復雜的 HTML, 放到 blogger 也是不太合。</li><li>用 Markdown 撰寫 ... 人工管理文、圖蠻辛苦的 ... 得做蠻多額外工作。</li></ol>期間看到 <a href="http://github.com/blog/272-github-pages">Github Pages</a> 是很贊的做法, 但太技客式 ... 現在大多用 <a href="http://www.flyingmeat.com/voodoopad/">VoodooPad</a>, <a href="http://www.omnigroup.com/applications/omnioutliner/">OmniOutliner</a>, <a href="http://www.aquaminds.com/">NoteTaker</a> 之類的, 要轉換還是太費工。<br /><br />前幾天在 <a href="http://www.omnigroup.com/">www.omnigroup.com</a> 網站逛, 看到 OO3 的 <a href="http://www.omnigroup.com/applications/omnioutliner/extras/">Extras</a>區有個 Helpify 能將 OO3 格式檔案轉成蘋果的輔助檔。而 OmniOutliner 用來寫長、短文都適宜, 感覺很合用, 動手將 Helpify 改成 Blogger 能吃的格式。<br /><br />Helpify 有兩個特點:<ol><li>轉換來源(OO3 文章)和結果(HTML, CSS, Images 檔案)無關, 大部分能輸出 Web 的書寫工具都儘可能複製原先的風格, 適合單獨存在, 很難塞入 Blogger 能接受的 HTML 格式中。使用 OO3 寫不同類文, 多會設定些不同風格, 透過 Helpify 轉換, 只有內容, 結構, 圖檔, 連結會轉換成 Web (還蠻多的)。</li><li>使用 Helpify 還能加一些特定的處理邏輯, 這是之前用 XSLT (OO3 的 Export 擴充標準)比較難做到的。以 Helpify 本身來說, 會將每個項目區塊轉成獨立檔案。</li></ol>放上這篇文章在 OO3 的快照比較一下:<br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDgbnT3RNhglbtzBNihj-BXg4vVLuBnF87n39p88l-EBSypBaPbboz2LCDRO5fIGjBksnK83ITJn9DZsczrWNI1_jfEGyAzMBQgSv6fhebBxsDD8LURaZ129K7YRve_kyo1FEk7w/s1600-h/ooblogger.png"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDgbnT3RNhglbtzBNihj-BXg4vVLuBnF87n39p88l-EBSypBaPbboz2LCDRO5fIGjBksnK83ITJn9DZsczrWNI1_jfEGyAzMBQgSv6fhebBxsDD8LURaZ129K7YRve_kyo1FEk7w/s320/ooblogger.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5325065014852728930" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 320px; height: 300px; " /></a></div><br />修改後的 OOblogger 放在 <a href="http://github.com/tcc/clippings/blob/021b2fe073095f9f32181d57a7626d3c9475369c/OOblogger.py">Github</a>。現在還要手工剪貼到 Blogger, 再找時間做上傳 ...tcchouhttp://www.blogger.com/profile/07117873012316262531noreply@blogger.com0