<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JeffHung.Blog &#187; development</title>
	<atom:link href="http://www.jeffhung.net/blog/categories/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jeffhung.net/blog</link>
	<description>(My smile insists of having nose. :-)</description>
	<lastBuildDate>Thu, 24 Nov 2011 07:25:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2-alpha</generator>
		<item>
		<title>徵 Web Front-end Developer</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/3235/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/3235/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 07:25:31 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=3235</guid>
		<description><![CDATA[敝部門最近在徵 Web Front-end Developer，歡迎有興趣的人與我聯絡。 先介紹一下敝部門。我現在在趨勢科技 CoreTech Backend 的 SPN team 工作，這個部門的主要工作是構建趨勢雲端防毒的後端基礎建設，處理來自全世界各地反饋回來的各種資料，以 global scale 分析處理，以提出各種反制威脅的解決方案。由於資料量很大，因此敝 team 累積了相當多的 big data 處理經驗，而且面對的是真實的資料，實際的問題，做的絕非假雲端。我們的團隊裡有許多鬼才，信奉 hacker 精神，使用的 open source 技術五花八門，平日常常需要膜拜彼此，因為令人讚嘆的事蹟層出不窮。 不過由於敝 team 擅長的是後端，前端雖然還是能做，但總是不夠專業，因此需要 web front-end 的人才加入，以便真實呈現挖掘自巨量資料的寶貴資訊。為協助在最短的時間內驗證各種解決方案，這個工作會有一部分需要能夠快速建構各種 visualization demonstration。這是個 contractor 或 part-time 職缺，公司內部有專門的 HIE (Human Interface Engineering) 部門，有志於 front-end 專長的人，將不乏於此發展個人職涯的機會。 工作的地點在台北敦化南路，上班時間正常，不常加班。以下為正式的 job description： Overview: Software development for web front-end solution Develop UI [...]]]></description>
			<content:encoded><![CDATA[<p>敝部門最近在徵 Web Front-end Developer，歡迎有興趣的人與我聯絡。</p>
<p>先介紹一下敝部門。我現在在趨勢科技 CoreTech Backend 的 SPN team 工作，這個部門的主要工作是構建趨勢雲端防毒的後端基礎建設，處理來自全世界各地反饋回來的各種資料，以 global scale 分析處理，以提出各種反制威脅的解決方案。由於資料量很大，因此敝 team 累積了相當多的 big data 處理經驗，而且面對的是真實的資料，實際的問題，做的絕非假雲端。我們的團隊裡有許多鬼才，信奉 hacker 精神，使用的 open source 技術五花八門，平日常常需要膜拜彼此，因為令人讚嘆的事蹟層出不窮。</p>
<p>不過由於敝 team 擅長的是後端，前端雖然還是能做，但總是不夠專業，因此需要 web front-end 的人才加入，以便真實呈現挖掘自巨量資料的寶貴資訊。為協助在最短的時間內驗證各種解決方案，這個工作會有一部分需要能夠快速建構各種 visualization demonstration。這是個 contractor 或 part-time 職缺，公司內部有專門的 HIE (Human Interface Engineering) 部門，有志於 front-end 專長的人，將不乏於此發展個人職涯的機會。</p>
<p>工作的地點在台北敦化南路，上班時間正常，不常加班。以下為正式的 job description：</p>
<blockquote>
<p>Overview:</p>
<ul>
<li>Software development for web front-end solution</li>
<li>Develop UI prototypes to demonstrate concepts</li>
<li>Web application design, implementation, unit testing and trouble shooting</li>
</ul>
<p>Qualification/Requirement:</p>
<ul>
<li>3+ years experience of web front-end design and development</li>
<li>Solid JavaScript programming and familiar with DHTML, CSS, XML, JSON, AJAX, and Flex</li>
<li>Experienced in new web technologies, like Django, jQuery, Ruby and Structs</li>
<li>Experienced in server side scripting with PHP/ASP/JSP will be a plus</li>
<li>Good English communication skill</li>
<li>Self-motivated, good teamwork and problem solving skill</li>
</ul>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/3235/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[OSDC.tw 2011] The Path to Pass into PaaS</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/3163/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/3163/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 15:43:38 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=3163</guid>
		<description><![CDATA[今天在 OSDC.tw 2011 裡講了一場，介紹我們 team 做的東西...]]></description>
			<content:encoded><![CDATA[<p>今天在 OSDC.tw 2011 裡講了一場，介紹我們 team 做的東西，投影片如下：</p>
<div style="width:425px" id="__ss_7402138"> <strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/jeffhung/osdctw-2011-the-path-to-pass-into-paas" title="[OSDC.tw 2011] The Path to Pass into PaaS">[OSDC.tw 2011] The Path to Pass into PaaS</a></strong> <object id="__sse7402138" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=osdc-tw-2011-thepathtopassintopaas-110326213502-phpapp02&#038;stripped_title=osdctw-2011-the-path-to-pass-into-paas&#038;userName=jeffhung" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse7402138" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=osdc-tw-2011-thepathtopassintopaas-110326213502-phpapp02&#038;stripped_title=osdctw-2011-the-path-to-pass-into-paas&#038;userName=jeffhung" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object> </div>
<p>嗯，總算在 blog 上塞點有用的東西。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/3163/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>醫生扮演組</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/3132/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/3132/#comments</comments>
		<pubDate>Fri, 03 Dec 2010 04:38:42 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=3132</guid>
		<description><![CDATA[拿著巧虎醫生扮演組，玩得不亦樂乎的紅蘿蔔，突然轉頭...]]></description>
			<content:encoded><![CDATA[<p>雖然已經<a href="http://www.plurk.com/p/9b0nkz">發了 plurk</a>，還是在 blog 裡記錄一下好了，免得紅蘿蔔長大後不認帳。:-p</p>
<p>拿著巧虎醫生扮演組，玩得不亦樂乎的紅蘿蔔，突然轉頭，拿瓶藥水給我，對我說：「把拔，這個毒藥給你喝。」</p>
<p>我：「........」</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/3132/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>亂數兩三事</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/3036/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/3036/#comments</comments>
		<pubDate>Sun, 20 Jun 2010 16:25:12 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=3036</guid>
		<description><![CDATA[剛好在 Plurk 上聊到亂數的問題：我印象中 Standard C 的 srand()、rand() 函式，有大問題，所以在 Plurk 上亂放炮，引來眾家好手關切。還好最後把細節回憶清楚了，也再次提醒了自己，要小心不要讓寫程式的「習慣」埋下難解的地雷。]]></description>
			<content:encoded><![CDATA[<p>是亂數兩三事，也是亂述兩三事。剛好在 Plurk 上<a href="http://www.plurk.com/p/5nebqt">聊</a>到亂數的問題：我印象中 Standard C 的 <code class="inline_code">srand()</code>、<code class="inline_code">rand()</code> 函式，有大問題，所以在 Plurk 上亂放炮，引來眾家好手關切。還好最後把細節回憶清楚了，也再次提醒了自己，要小心不要讓寫程式的「習慣」埋下難解的地雷。</p>
<p>故事是這樣的，在之前開發某分散式系統時，為了避免系統啟動時，因為散布在多台機器的許多程式，一起同時運作而造成塞車，所以套用 <a href="http://en.wikipedia.org/wiki/Carrier_sense_multiple_access_with_collision_detection">CSMA/CD</a> 的招數，讓大家在啟動時，各自暫停若干時間，暫停的長度由亂數決定。</p>
<p>不過，因為 Standard C 的 <code class="inline_code">srand()</code>、<code class="inline_code">rand()</code> 係 pseudo random 的關係，只要給 <code class="inline_code">srand()</code> 的值一樣，之後大家所 <code class="inline_code">rand()</code> 得到的 sequence 都會一樣。大部份的教科書，在介紹這兩個函式的時候，大都是用 <code class="inline_code">time()</code> 取得當前 epoch 秒數喂進 <code class="inline_code">srand()</code>，所以如訓練有術的狗一般，我也很直覺的就用同一個方法設定亂數種子值。然後很不幸地，當所有程式同時啟動時，因為呼叫 <code class="inline_code">time()</code> 的時間非常接近，所以傳進 <code class="inline_code">srand()</code> 的數值，也幾乎一模一樣，導至這整招失效。而且因為 random sequence 一模一樣，所以後面的動作都非常「synchronize」，效率可想而知。</p>
<p>我那時的解法是，乾脆進而撰寫了 <code class="inline_code">device_random_generator</code> 與 <code class="inline_code">guid_random_generator</code> 來使用，前者直接利用硬體手法取得亂數值，後者仰賴了 GUID 的產生，有一部份是亂數的結果。</p>
<p>但若嫌麻煩，使用 avhacker 或 sorry 提的，用更精確的時間，或把 Process ID、Thread ID 等一起參作伙做撒尿魚丸，來得到亂數種子值，都是簡便但可行的好方法。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/3036/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Join 地獄</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/3021/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/3021/#comments</comments>
		<pubDate>Fri, 21 May 2010 09:18:25 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=3021</guid>
		<description><![CDATA[標題有雙關。XD 我們小組所負責的某模組的 database schema，原本只有兩個 table，送出去與整個 team 所有模組的 database schema 整合後，事情變成： 模組裡最會被頻繁使用的 API，所需要下的 SQL query，需要 join 達 8 個 tables，才能拿到我們需要的資訊。若還要驗證輸入的參數是否正確，則還需要再多 join 一個，共 9 個 tables。 這個世界真是美妙啊。]]></description>
			<content:encoded><![CDATA[<p>標題有雙關。XD</p>
<p>我們小組所負責的某模組的 database schema，原本只有兩個 table，送出去與整個 team 所有模組的 database schema 整合後，事情變成：</p>
<p>模組裡最會被頻繁使用的 API，所需要下的 SQL query，需要 join 達 8 個 tables，才能拿到我們需要的資訊。若還要驗證輸入的參數是否正確，則還需要再多 join 一個，共 9 個 tables。</p>
<p>這個世界真是美妙啊。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/3021/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Letting va_list re-entraint by va_copy()</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2954/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2954/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 15:38:01 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2954</guid>
		<description><![CDATA[之前在這篇《Non-standard behavior of (v)snprintf, on Visual C++》探究過 strprintf() 的實作方法。那時我以為已經找到終極解法，僅需為每個不符合標準的平台，製作 work around 即可。不過最近將這些程式搬到 Mac OS X 上面，卻連連接到 Segment Fault，才知道其實我的 strprintf() 還有缺陷，導因於我的無知與疏忽。]]></description>
			<content:encoded><![CDATA[<p>之前在這篇《<a href="http://www.jeffhung.net/blog/articles/jeffhung/1064/">Non-standard behavior of (v)snprintf, on Visual C++</a>》探究過 <code class="inline_code">strprintf()</code> 的實作方法。那時我以為已經找到終極解法，僅需為每個不符合標準的平台，製作 work around 即可。不過最近將這些程式搬到 Mac OS X 上面，卻連連接到 <a href="http://en.wikipedia.org/wiki/Segmentation_fault">Segment Fault</a>，才知道其實我的 <code class="inline_code">strprintf()</code> 還有缺陷，導因於我的無知與疏忽。</p>
<p>拿該篇最後一個版本的程式，在 Mac OS X 10.6 (Snow Leopard) 上面編譯執行，會得到下列的輸出結果：</p>
<pre class="screen">
SHELL&gt; ./a.out
[DEBUG] pbuf_size == 16
[DEBUG] len == 13
[DEBUG] {13} Hello, sign!
Hello, sign!
[DEBUG] pbuf_size == 16
[DEBUG] len == 17
[DEBUG] pbuf_size == 18
[DEBUG] len == 26
[DEBUG] pbuf_size == 27
[DEBUG] len == 15
[DEBUG] {15} Hello, (null)!
[DEBUG] free pbuf
Hello, (null)!
[DEBUG] pbuf_size == 16
[DEBUG] len == 36
[DEBUG] pbuf_size == 37
[DEBUG] len == 9
[DEBUG] {9} Hello, !
[DEBUG] free pbuf
Hello, !
</pre>
<p>這個結果，很顯然地，並不正確。起先我以為是 Mac OS X 的 <code class="inline_code">vsnprintf()</code> 和 Windows 平台一樣，不符合 C99 標準。不過驗證的結果卻非如此。幾經波折，再加上空閒很少，拖了好久我才注意到，上列輸出裡，第二輪預期結果為 <code class="inline_code">&quot;Hello, jeffhung!&quot;</code> 的測試，其 <code class="inline_code">len</code> 值起先為正確的 <code class="inline_code">17</code>，後來卻變成了 <code class="inline_code">26</code> 與 <code class="inline_code">15</code>。這個差異，讓我注意到，我這段程式，居然只有一個 <code class="inline_code">va_start()</code>，而沒有 <code class="inline_code">va_end()</code>。</p>
<p>見鬼，真是見鬼！！居然犯這種低級錯誤，我羞愧到極點，想要鑽到土裡去。不過，還好趕緊檢查所有我寫的相關程式庫，都沒有這種少掉 <code class="inline_code">va_end()</code> 的錯誤，只能算是當初寫文章時，準備範例程式不夠嚴謹。</p>
<p>但是將 <code class="inline_code">va_end()</code> 補在函式後面後，卻仍然產生同樣的錯誤輸出，讓我百思不得其解。測試後發現，要將 <code class="inline_code">va_start()</code> 與 <code class="inline_code">va_end()</code> 包在 <code class="inline_code">vsnprintf()</code> 前後才行。也就是說，每次將 <code class="inline_code">va_list</code> 變數送進去給 <code class="inline_code">vsnprintf()</code> 用之前，都要重新用 <code class="inline_code">va_start()</code> 初始化一次。這不禁讓我懷疑，<code class="inline_code">va_list</code> 變數，是 non-reentraint 的。</p>
<p>翻查 C99 標準，在 7.15.3 節裡找到這句：</p>
<blockquote>
<p>The object <code class="inline_code">ap</code> may be passed as an argument to another function; if that function invokes the <code class="inline_code">va_arg</code> macro with parameter <code class="inline_code">ap</code>, the value of <code class="inline_code">ap</code> in the calling function is indeterminate and shall be passed to the <code class="inline_code">va_end</code> macro prior to any further reference to <code class="inline_code">ap</code>.<sup>212)</sup></p>
<p><small>212) It is permitted to create a pointer to a <code class="inline_code">va_list</code> and pass that pointer to another function, in which case the original function may make further use of the original list after the other function returns.</small></p>
</blockquote>
<p>這證實了我的想法。另外，原來還有 <code class="inline_code">va_copy()</code> 這個 macro，以便在自己寫的，直接收一個 <code class="inline_code">va_list</code> 變數而非 <code class="inline_code">...</code> 的 <code class="inline_code">v</code> 系列函式，複製 <code class="inline_code">va_list</code> 變數好重覆使用。再依據 C99 標準裡第 7.15.1.1 節的說法：</p>
<blockquote>
<p>Each invocation of the <code class="inline_code">va_start</code> and <code class="inline_code">va_copy</code> macros shall be matched by a corresponding invocation of the <code class="inline_code">va_end </code>macro in the same function.</p>
</blockquote>
<p>得知自製 <code class="inline_code">v</code> 系列函式時，若收到的 <code class="inline_code">va_list</code> 變數會不只用到一次，如再傳給 <code class="inline_code">vsnprintf()</code> 很多次，則最好每次都用 <code class="inline_code">va_copy()</code> 製作複本，使用這個複本，並馬上利用 <code class="inline_code">va_end()</code> 銷毀之。</p>
<p>雖然說我之前寫的相關程式庫，並沒有犯少了 <code class="inline_code">va_end()</code> 的低級錯誤，但一樣還是沒有注意到這個 reentraint 的問題。還好在所 target 的平台，實際上並不會造成影響，隨附的 test cases 的成功執行，也都確保了這點。不過，這種 non portable issue，還是地雷一枚。寫出這種程式，慚愧啊慚愧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2954/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Subversion export remotely with uninstalled svn-rexport.sh</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2905/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2905/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 18:24:40 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2905</guid>
		<description><![CDATA[Subversion 採用了許多成熟的程式庫，這種模組化的設計，使其可以專注在版本控制的核心問題上，而不必與如 portability 等問題打交道。然而，若我們想要在全心安裝的系統裡，儘快開始使用 Subversion 的話，這種設計，就會因為 dependency 太多，產生許多安裝時的麻煩。這些麻煩，在當我們開始將許多軟體的設定檔，放進 repository 之後，更容易造成 bootstrapping 的問題。]]></description>
			<content:encoded><![CDATA[<p>Subversion 採用了許多成熟的程式庫，這種模組化的設計，使其可以專注在版本控制的核心問題上，而不必與如 portability 等問題打交道。然而，若我們想要在全心安裝的系統裡，儘快開始使用 Subversion 的話，這種設計，就會因為 dependency 太多，產生許多安裝時的麻煩。這些麻煩，在當我們開始將許多軟體的設定檔，放進 repository 之後，更容易造成 bootstrapping 的問題。</p>
<p>例如，Subversion 相依於 Apache，而我對於 <code class="inline_code">www/apache22</code>，亦有一套針對自己喜好的設定，這些設定會存放於 Subversion 裡做版本控制。裝新機時，直接從 Subversion 裡拿出設定檔，即可將系統安裝成我慣用的樣子。然而，以上實際上是個雞生蛋、蛋生雞的問題：在裝 <code class="inline_code">www/apache22</code> 之前，沒辦法安裝 <code class="inline_code">devel/subversion</code>，但我又需要 <code class="inline_code">devel/subversion</code>，以便取得放在 repository 裡，用來設定 <code class="inline_code">www/apache22</code> 的選項。</p>
<p>為了解決這個問題，要不是得先用預設選項，裝一組陽春的 <code class="inline_code">www/apache22</code> 與 <code class="inline_code">devel/subversion</code>，起出設定選項之後，再整個砍掉重練一次；要不就得利用其它機器，取得設定檔。前者太過麻煩，所以我通常是用後者。</p>
<p>但後者其實還是很麻煩，因此，如果有個機制，可以讓我不必安裝 Subversion，就可以取得 <code class="inline_code">svn export</code> 出的內容，那整件事情就容易許多了。因為我有寫 install script，所以若有這個機制，整個 deploy 過程，就可以用兩個指令搞定：</p>
<ol>
<li>利用這個機制，取出最新版的設定；</li>
<li>執行 install script，會將整個環境設定成我慣用的樣子，所有設定檔皆安裝至定位。</li>
</ol>
<p>所以，問題來了，怎樣在本機尚未安裝 Subversion 的情況下，透過另一台機器，取得 repository 內容？甚至，做這件事的程式，如果不必先安裝在本機，那更好。於是，我發現我搞出了 <code class="inline_code">svn-rexport.sh</code> 這個 script。這個 script 的用法很特別，其 usage 為 (後略)：</p>
<pre class="code">
Usage: ssh [USER@]HOST svn-rexport.sh [OPTIONS...] URL [PATH] | sh -s
</pre>
<p>流程為：</p>
<ol>
<li>透過 ssh 到另一台遠端機器裡執行安裝在那台機器上的 <code class="inline_code">svn-rexport.sh</code>，因此，我們無須在本機安裝 <code class="inline_code">svn-rexport.sh</code>。</li>
<li>接著，在遠端執行的 <code class="inline_code">svn-rexport.sh</code>，會依據 command-line 參數，將由 URL 指定的 repository 內容，export 出來。</li>
<li>起出內容之後，用 <a href="http://www.freebsd.org/cgi/man.cgi?query=shar"><code class="inline_code">shar</code>(1)</a> 包裝，寫到 <code class="inline_code">stdout</code>。</li>
<li>由 <code class="inline_code">svn-rexport.sh</code> 在遠端機器輸出的 shar 檔內容，會透過 SSH 送回本機，此時用 pipe 導到每台 UNIX 都有的 bourne shell (<code class="inline_code">sh</code>)，令 <code class="inline_code">sh</code> 從 <code class="inline_code">stdin</code> 讀入要執行的內容並執行之。</li>
<li>因為 sh 所執行的內容，格式為 shar，相當於解開這個 shar-ball，於是就在本機裡，將我們所需要的 repository 內容，解開置放於目前目錄下。</li>
</ol>
<p>然後，我就可以執行 install script，將慣用的環境 deploy 出來。整個機制，在本機端，只需要有 <code class="inline_code">ssh</code> 與 <code class="inline_code">sh</code> 兩個指令即可。</p>
<p>以上，實在是太邪惡了啊，不過，的確是替我節省了很多時間，讓我隨時可以開個 VM，兩、三動裡，就可以重現我慣用的開發環境，十分方便。程式碼放在 <a href="http://gist.github.com/312523">gist:312523 (<code class="inline_code">svn-rexport.sh</code>)</a>，以下為完整的 usage message：</p>
<pre class="screen">
Usage: ssh [USER@]HOST svn-rexport.sh [OPTIONS...] URL [PATH] | sh -s

Export Subversion URL in remote host and extract to local PATH&gt;, even without
this script.  Assuming this script is already deployed in HOST, and USER can
run Subversion commands non-interactively in HOST.  This command will run this
script in HOST as USER, export from Subversion URL, pack as shar(1) ball, send
back via ssh(1), and extract locally to PATH.

Alternatively, we can specify USER@HOST via --connect option if we have this
script deployed in local machine.  When --connect is specified, we should run
this script locally. This script will manipulate all of above via ssh(1).

Options:

  -h,--help                 Show this help message.
  -u,--username USERNAME    Use USERNAME to login to Subversion repository.
  -p,--password PASSWORD    Use PASSWORD to login to Subversion repository.
                            (USERNAME and PASSWORD are required if these is no
                            credentials cached in USER@HOST, since Subversion
                            command will be ran non-interactively.)
  -c,--connect [USER@]HOST  When run this script locally with this option,
                            will connect to USER@HOST via ssh(1) to export URL
                            to local PATH.  (USER default to $USER).
  -r,--revision REV         Use REV as the Subversion revision argument.
  -v,--verbose              Show verbose messages.

Example:

  - Run remotely: will run this script in HOST as USER, export from Subversion
    URL, pack as shar(1) ball, send back via ssh(1), and extract locally to PATH.

    SHELL&gt; ssh USER@HOST svn-rexport.sh http://foo.com/svn/ bar | sh -s

  - Run locally: will execute subversion command remotely via ssh(1).

    SHELL&gt; svn-rexport.sh --connect user@foo.com http://foo.com/svn/ bar

Revision: r578 (2010-02-24)
</pre>
<p>噢，對，<code class="inline_code">--connect</code> 還沒做。:-p</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2905/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Readability and iPhone Bookmarklets</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2849/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2849/#comments</comments>
		<pubDate>Sun, 07 Feb 2010 03:27:14 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2849</guid>
		<description><![CDATA[僅管 Safari for iPhone 這點已經做的很好，雙點文章就可以將網頁縮放到，剛好閱讀視野 (view port) 是所點擊的文章區塊的寬度，但碰上段落寬度過大的網頁的時候，因為沒有像古代那樣重新排版 (reflow) 過，所以字型反而會小到看不清楚，無法閱讀。最近看到看到 gugod 的介紹：《Readibility: 發人省思的 Bookmarklet》，就覺得這實在就是解決段落過寬的好方法。]]></description>
			<content:encoded><![CDATA[<p>僅管 Safari for iPhone 這點已經做的很好，雙點文章就可以將網頁縮放到，剛好閱讀視野 (view port) 是所點擊的文章區塊的寬度，但碰上段落寬度過大的網頁的時候，因為沒有像古代那樣重新排版 (reflow) 過，所以字型反而會小到看不清楚，無法閱讀。最近看到看到 gugod 的介紹：《<a href="http://gugod.org/2010/02/readibility-bookmarklet.html">Readibility:  發人省思的 Bookmarklet</a>》，就覺得這實在就是解決段落過寬的好方法。</p>
<p>經過測試，我喜歡將 <a href="http://lab.arc90.com/experiments/readability/">Readability</a> 設定成使用 eBook 字型，large 字體大小，以及 wide 邊界。</p>
<p>可是，在 iPhone 上要收錄 <a href="http://en.wikipedia.org/wiki/Bookmarklet">bookmarklet</a> 實在是很麻煩，要先找個地方把 bookmarklet 串在正常的 link 後用 <code class="inline_code">#</code> 隔開，收錄書簽之後，再編輯之將 <code class="inline_code">#</code> 之前的部份刪除。「還要再編輯」這問題不大，比較麻煩的是，往往必須依靠 desktop 的幫忙，才能「修改 bookmarklet，偽裝成正常的 URL，並找個地方置放」。</p>
<p>為了解決這個問題，於是找到了《<a href="http://dpatrickcaldwell.blogspot.com/2009/08/iphone-bookmarklet-to-install-iphone_06.html">iPhone Bookmarklet to Install iPhone Bookmarklets</a>》這篇文章。這篇文章所提供的這個 bookmarklet 真是幹的好啊，直接用 bookmarklet 即時將頁面裡的所有 link 全都改成「偽裝過的 bookmarklet」的形式，然後我們僅需點觸要收錄的 bookmarklet 鍊結，此時頁面不會變化，但對應的 url 已經變成內含 bookmarklet 的版本。收錄之，然後再把 <code class="inline_code">#</code> 之前的部份刪除，就搞定了。更方便的是，收錄此 bookmarklet 也僅需要先點觸之。</p>
<p>很可惜地，這個 bookmarklet 碰上 Readability 無效，所以只好還是等回到家之後，再來依靠 desktop 幫忙，安裝 Readability。</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2849/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>為了 cvsup 用 socks5 翻牆</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2841/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2841/#comments</comments>
		<pubDate>Sat, 06 Feb 2010 13:57:48 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2841</guid>
		<description><![CDATA[承《為了 git:// 用 tsocks  翻牆》，這回想要 cvsup 結果也被公司防火牆擋住了。因為剛灌好系統什麼都沒有，而 net/tcosks 又相依於若干其它套件，因此這回改用可獨立運作的 net/socks5，以減少要「重來」的部份。]]></description>
			<content:encoded><![CDATA[<p>承《<a href="http://www.jeffhung.net/blog/articles/jeffhung/2708/">為了 <code class="inline_code">git://</code> 用 <code class="inline_code">tsocks</code> 翻牆</a>》，這回想要 cvsup 結果也被公司防火牆擋住了。因為剛灌好系統什麼都沒有，而 <code class="inline_code">net/tcosks</code> 又相依於若干其它套件，因此這回改用可獨立運作的 <code class="inline_code">net/socks5</code>，以減少要「重來」的部份。</p>
<p>一樣使用 SSH 建 tunnel：</p>
<pre class="screen">
SHELL&gt; ssh -D5487 &lt;account&gt;@&lt;server-address&gt;
</pre>
<p>安裝好 net/socks5 之後，建立 <code class="inline_code">/usr/local/etc/libsocks5.conf</code> 檔案設定之：</p>
<pre class="code">
# proxy cmd     host    port    users   proxies
socks5  -       -       -       -       localhost:5487
</pre>
<p>每一行為一個 entry，以空白隔開各欄位，「<code class="inline_code">-</code>」表示 any。更進階的設定法請參照 <code class="inline_code">libsocks5.conf</code>(5)。</p>
<p>使用時，在原來的指令前面，冠以 <code class="inline_code">runsocks</code> 即可。如下：</p>
<pre class="screen">
SHELL&gt; cd /usr/src
SHELL&gt; runsocks make update
</pre>
<p>同事建議，可以改用走 HTTP 的 <code class="inline_code">portsnap</code>(8)，或是 <code class="inline_code">freebsd-update</code>(8) 以 binary 形式升級系統。這倒也是個不錯的辦法，設定好 <code class="inline_code">http_proxy</code> 環境變數即可使用。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2841/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>No way to disable geotag feature in Tweetie 2</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2832/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2832/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 04:22:58 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2832</guid>
		<description><![CDATA[早上在捷運裡，用 iphone 發了一封信到 support@atebits.com，回報 Tweetie 2 for iPhone 的問題...]]></description>
			<content:encoded><![CDATA[<p>早上在捷運裡，用 iPhone 發了一封信到 support@atebits.com，回報 <a href="http://www.atebits.com/tweetie-iphone/">Tweetie 2 for iPhone</a> 的問題：</p>
<blockquote>
<p><strong>No way to disable geotag feature</strong></p>
<p>Hi,</p>
<p>I'm user of tweetie 2 for iPhone. I love this software. However, I'd  like to report a bug (mis design): there's no way to disable geotag  feature.</p>
<p>I like this feature. But I'd like to keep my position in secret most of  the time, and exposing it only when I really want. But, once I enabled  the feature, I no longer can disable it. And, every time I post a twit, a  window pop up asking whether do I allow tweetie to get my current  position. Since most of the time I do not like exposing my position, I  selected No. This always make tweetie fail to get geo info and lead to  another error message window popped up.</p>
<p>The whole process is annoying. But I find no place to disable geotag  feature. I would like tweetie let user choose whether they want the  feature on or off defaultly. If user choose no, geotag can only attached  in twit when user explicitly turned it on. After the twit sent, the  option turn back to No, and user do not need to disable it manually to  prevent unwanted geotag attached in next twit.</p>
<p>Thanks for bringing us this great software. It is really useful. I hope  my suggestion can be adopted and make tweetie better.</p>
<p>Sincerely,<br />
Jeff Hung</p>
<p>Sent from my iPhone</p>
</blockquote>
<p>一分鐘之後，收到系統自動回信，我的 <a href="http://support.atebits.com/discussions/problems/2208-no-way-to-disable-geotag-feature">bug report</a> 已經被登錄在其系統裡了。來等看看幾時可以有回應與解法。</p>
<p>我發現，atebits.com 的問題回應機制設計的挺精妙。support.atebits.com 的 <a href="http://support.atebits.com/discussions/problems">Problems</a> 列表裡只有我那一則問題。該頁裡有這麼一句話：</p>
<blockquote>
<p>This category is private &mdash; new discussions are only visible to the support staff and the original reporter.</p>
</blockquote>
<p>既然我從未在該系統建立過 profile，顯然當初那封系統自動回信給的 URL 裡，所埋的那串 <code class="inline_code">anon_token</code> 另有玄機：當我循著該 URL 造訪時，自動建立了 anonymous profile。如果我繼而選擇建立 profile 時，此 anonymous profile 可以「變身」成「我」，那這整套機制就可說是走通了，帥。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2832/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Untrustable CNNIC SSL CA</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2804/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2804/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 12:31:23 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2804</guid>
		<description><![CDATA[最近 CNNIC 的 SSL CA (Certificate Authority) 被納入 Firefox 與各大系統的 Root CA，引起熱烈討論。沒空追蹤這個事件，以下僅簡介其危險，與暫時解法： CNNIC 就跟 TWNIC 一樣，是國家級的網路管理中心，主要負責如 domain registration 業務。雖然 CNNIC 號稱是非營利組織，但實際上對於豎立 GFW 之中國政府的各項要求，沒有能力拒絕。事實上，CNNIC 也幹過，發佈內含流氓軟件功能，且使用者無法刪除的中文上網官方版軟體這種事。 由於 CNNIC SSL CA 被納入 Root CA，依據 SSL CA 的階層式信任的架構，CNNIC 隨時可以發佈假的 CA，進行 SSL MITM (Man-In-The-Middle) 攻擊。這個意思是說，當你從境外連結中國境內的網站，透過 SSL 登入該網站系統時，即使瀏覽器顯示此 SSL 安全連線安全無虞，但實際上因為假的 CA 之故，很有可能連到的實際上是個釣魚網站 (DNS hijacking 是中國 GFW 常用的技倆)。因此，你的帳號密碼，就會被竊取；而如果這密碼是平常常用的密碼，那你所有平常用的資訊服務，盡皆淪陷。 另一種更可能的情境是，在中國境內連 Gmail 時，由於 CNNIC [...]]]></description>
			<content:encoded><![CDATA[<p>最近 CNNIC 的 SSL CA (Certificate Authority) 被納入 Firefox 與各大系統的 Root CA，引起熱烈討論。沒空追蹤這個事件，以下僅簡介其危險，與暫時解法：</p>
<p>CNNIC 就跟 TWNIC 一樣，是國家級的網路管理中心，主要負責如 domain registration 業務。雖然 CNNIC 號稱是非營利組織，但實際上對於豎立 <a href="http://en.wikipedia.org/wiki/Golden_Shield_Project">GFW</a> 之中國政府的各項要求，沒有能力拒絕。事實上，CNNIC 也幹過，發佈內含流氓軟件功能，且使用者無法刪除的<a href="http://zh.wikipedia.org/wiki/%E4%B8%AD%E6%96%87%E4%B8%8A%E7%B6%B2%E5%AE%98%E6%96%B9%E7%89%88%E8%BB%9F%E9%AB%94">中文上網官方版軟體</a>這種事。</p>
<p>由於 CNNIC SSL CA 被納入 Root CA，依據 SSL CA 的階層式信任的架構，CNNIC 隨時可以發佈假的 CA，進行 SSL <a href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">MITM (Man-In-The-Middle)</a> 攻擊。這個意思是說，當你從境外連結中國境內的網站，透過 SSL 登入該網站系統時，即使瀏覽器顯示此 SSL 安全連線安全無虞，但實際上因為假的 CA 之故，很有可能連到的實際上是個釣魚網站 (<a href="http://en.wikipedia.org/wiki/DNS_hijacking">DNS hijacking</a> 是中國 GFW 常用的技倆)。因此，你的帳號密碼，就會被竊取；而如果這密碼是平常常用的密碼，那你所有平常用的資訊服務，盡皆淪陷。</p>
<p>另一種更可能的情境是，在中國境內連 Gmail 時，由於 CNNIC 的假 CA 與 DNS hijacking 之故，連到的是假的 Gmail 登入頁，你很可能毫無所覺，使自己的 Gmail 帳號密碼拱手予人。中國政府由充足的動機，利用此法，竊取民運人士的 Gmail 帳密。記得否？Gmail 帳號系統遭攻擊，是 Google 宣稱可能退出中國的主因之一。</p>
<p>因此，在各官方決定並真的移除 CNNIC 相關 CA 之前，我們最好自力救濟。以下列出我搜集到的方法：</p>
<p>《<a href="http://www.erawtfos.com/2010/01/28/%E4%B8%BAmac%E7%9A%84safari%E5%B1%8F%E8%94%BDcnnic%E6%A0%B9%E8%AF%81%E4%B9%A6/">为Mac的Safari屏蔽CNNIC根证书</a>》：</p>
<ol>
<li>開啟 Keychain Access 程式</li>
<li>左上方選擇 System Roots</li>
<li>右方雙擊 CNNIC ROOT</li>
<li>打開 Trust</li>
<li>全部設成 Never Trust</li>
<li>開 Safari 連 https://www.enum.cn/ 測試</li>
</ol>
<p>《<a href="https://www.zuola.com/weblog/?p=1454">苹果下的FIREFOX如何删除CNNIC的根证书</a>》：</p>
<ol>
<li>Firefox: Perferences / Options -&gt; Advanced -&gt; Encryption -&gt; View Certificates</li>
<li>Export CNNIC:CNNIC Root, then delete it.</li>
<li>Export Entrust.net:Entrust.net Secure Server Certification Authority and Entrust.net:CNNIC SSL, then delete them.</li>
<li>Windows: Run -&gt; certmgr.msc</li>
<li>Untrusted Certificates -&gt; Certificates -&gt; All Tasks: Import...</li>
<li>Import all CA exported from firefox in previous steps.</li>
</ol>
<p>&nbsp;《<a href="http://felixcat.net/2010/01/throw-out-cnnic/">CNNIC，我不信任你！&mdash;&mdash;从&ldquo;受信任的根证书&rdquo;里赶走CNNIC</a>》</p>
<p>《<a href="http://people.debian.org.tw/~chihchun/2010/02/02/remove-cnnic-cert-on-linux/">在 Linux 上移除 CNNIC 憑證</a>》</p>
<p>在 Opera 上《<a href="http://jedi.org/p4/Opera/pub/news.html#005981">移除 CNNIC 憑證 (2010/02/02 23:32)</a>》</p>
<p>《<a href="http://www.plurk.com/p/3mfjwm">最近的話題之一：從系統/瀏覽器中移掉 CNNIC 的憑證</a>》</p>
<p>大家的動作都很快，所以這篇文章就當做我自己的筆記文了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2804/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>不要跑這麼快</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2807/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2807/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 07:54:30 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2807</guid>
		<description><![CDATA[某頻道裡 (訪客 ID 改成 visitor)： 20:52 &#60; visitor&#62; 有人在嗎 20:53 -!- visitor has left #cpp-tw [] 21:02 &#60;@lukhnos&#62; there 21:02 &#60;@lukhnos&#62; ha gone 21:09 &#60; jeffhung&#62; 好久沒寫 C/C++。 21:48 &#60;@lukhnos&#62; jeffhung: 都在寫... ? 22:40 &#60; yhchan&#62; jeffhung: 我也好久沒寫了... 23:12 &#60; jeffhung&#62; 前陣子都在寫 java，最近畫 uml、看 python 比較多。 Day changed to 30 Jan 2010 15:47 &#60; visitor&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>某頻道裡 (訪客 ID 改成 <code class="inline_code">visitor</code>)：</p>
<pre class="screen">
20:52 &lt; visitor&gt; 有人在嗎
20:53 -!- visitor has left #cpp-tw []
21:02 &lt;@lukhnos&gt; there
21:02 &lt;@lukhnos&gt; ha gone
21:09 &lt; jeffhung&gt; 好久沒寫 C/C++。
21:48 &lt;@lukhnos&gt; jeffhung: 都在寫... ?
22:40 &lt; yhchan&gt; jeffhung: 我也好久沒寫了...
23:12 &lt; jeffhung&gt; 前陣子都在寫 java，最近畫 uml、看 python 比較多。
Day changed to 30 Jan 2010
15:47 &lt; visitor&gt; 有人在嗎
15:48 -!- visitor has left #cpp-tw []
15:48 &lt; jeffhung&gt; 不要跑這麼快。
15:48 &lt; jeffhung&gt; -.-||</pre>
<p>不用跑這麼快啊啊啊～～</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2807/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>/dev/random 很慢，/dev/urandom 好一些</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2797/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2797/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 15:04:47 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2797</guid>
		<description><![CDATA[為了要製造一個大檔，所以下了這個指令：SHELL> dd if=/dev/random of=random1g.1 bs=1M count=1024]]></description>
			<content:encoded><![CDATA[<p>為了要製造一個大檔，所以下了這個指令：</p>
<pre class="screen">
SHELL&gt; dd if=/dev/random of=random1g.1 bs=1M count=1024
</pre>
<p>沒想到，等了 10 分鐘還沒有結束，<code class="inline_code">ls</code> 一看，<code class="inline_code">random1g.1</code> 才數百 K 大而已，火大只好退而求其次用 <code class="inline_code">/dev/zero</code> 做。不過疑問還是存在：為什麼 <code class="inline_code">/dev/random</code> 這麼誇張地慢？</p>
<p>早上改用 <code class="inline_code">/dev/urandom</code> 試，速度快很多。雖然還是很慢，但已經可以在合理時間完成任務。查了一下 Google，找到這篇《<a href="http://shoe.bocks.com/nlug/2003-Jul/3368.html"><strong>Re: [Nottingham] Very slow dd if=/dev/random</strong></a>》：</p>
<blockquote>
<p>/dev/random will block until it has gathered enough entropy to give you<br />
some more randomness. If it is on the same machine, try moving your mouse<br />
or using the keyboard to generate some more.</p>
<p>An experiment (under X) will demonstrate it. Open an xterm and run 'od -c<br />
/dev/random'. It should work for a few seconds and then stop. Whilst<br />
it's stopped, moved the mouse or open another window. It should start<br />
moving again.</p>
<p>If you don't want blocking to occurr for 'truer' randomness, try using the<br />
device '/dev/urandom'&nbsp;</p>
</blockquote>
<p>所以，套句同事的話：在用 <code class="inline_code">/dev/random</code> 或 <code class="inline_code">/dev/urandom</code> 的時候，沒事請亂敲鍵盤一下。XD</p>
<p>測試環境：CentOS 5.4 in VMware。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2797/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>為了 git:// 用 tsocks 翻牆</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2708/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2708/#comments</comments>
		<pubDate>Tue, 12 Jan 2010 11:52:12 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2708</guid>
		<description><![CDATA[在公司裡因為 firewall 的關係，沒辦法從公司裡面用 git 存取 git:// 的 repository，因此必須想辦法「翻牆」。以下簡述方法...]]></description>
			<content:encoded><![CDATA[<p>在公司裡因為 firewall 的關係，沒辦法從公司裡面用 <code class="inline_code">git</code> 存取 <code class="inline_code">git://</code> 的 repository，因此必須想辦法「翻牆」。以下簡述方法：</p>
<p>首先，在外面要有台 SSH server「接應」，利用 SSH tunnel 當作 socks server：</p>
<pre class="screen">
SHELL&gt; ssh -D5487 &lt;account&gt;@&lt;server-address&gt;
</pre>
<p>然後，安裝 tsocks 這套軟體，在 FreeBSD 裡就是 <code class="inline_code">/usr/ports/net/tsocks</code>，在 Ubuntu 裡就直接找 tsocks 裝即可。裝好後設定檔在 <code class="inline_code">/etc/tsocks.conf</code> 或 <code class="inline_code">/usr/local/etc/tcosks.conf</code>，修改其內容，將 default server 設定改成如下：</p>
<pre class="code">
# Default server
# For connections that aren't to the local subnets or to 150.0.0.0/255.255.0.0
# the server at 192.168.0.1 should be used (again, hostnames could be used
# too, see note above)
server = 127.0.0.1
# Server type defaults to 4 so we need to specify it as 5 for this one
server_type = 5
# The port defaults to 1080 but I've stated it here for clarity.
server_port = 5487</pre>
<p>然後在執行 <code class="inline_code">git</code> 時，前面冠以 tsocks 指令如下即可：</p>
<pre class="screen">
SHELL&gt; tsocks git clone git://foo.com/bar.git bar</pre>
<p>搞定收工。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2708/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>「對象」</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2657/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2657/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 17:44:26 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2657</guid>
		<description><![CDATA[話說前陣子聽說了一件事：對岸管 Inner Library 叫「內庫」。據曾去中國出差的同事說...]]></description>
			<content:encoded><![CDATA[<p>話說前陣子聽說了一件事：對岸管 Inner Library 叫「內庫」。據曾去中國出差的同事說，開會時內庫滿天飛，台灣同事個個臉上三條線，中國同事則是渾不覺有何不妥。</p>
<p>這種因用語不同而產生的誤解與不適，所在多有。我們看他們用法很奇怪，他們看我們用法也很奇怪。在台灣，似乎除了公認的譯法之外，使用原文也可以被接受。以我個人來說，雖然不計較信、雅、達三者兼具，但若最基本的「信」，也就是正確呈現原文意含，都無法達到時，我寧願使用原文。例如，「巨集」或「宏」，我都無法接受，寧願使用「macro」。</p>
<p>前幾天，我發了《<a href="http://www.jeffhung.net/blog/articles/jeffhung/2634/">Method overloading and naming</a>》這篇文章，事後對於以下這句話，感到不妥，故趕緊追加註解說明：</p>
<blockquote>
<p>如果今天 parameter 的意義，不是以「受詞」的方式存在，那就很有必要在 method name 上動點手腳。</p>
</blockquote>
<p>註解裡說明，「受詞」一詞的用法，有所爭議。什麼爭議呢？假設 <code class="inline_code">addBooks</code> 是這麼被呼叫的：</p>
<pre class="code">
class Librarian
{
    public void organize()
    {
        ...
        bookShelf.addBooks(newCategory);
        ...
    }

    public static void main()
    {
        Librarian librarian = new Librarian();
        librarian.organize();
    }
}
</pre>
<p>在此例中，「受詞」實際上是 <code class="inline_code">bookShelf</code>「物件」，而「主詞」則是呼叫 <code class="inline_code">addBooks</code> 方法者，也就是 <code class="inline_code">librarian</code> 物件。既然「受詞」另有其人，所以 <code class="inline_code">newCategory</code> 這個 parameter 當然不可能是以「受詞」的方式存在。是故，上述該句確實是有問題的。</p>
<p>一樣從物件導向的角度來看，呼叫 <code class="inline_code">addBooks</code> 的圖應該這麼畫：</p>
<p style="text-align: center;"><a href="http://www.flickr.com/photos/jeffhung/4265944287/" target="_blank"><img src="http://farm5.static.flickr.com/4020/4265944287_635624dcb0_o.png" alt="" /></a></p>
<p>這張圖翻譯成句子，是這個樣子：<em>The librarian tells bookShelf to addBooks (from) newCategory.</em></p>
<p>當畫成圖並翻成句子後，我們更明顯地看出了各參與者的地位：</p>
<ul>
<li>「主詞」是 <em>the librarian</em>；</li>
<li>「受詞」是 <em>bookShelf</em>；</li>
<li>「動詞」永遠是 <em>tell</em>，因為 <a href="http://pragprog.com/articles/tell-dont-ask">Tell, Don't Ask</a>；</li>
<li>&nbsp;所 <em>tell</em> 的「訊息」是 <em>addBooks (from) newCategory</em>，由此我們可以發現，parameter 亦為「訊息」的一部份。</li>
</ul>
<p>扯遠了。總之，講到「受詞」，我們應當從其原文來思考。查字典可知，「object」一字有以下兩個意思：</p>
<ol>
<li>a material thing that can be seen and touched.</li>
<li>a person or thing to which a specified action or feeling is directed.</li>
</ol>
<p>前者便是台灣譯法「物件」，後者則是中國譯法「對象」。從以上的討論可知，「object」一字的選用，兼具了這兩個意思，故台灣與中國譯法，都只有「信」一半，兩者都譯得對，但也都沒譯完全。既然半斤八兩，那我便應該時時警惕自己，不要碰到「面向對象」就只感到「這好奇怪」然後就沒了；應該要更進一步體認的是，「對象」、「物件」都是對的，千萬不要因為習慣於台灣的譯法，而忽視了「object」還有另一面意義存在，而導致了思考模式的偏頗。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2657/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Auto-save failed in wordpress 2.9</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2633/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2633/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 15:43:17 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2633</guid>
		<description><![CDATA[這該是 Wordpress 2.9 的 bug 吧，至少當我升上 2.9 之後，才開始發現這個問題。從某一版 wordpress 開始，支援了 auto-save 功能，可以自動儲存目前正在編輯的文章，以避免誤關 browser 或其它因素，導致正在編輯的文章內容流失。然而...]]></description>
			<content:encoded><![CDATA[<p><span title="processed" class="status-body"><span class="entry-content">這該是 WordPress 2.9 的 bug 吧，至少當我升上 2.9 之後，才開始發現這個問題。從某一版 wordpress 開始，支援了 auto-save 功能，可以自動儲存目前正在編輯的文章，以避免誤關 browser 或其它因素，導致正在編輯的文章內容流失。<br />
</span></span></p>
<p><span title="processed" class="status-body"><span class="entry-content">然而，從 2.9 版開始，我發現，當我開啟一個新文章，正在編輯文章標題，還未按下 Save Draft 或 Publish 按鈕時，因為我動作通常很慢，此時 auto-save 功能會發揮作用，先幫我存了一個版本。</span></span><span title="processed" class="status-body"><span class="entry-content">然後，</span></span>當我決定該是存檔的時候，按下 Save Draft 或 Publish 時，wordpress 反而會顯示「<span title="processed" class="status-body"><span class="entry-content">Your attempt to edit this post &quot;&lt;title&gt;&quot; has failed.</span></span>」的錯誤訊息。此時，若是回上一頁重來，browser 的 cache 不一定會幫我們保留住剛剛所編輯的所有文章內容；而若是按下「try again」，會存成一篇與 auto-save 所存的文章不同編號的新文章，且此新文章毫無內容，auto-save 存的版本，又僅含 auto-save 的那個時間點的內容，後者以我來說，通常是半個標題而已。</p>
<p>這種會剛剛寫的一大堆東西消失不見的現象，讓我想要撞牆好幾次，後來才抓出問題的規律來。</p>
<p>這其實是個 race condition，auto-save 功能自動存了一個版本，而因為此版本已經選擇了一個文章編號，當使用者按下 Save Draft 或 Publish 按鈕時，就會因為文章編號已存在，而存檔失敗。因為顯示錯誤訊息的頁面，沒有夾代文章內容，於是當「try again」時，會存成空白內容的新文章。<span title="processed" class="status-body"><span class="entry-content"><br />
</span></span></p>
<p><span title="processed" class="status-body"><span class="entry-content">解決方法？沒有，我沒有時間找，暫時在開完新文章後馬上按「Save Draft」按鈕迴避之。</span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2633/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Method overloading and naming</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2634/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2634/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 01:21:00 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2634</guid>
		<description><![CDATA[看到這篇《How Programming Books Promote Code Smells》裡的第一條，我僅同意一半。我同意有些註解毋須存在，只要「命名」做得好即可；但是，我不同意 addBooksFromCategory 這種命名法。]]></description>
			<content:encoded><![CDATA[<p>看到這篇《<a href="http://kaczanowscy.pl/tomek/2010-01/programming-books-promote-code-smells?">How Programming Books Promote Code Smells</a>》裡的第一條，我僅同意一半。我同意有些註解毋須存在，只要「naming」做得好即可；但是，我不同意 <code class="inline_code">addBooksFromCategory</code> 這種命名法。</p>
<p>該文的範例是這個樣子：</p>
<pre class="code">
// Add Books associated with the Category
public void addBook(Category category) {
    bookMap.put(category.getCategoryId(), category.getBooks());
}
</pre>
<p>認為那行註解沒有存在的價值，因為程式改成如下即可：</p>
<pre class="code">
public void addBooksFromCategory(Category category)
    bookMap.put(category.getCategoryId(), category.getBooks());
}
</pre>
<p>然而我認為，其實根本不必改程式，把註解拿掉即可。程式應該如下：</p>
<pre class="code">
public void addBooks(Category category)
    bookMap.put(category.getCategoryId(), category.getBooks());
}
</pre>
<p>為什麼？因為我認為，parameters 亦為 naming 的一部份，這也是 function overloading 的價值之所在。當我們看到如下兩個函式：</p>
<pre class="code">
public void addBooks(Book[] books);
public void addBooks(Category category);
</pre>
<p>當然可以很明確地知道，後者是「從 category 加書」，所以，其實沒有必要把函式名改成「<code class="inline_code">addBooksFromCategory</code>」。這其實跟之所以要把註解拿掉的理由一樣：去除餘冗的資訊 (remove redundant information)。</p>
<p>從物件導向的角度來看，method name 實為要送給 object 的 message。我認為 message 的命名最好能夠簡化，單一概念僅用單一種 message (method name) 來指涉，這樣比較易讀好懂：只有一種 <code class="inline_code">addBooks</code> 函式 (message)，比起既有 <code class="inline_code">addBooks</code> 又有 <code class="inline_code">addBooksFromCategory</code> 要來的簡單。</p>
<p>不過，如果今天 parameter 的意義，不是以「受詞」的方式存在，那就很有必要在 method name 上動點手腳。例如這樣的寫法：</p>
<pre class="code">
public void addBooksBy(Kiosk kiosk, Book[] books);
</pre>
<p>就比這樣的寫法好很多：</p>
<pre class="code">
public void addBooks(Kiosk kiosk, Book[] books);</pre>
<p>此時，<code class="inline_code">kiosk</code> 參數的「地位」，與 <code class="inline_code">books</code> 參數的地位，迥然不同。在這個情況之下，就很有必要在函式名稱裡，多加點東西，使之更「傳神」。否則，像上述後者的寫法，反而會讓人混淆，無法確定 <code class="inline_code">kiosk</code> 參數的意義與用法。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2634/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>老師有沒有講？不要用 magic number！</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/1696/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/1696/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 01:18:14 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[magic number]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=1696</guid>
		<description><![CDATA[老師有沒有講？不要用 magic number！]]></description>
			<content:encoded><![CDATA[<p>老師有沒有講？不要用 <a href="http://en.wikipedia.org/wiki/Magic_number_(programming)">magic number</a>！哼，摔鍵盤。</p>
<p>前陣子碰到一個奇怪的 bug，程式死在不應該出錯的地方，找半天找不到原因。最後靈機一動，發覺到每次跑，都死在同一筆 test data (跑一輪要很久，以小時計)。可是，檢查該筆 test data，又找不到任何特殊的地方。最後只好把目標放在，該筆 test data 的「序號」，才發覺又是新同事幹的好事。</p>
<p>我們的程式，跑一筆 test data，需要先配一塊資料結構，使用這個資料結構進行運算，最後再釋放這塊資料結構。為了效率的考量，我們選擇由 caller 負責準備這塊資料結構的記憶體。</p>
<p>也就是說，不像 <code class="inline_code">fopen()</code> 那樣，回傳一個 <code class="inline_code">FILE*</code> 指向 library 所配置的記憶體，而是由呼叫端，也就是應用程式，負責準備這塊記憶體，最後也由呼叫端，負責釋放。這樣的壞處是，資料結構的大小與內容，可以被呼叫端看見，違反了<a href="http://en.wikipedia.org/wiki/Information_hiding">資訊隱藏</a>的原則。但相對地，應用程式可以視需要，改用如全域變數等方式，而迴避了動態配置記憶體的效能負擔。</p>
<p>舉例來說，針對 command-line 傳來的各個 test case，我們可能測試如下：</p>
<pre class="code">
int main(int argc, char* argv[])
{
    for (int i = 1; i &lt; argc; ++i) {
        FooStruct foo;
        memset(&amp;foo, 0, sizeof(foo));
        InitFoo(&amp;foo);
        CalcFoo(&amp;foo, argv[i]);
        UninitFoo(&amp;foo);
    }
    return 0;
}
</pre>
<p>因為程式可能會以 single-thread 跑 N 次，或是以 multi-thread 分散開來跑，所以，這樣的架構不可行，多個 thread 可能同時存取到同一個 foo。因此，新同事選擇將 <code class="inline_code">FooStruct</code> 放在全域變數裡。如下：</p>
<pre class="code">
FooStruct foo[1789];

int main(int argc, char* argv[])
{
    for (int i = 0; i &lt; (argc - 1); ++i) {
        InitFoo(&amp;(foo[i]));
        CalcFoo(&amp;(foo[i]), argv[i + 1]);
        UninitFoo(&amp;(foo[i]));
    }
    return 0;
}
</pre>
<p>然後當我們換了一組更多筆數的 test data 時，程式就爆炸了。</p>
<p>據說當初在開這個測試用程式的規格時，有講到 test data 的來源、數量甚至測法，要能夠在 run-time 時指定。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/1696/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>努力練習嘴炮</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2509/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2509/#comments</comments>
		<pubDate>Mon, 23 Nov 2009 17:27:17 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2509</guid>
		<description><![CDATA[我想要寫 code 啊～ ~&#62;.&#60;~ 努力練習嘴炮，加班都是為了投影片。嗚嗚，懷念熬夜寫程式的日子。咦？XD]]></description>
			<content:encoded><![CDATA[<p>我想要寫 code 啊～ ~&gt;.&lt;~</p>
<p>努力練習嘴炮，加班都是為了投影片。嗚嗚，懷念熬夜寫程式的日子。咦？XD</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2509/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>筆記：Why are Facebook, Digg, and Twitter so hard to scale?</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/2442/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/2442/#comments</comments>
		<pubDate>Sun, 01 Nov 2009 06:57:39 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[digg]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[Industry]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/?p=2442</guid>
		<description><![CDATA[筆記文：Why are Facebook, Digg, and Twitter so hard to scale? 傳統的 web site 很好 scale 的原因在於： They usually access only their own data and common cached data. Only 1-2% of users are active on the site at one time. 但 facebook、dig 與 twitter 就不是如此了。 Facebook takes a Pull on Demand approach. 所以 facebook 有好友數上限，因為 pull [...]]]></description>
			<content:encoded><![CDATA[<p>筆記文：<a href="http://highscalability.com/blog/2009/10/13/why-are-facebook-digg-and-twitter-so-hard-to-scale.html">Why are Facebook, Digg, and Twitter so hard to scale?</a></p>
<p>傳統的 web site 很好 scale 的原因在於：</p>
<ul>
<li><em>They usually access only their own data and common cached data.</em></li>
<li><em>Only 1-2% of users are active on the site at one time.</em></li>
</ul>
<p>但 facebook、dig 與 twitter 就不是如此了。</p>
<p><em>Facebook takes a <strong>Pull on Demand</strong> approach.</em> 所以 facebook 有好友數上限，因為 pull on demand 可能會來不及抓完所有資料。<em>Another approach to find out what's new is the <strong>Push on Change</strong> model.</em> 代價就是 de-normalize 導致儲存需求大增。</p>
<p>如何在兩者之間達到平衡，就是關鍵了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/2442/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

