Android的Activity學習筆記

在開發Android的Mobile Application當中,Activity是相當重要的一個觀念。這一篇紀錄著我學習Activity相關的筆記,也歡迎大家留言討論。

低耦合(Low-Coupling)與高內聚力(High Cohesion)的設計原則

物件導向設計有一個很重要的原則就是盡量達到低耦合(Low-Coupling)與高內聚力(High-Cohesion)的結果。最近看到一篇文叫作【Two powerful principles to improve the design】的文章用很簡潔的方式介紹了這樣設計的好處。

J2EE Solutions 比較表

這個網站收錄了J2EE Open Source各種solutions的比較表,從Presentation、IDE、Web ... 等分門別類整理,還不錯,可以當作一個參考。



http://swik.net/CompareJ2EESolutions

Sharding V.S. Multiple Database

最近看到一篇文章在討論Database Sharding和Having Multiple Database之間的差異。

Apache Load-Balancer Load Module Order

If you want to use Apache web server as load-balancer, you have to load some modules. The order of how to load modules matters. Please follow the order :

  • LoadModule proxy_module modules/mod_proxy.so 
  • LoadModule proxy_http_module modules/mod_proxy_http.so

執行MySQL出現ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)錯誤

代表MySQL服務沒有啟動,請依序執行:

  • mysqld --install 
  • net start mysql

我讀【科技CEO的創新X創業學】- Sabeer Bhatia, Hotmail 共同創辦人


章節: Sabeer Bhatia, Hotmail 共同創辦人

  • 他們的確會抄襲我們的想法,如果他們把這個創意告訴Netscape會如何呢?或者再把這個創意告訴其他人?你必須了解,那時候我們一無所有,有的只是創意。

我讀【科技CEO的創新X創業學】- Max Levchin, PayPal 共同創辦人


章節:01 - Max Levchin PayPal 共同創辦人

  • 這種軟體真的很酷,數學運算上非常複雜,安全性也很高,但遺憾的是,沒有人需要。

我讀【科技CEO的創新X創業學】- 引言

最近買了一本書,叫作【科技CEO的創新X創業學】,以下的文章會針對每一篇進行佳句摘要和記錄,一方面加深印象,一方面也分享給大家,希望我們能夠一起從中得到些許啟發。

章節:引言

  • 短跑選手在離開起跑點達到最高速度的時候,就會開始慢慢減速,而冠軍通常都是減速程度最小的人,大多數創業者也是如此,最有生產力的階段通常是在剛開始的時候。
  • 我認為在工作中普遍存在一條準則-工作表現上投注越少精力的人,越會做表面功夫來彌補。
  • 事實上,程式設計師絕對不可能在上班時間穿著整齊、乖乖坐在座位上、桌面整理乾淨,他們通常還不修邊幅(我曾經因為寫程式時只圍一條毛巾而臭名遠播),凌晨兩點還待在像垃圾堆一樣的辦公室。
  • 如果能讓新創公司看起來更企業化,而大公司試著像新創公司一樣丟開包袱,未嘗不是兩全其美。

Steve Jobs changed from Signal vs. Noise

看了好多大家緬懷Steve Jobs的文章和報導,印象最深刻也最喜歡的是在Signal v.s. Noise部落格中的這一篇【Steve Jobs changed】

Spring Social 介紹

Spring Social 是最近Spring Project中所提供的一個Framework,它讓使用者可以把你原有的Spring Application和Thrid-Party Service Provide(ex : facebook, twitter)做整合,讓你用這些SaaS來認證,操作其API...等等。

Design Restful Web Service - Use SpringMVC as Example

最近公在公司的讀書會分享了REST的概念,花了些時間做了投影片,以及用SpringMVC做了一個小小的範例,對於REST的架構有了初步的認識,也釐清了一些觀念,把投影片分享出來,希望對於需要的人會有些幫助。

Ubuntu 10.04 安裝 Sun JDK 步驟


  1. sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
  2. sudo aptitude update
  3. sudo aptitude install sun-java6-jdk sun-java6-plugin

使用Java自動化執行工作 - Timer 和 ScheduledExecutorService

在Java中,如果想要在給定的時間區隔或固定時間執行某些任務,有幾種方法,在這裡稍微做個筆記。

Maven 之 POM(Project Object Model) 設定檔

在Maven中,最重要也是最基本的就是POM(Project Object Model)了。POM是一個XML的設定檔,它包含了Maven在建置專案時的所有資訊。

在執行Maven時,它會去檢查專案目錄下是某具有pom.xml檔案,如果沒有時,任何操作都會出現build error。

Maven 介紹

Maven是一套用來管理Java專案的工具,使用Maven,你可以讓專案在建置、測試、管理、部屬等工作上更為輕鬆。同時在管理dependency上,更是會讓你用起來愛不釋手。

我們先透過一個小範例讓大家對Maven的運作有一個初步的了解,在使用它之前,你必須要先安裝好適當的jdk。
首先,請先下載Maven,在這一篇的操作中,我們已Maven 2.2.1版本為主。
下載頁面:http://maven.apache.org/download.html

Eclipse安裝Maven套件時出現 "Cannot complete the install because one or more required items could not be found." 的解決方法

最近在Eclipse安裝Maven套件時,會出現這樣的錯誤

Cannot complete the install because one or more required items could not be found. Software being installed: Maven Integration for Eclipse (Required) 0.12.1.20110112-1712 (org.maven.ide.eclipse.feature.feature.group 0.12.1.20110112-1712) Missing requirement: Maven Integration for Eclipse (Editors) 0.12.1.20110112-1712 (org.maven.ide.eclipse.editor 0.12.1.20110112-1712) requires 'bundle org.eclipse.zest.core 0.0.0' but it could not be found Cannot satisfy dependency: From: Maven Integration for Eclipse (Required) 0.12.1.20110112-1712 (org.maven.ide.eclipse.feature.feature.group 0.12.1.20110112-1712) To: org.maven.ide.eclipse.editor [0.12.1.20110112-1712]

看起來是缺少一些dependency的套件, 查了一下,只要安裝GEF套件即可,網址在此:http://download.eclipse.org/tools/gef/updates/releases/

另外,Maven的Update Site:http://m2eclipse.sonatype.org/sites/m2e

解決jdom輸出時產生無意義(空白)Namespace之問題

在新版的jdom(我用的時候是1.1)中,使用XMLOutputter來輸出整個XML Document時,在Element上會產生空白內容的Namespace,像是這樣:

<bean xmlns=""></bean>
不管是呼叫Element的removeNamespaceDeclaration()或是設定NO_NAMESPACE都沒有用,甚至在create element之後呼叫remove attribute()去remove xmlns屬性也不行,這案情不單純阿...。

後來Google到一篇,裡面說到jdom新版有bug,要去source code裡面解決,不過也沒說是什麼問題,只好自己來啦!好險並不是很困難,原因在於XMLOutputter這支code裡面出了問題,在XMLOutputter中,有一個方法叫printNamespace,裡面原本的code有一段是長這樣:



很明顯有了錯,改成下面這樣就可以了:

[Shell Script] 用echo將文字以附加(apppend)方式寫入檔案

在編寫Shell Script時,如果你有echo到某個檔案的需求,你希望寫入檔案時是以附加(append)的方式進行,而不是整個覆蓋的話,你可以使用【>>】來取代【>】:

echo "aaa" >> /home/kevingo/example.txt
echo "bbb" >> /home/kevingo/example.txt


如此一來,example.txt中的內容就會是:
aaa
bbb

High Availability(HA) 與 Load Balance

最近在架設Web Server和Database的Cluster,主要的目的在於建構出一個High Availability(HA)的服務環境。

High Availability(HA)指的是提供一個高可靠度的運作環境,以網路服務來說,在Back-End需要的是Web Server Cluster和Database Cluster,目的在於當有任何一個節點crash後,會有其他的節點自動補上。

而Load Balance指的是當使用者的請求(request)進入到Back-End之後,會導入到目前loading比較輕的server,如此一來可以減輕每個server的負擔。

【相關閱讀】
商業服務的Ruby on Rails HTTP Cluster觀念及測試

MySQL Cluster 之 Data Nodes 與 Node Groups 之間的關係

在建立MySQL Cluster的時候,data node的數量和其所屬的node group是有相依關係的。從官方的文件中可以得到這樣的關係是

  • number of node groups = number of data nodes / NoOfReplicas

換句話說,你沒有辦法直接對node groups的數量進行設定,它取決於data nodes的數量和NoOfReplicas這兩個參數。

例如:

假設data nodes = 4

NoOfReplicas = 1 , node groups = 4
NoOfReplicas = 2 , node groups = 2
NoOfReplicas = 4 , node groups = 1

data nodes的數量最好是偶數,才能被平均分配到每個group當中。


Scrum 專案管理

Scrum是一種專案管理的模式,特別常用於軟體專案的開發上。Scrum字面上的意思指的就是【美式足球的爭球】,Scrum的運作精神就是希望能夠在每一次段時間的衝刺(Sprint)中,逐步逐步的透過小產出來完成最後的產品。

在Scrum的管理方法中,總共有四種角色:

  • Stakeholder
    • 使用者
    • 負責提供需求,在Scrum中,我們稱之為故事(Stroy)
  • Product Owner
    • 整個Scrum團隊的負責人
    • 將使用者的Story轉換為Product Backlog
    • 必須要為使用者的Story依據重要性進行排序(Priority)
  • Scrum Master
    • 開發團隊的領導人
    • 通常需要較深的開發經驗與技術知識背景
  • Scrum Team Member
    • 完成產品需求

從這裡可以看出,Scrum的角色定義其實並沒有太特別,比較有趣的是它的運作流程,讓我們來看看這張圖:


這張圖可以被拆成以下幾個步驟:

  1. Stakeholder向Product Owner提出自己的需求
  2. Product Owner將需求轉換為Product Backlog
  3. 透過Sprint Planning Meeting後,將Product Backlog轉換為Sprint Backlog
  4. 在每一次的Sprint中,按照優先順序,進行一次Sprint(衝刺)
  5. 每次的衝刺中,都會進行Daily Scrum Meeting,確保進度
  6. 完成產出後,由Product Owner來驗收成果
  7. 整個Scrum流程做完後,進行Retrospective Meeting,檢討整個流程需要改進之處


而在Scrum中,幾個名詞的解釋如下:


  • Product Backlog:指的就是使用者的需求。通常被排定好重要性和預計完成時間。

  • Sprint:一個工作週期,通常為期一到四週
  • Sprint Backlog:每一個Sprint需要完成的工作清單
  • Sprint Planning Meeting:在執行每次的Sprnit之前所召開的會議,用來決定這次的Sprint要完成的工作(Sprint Backlog)
  • Daily Scrum Meeting:在每天會舉行的會議,時間大約為15分鐘左右。Scrum Master會在這個會議中問三件事情
    • 昨天完成什麼
    • 今天要作什麼
    • 遭遇到什麼困難

為了管理方便,在Scrum進行過程中,還會有一些工具來幫助你進行得更加順暢:


  • Task Board:用來確認工作完成狀況的表格。實際上許多人會用有顏色的便利貼來區分,不同的顏色代表不同的工作或不同的負責人。




  • Burn Down Chart:用來監控專案進度的表格,X軸是時間,Y軸是專案總時程或總工作數目。理想中的走勢應該是向藍色線一樣的斜率,但是實際執行時,通常會有出入,可能會像紅色摺線一般,可以用來觀察專案的走勢。



【相關閱讀】
Scrum (development)
A Simple Intro of Scrum
What is SCRUM?
5分鐘 學 Scrum (簡介)

Java PaaS Shoot Out Reading Notes

這篇記錄一下最近同事分享的一篇【Java PaaS shootout】的文章。【Java PaaS shootout】比較了三個使用Java為主要開發語言的PaaS平台,分別是:Google App Engine(GAE)、Amazon Elastic Beanstalk和CloudBees RUN@Cloud。

What is PaaS(Platform as a Service)?

  • PaaS is a type of cloud service in which the provider delivers not only on-demand hardware and operating-system services, but also application platforms and solution stacks.
PaaS是建築在IaaS的基礎建設之上,提供客戶一組應用程式的平台和整套的解決方案(Solution Stack)

MongoDB REST Interface

MongoDB provides rest interface for basic observation of server status. The URL for rest interface is "port+1000".

For example, if you specify the mongodb port with 10000, the rest interface URL will be http://localhost:11000.

MongoDB Admin UI Tool

最近在找一個MongoDB Admin的UI工具,要不然看console很痛苦的...。在MongoDB的官網上有一篇介紹了許多UI tools:


有一些工具是用Web-based來管理,但是這些工具必須要綁web server,不是很喜歡;如果為了跨平台的需求,可以試試看JMongoBrowser,這是用Java寫成的,支援Linux、Windows、MacOS。

[Android Dev] 判斷SD卡是否存在

To check whether the sdcard existed or not, execute the following code :

if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))

Multi-Tenant Data Architecture 分享 (多租戶的資料設計架構) part1

最近同事分享了一篇好文章:Multi-Tenant Data Architecture,在這裡紀錄一下自己閱讀的感想。在這一篇中,先針對三種架構進行介紹,比較其優缺點和適用環境,下一篇再來描述如何針對不同的需求,選擇一個最適合你的設計架構。

  • 什麼是多租戶(Multi-Tenant)?
從字面上來看,就是有多個租用的客戶。在SaaS的雲端平台架構中,多租戶技術指的是大量的用戶共同使用、分享一組軟硬體資源。這這裡要分享的是在多租戶技術中,資料隔離的架構設計。

Sandglaz - 讓你的生活大小事情按照優先順序排好吧!

你是不是發現生活被許多大大小小的事情給占滿了,重要的事情沒做好,時間都被不重要的事情給占滿了?如果你經常被雜事把時間佔滿,不妨試試看Sandglaz這個服務。Sandglaz這個服務的概念是 - 將【事情依照輕重緩急進行分類】。基本上,生活中的事情你可以分成【重要且緊急】、【重要但不緊急】、【不重要但緊急】和【不重要且不緊急】這四大類,而Sandglaz這個服務也正好有這四個對應的象限。

如何成為一個好的前端工程師(Front-end Engineer)

最近公司可能會需要僱用一到兩個前端工程師(Front-end Engineer),雖然前端工程師這個名詞之前就有聽過,也大概知道工作內容是在處理前端UI部分,要會的技能大概會有CSS、HTML、Javascript...等,不過最近看到幾篇不錯的文章在介紹這個職位,在這裡大概筆記一下,也跟大家分享。

在JOSSO中使用MD5對密碼進行加密

使用JOSSO當作Single-Sign-On的Solution時,default的資料庫中儲存的是明碼,在實作面上,用明碼顯然是相當不安全的作法。

如果想要儲存被MD5過的密碼,自然需要針對JOSSO進行設定,不過找了很久,一只找不到相關設定..,最後只好針對Source Code進行修改。


下載回來之後,處理使用者登入的Servlet叫做UsernamePasswordLoginAction,位置在\josso-1.8.3-src\components\josso-protocol\src\main\java\org\josso\gateway\signon\UsernamePasswordLoginAction.java,當中,針對從request中取得的password去進行MD5加密就可以了。

JOSSO 解決登入出現AuthenticationFailureException的問題

最近在研究JOSSO(Java Open Single Sign-On)時,在登入時會出現AuthenticationFailureException,找了一段時間的資料,發現在這個討論串有類似的解答:


主要是說,當你在josso-gateway-auth.xml中設置的basic-authscheme如果是basic-auth-scheme時,要把hashAlgorithm和hashEncoding這兩個properties拿掉,不然會出現類似的Exception。

拿掉之後的配置會類似這樣:

    <basic-authscheme:basic-auth-scheme
            id="josso-basic-authentication"
            ignorePasswordCase="false"
            ignoreUserCase="false">

        <basic-authscheme:credentialStore>
            <s:ref bean="josso-identity-store"/>
        </basic-authscheme:credentialStore>

        <basic-authscheme:credentialStoreKeyAdapter>
            <s:ref bean="josso-simple-key-adapter"/>
        </basic-authscheme:credentialStoreKeyAdapter>

    </basic-authscheme:basic-auth-scheme>


之後就可以正常登入了:

Redmine Install on Windows (安裝Redmind 小記錄) - 下載連結更新!

Redmind 是一套用Ruby on Rails所開發的Open Source專案管理工具。基本上他支援很多在開發專案時常見需要的功能模組,可以參考以下這篇文章:


如果想要馬上玩玩看,也可以使用Redmind的Online Demo:http://demo.redmine.org/

這篇文章主要介紹一下在Windows上安裝的步驟以及遇到的問題和解決方法。在安裝Redmind時並不會太困難,只是需要注意一些版本相依的問題。安裝前,請先下載Redmind Install Package,這是我把相關需要安裝的軟體都綁在一起作成的一個安裝包,下載回去之後解壓縮隨便放在一個目錄中。


接著按照以下步驟進行:

1. 執行rubyinstaller-1.8.7-p334.exe,安裝Ruby,同時將安裝目錄下的bin將到Path系統變數中(Ex: 把C:\Ruby187\bin 加到系統變數)

2. 將rubygems-1.3.1.zip壓縮檔解壓縮到任意目錄(Ex : C:\rubygems-1.3.1)。

3. 打開命令提示字元,切換到第二步驟的目錄下,輸入以下命令 ruby setup.rb,這個命令會以Offline的方式安裝RubyGems。

4. 接著再命令提示字元中輸入以下指令gem install rake,安裝rake。

5. 將rails-2.3.3.zip解壓縮到任意目錄(Ex: C:\rails),同時切換到該目錄輸入以下指令gem install rails -v=2.3.3 --include-dependencies,進行Offline安裝rails的動作。

6. 在命令提示字元中執行gem install mysql 指令,安裝C bindings for MySQL

7. 安裝MySQL,同時將命令提示字元切換到Mysql>下。

8. 建立一個資料庫 create database redmine character set utf8;

9. 安裝 vcredist_x86.exe

10. 安裝Win32OpenSSL_Light-0_9_8j.exe,安裝完後,將安裝目錄下的DLL檔案都copy到system32目錄中。

14. 將ZLib 1.2.3目錄中的zlib1.dll更名成zlib.dll並且copy到Ruby安裝目錄的bin下。

12. 將redmine-0.9.1.zip解壓縮到任意目錄(Ex:C:\redmine),同時把目錄下的config\database.yml.example檔案複製一份,並且更名為database.yml

13. 修改第12步驟中database.yml檔案的內容,主要修改的區塊如下,根據自己的配置修改,注意,所有的冒號後面都要空一格,要不然之後會出現 'yntax error on line 14, col 2: ` encoding: utf8 的編碼錯誤。

production:
adapter: mysql
database: redmine
host: localhost
username: root
password:
encoding: utf8


14. 將libmySQL.dll檔案複製到Ruby安裝目錄下的bin目錄中。

15. 切換到Redmind的目錄,輸入以下指令rake config/initializers/session_store.rb

16. 接著輸入以下指令rake db:migrate RAILS_ENV="production"。這個指令是去建立資料庫的table和對應的schema。

17. 接著輸入以下指令rake redmine:load_default_data RAILS_ENV="production" ,選擇語系時,要中文就輸入zh-TW

18. 最後一步!輸入ruby script/server webrick -e production ,啟動Redmine。看到以下畫面就代表成功囉:


最後在瀏覽器上輸入http://localhost:3000/就可以看到Redmine的介面了!


基本上要跑起來就是這樣,可以先玩玩看,之後還可以整合SVN,改天再寫!

[設計模式] Strategy Pattern(策略模式) Part 2

Strategy Pattern(策略模式) Part 1裡面我們提到,如果我們裡用繼承父類別的方法,就會造成子類別被強迫實作他不需要的方法,有沒有更好的方式呢?

我們觀察到,每個角色共同擁有的功能是【攻擊】,只是攻擊的武器不同,因此,我們可以把攻擊這個方法獨立抽出來。先建立一個叫做Attack的Interface:


public interface Attack
{
    void useWeapon();
}


接著我們針對三個武器建立三個Class,分別是KnifeBehavior、SwordBehavior和AxeBehavior,同時這三個類別要去實作Attack這個介面:


public class KnifeBehavior implements Attack
{
     public void useWeapon()
     {
          System.out.println("Attack by Knife");
     }
}



public class SwordBehavior implements Attack
{
     public void useWeapon()
     {
          System.out.println("Attack by Sword");
     }
}



public class AxeBehavior implements Attack
{
     public void useWeapon()
     {
          System.out.println("Attack by Axe");
     }
}


接著,我們可以在原來角色的類別(Character)中,增加一個 setFightAction(Attack attack);的方法,這個方法可以讓實作他的角色類別依照需要來動態的產生不同的攻擊方法,因此,我們原本的角色類別變成:

public abstract class Character {
    public abstract void fight();
    public abstract void action();
    public abstract void char();
    public abstract void setFightAction(Attack attack);
}

如此一來,實作角色類別的個別角色(King、Queen和Knight)的程式就會變成:

public class King extends Character {

     Attack attack;

     @Override
     public void action() {}

     @Override
     public void chat() {}

     @Override
     public void fight() {
          f.useWeapon();
     }

     @Override
     public void setFightAction(Attack attack) {
          this.attack = attack;
     }
}


最後,我們要使用每個角色時,只需要這樣寫:

public class PlayGame {
    public static void main(String [] a) {
        King kevingo = new King();
        kevingo.setFightAction(new KnifeBehavior());
        kevingo.fight();

        Queen mary = new Queen();
        mary.setFightAction(new SwordBehavior());
        mary.fight();

        Knight tom = new Knight();
        tom.setFightAction(new KnifeBehavior());
        tom.fight();
    }
}


往後,當我們需要有新的攻擊方式時,只需要重新建立一個新的攻擊類別,而如果皇后要改拿其他的武器時,也只要在setFightAction中指定新的攻擊類別,真是太好了!

再回顧一下Strategy Pattern的定義:

  • 策略模式在於觀察程式中變動的部分,並且將他們抽離出來封裝成可互相抽換的演算法家族。這個模式讓你即使任意更換實作的演算法,也不會變動到去使用者他們的客戶端程式。

在這個範例中,我們把不同型態的攻擊方法抽出來變成一組家族,建立一個Interface叫做Attack,同時根據不同的攻擊方法來建立不同的類別,往後我們只要利用set方法就可以輕鬆的替換攻擊的方式,這就是策略模式的用途所在。

當然這個模式不是沒有缺點,最顯而易見缺點就是他必須要維護比較多的類別,當實作的策略變多的時候,維護起來就會比較吃力囉。

不喜歡Facebook新的瀏覽照片方式?試試看Better Facebook的外掛(支援Firefox、Chrome、Safari等多款瀏覽器)!


相信最近大家在用Facebook的時候,一定會發現瀏覽照片的方式變更了。現在Facebook會在前景開啟一個黑色為底的畫面來讓你瀏覽照片,不得不說這樣的瀏覽介面和方式實在有點難用加不美觀。今天介紹大家一個瀏覽器的外掛套件 -【Better Facebook】,可以讓你回覆到舊有瀏覽照片的方法,同時還增加了許多新功能,最棒的是這個外掛套件同持支援Firefox、Chrome、Safari、Opera等多款主流的瀏覽器,真是太棒了!


根據你使用的瀏覽器下載完成之後,第一次登入到Facebook頁面時會跑出設定的精靈選項,基本上可以直接一直按Next到底,因為事後都可以修改:


當中可以看到Better Facebook提供了類似分頁標籤的功能,可以針對不同的應用程式或朋友進行分類:


不過安裝Better Facebook最重要的還是要把照片瀏覽的方式改回原本自己習慣的瀏覽介面,很簡單,在Facebook的首頁的右上角會看到一個Options,點選進去就會跑出Better Facebook的設定畫面:


接著在【Popular】的標籤裡面,把【Disable the "Light Box".....】的選項給勾選起來,接著重新整理頁面,你會發現瀏覽照片的方法已經改回原本的囉!


而Better Facebook還有許多的功能,大家可以慢慢嘗試,當然如果不喜歡的話,就通通取消勾選只保留回復原本瀏覽照片的選項也是一招,大家試試看囉:)

在Visual Studio找不到DLL Reference?先確定Target Framework吧!

最近在練習C#程式開發時,偶而會碰到要reference某個dll的時候,找不到相對應的namespace,後來上網尋找了一下,發現不是這顆DLL消失了,而是Project裡面的Target Framework被設定為Client Profile的形式。


至於Client Profile和一般的.NET Framework有什麼不同,可以參考msdn上面的這篇文章:

.NET Framework Client Profile

另外這一篇文章也寫得不錯:

What’s new in .NET Framework 4 Client Profile RTM

簡而言之,Client Profile算是一個Compact Version,如果你要開發Web Service,也許可以用,但如果是桌面端AP的話,建議還是用原本的.NET Framework,比較可以省掉一些麻煩囉。

NUnit Test 筆記 (1) - NUnit in Visual Studio

NUnit是一個Open Source的框架,用來進行.NET程式的單元測試。以下分享一下自己閱讀以及使用NUnit的紀錄,希望對大家有些幫助。

什麼是單元測試(Unit Test)?


簡單來說,一個單元就是在程式當中最基本、最小的一個單位,最常見的是一個方法。單元測試就是為了去檢驗這個單元所執行的結果是否正確,換句話說,也就是去檢查程式的結果和程式設計師的預期規劃是否相同。

Unit testing is a method by which individual units of source code are tested to determine if they are fit for use. A unit is the smallest testable part of an application. In procedural programming a unit may be an individual function or procedure. Unit tests are created by programmers or occasionally by white box testers.
Ref: http://en.wikipedia.org/wiki/Unit_testing

下載NUnit並且在Visual Studio專案中引入DLL


NUnit 下載連結:http://www.nunit.org/index.php?p=download

如果是要在Visual Studio裡面使用的話,建議可以下載bin的連結,這樣就不用自己重新compile了。
下載回來之後,如果想要在Visual Studio裡面撰寫測試程式,必須要引用nunit.framework這個dll,把他加到你的專案裡面:


實際撰寫NUnit測試程式碼


假設我們有一個計算機(Calculator)的程式,測試時是想要去檢查內部的方法是否正確。首先可以建立兩個Project,一個是放計算機的主程式(這裡的namespace是kevingo.Calculator),另外一個Project則是撰寫測試程式碼用(NUnitTestProject)。

首先建立一個計算機的程式:


public class Calculator
{
    int result = 0;
    public int Add(int a, int b)
    {
        result = a+b;
        return result;
    }

    public int Sub(int a, int b)
    {
        result = a-b;
        return result;
     }

    public int Multiple(int a, int b)
    {
        result = a*b;
        return result;
    }

  
    public int Divide(int a, int b)
    {
        result = a/b;
        return result;
    }
}


在另外一個Project寫測試程式碼,這裡我偷懶一下,只先撰寫兩個測試方法來檢查Add和Sub的功能:

namespace NUnitTestProject
{
    [TestFixture]
    public class Program
    {
        Calculator c1 = new Calculator();

        [Test]
        public void TestAdd()
        {
            int addResult = c1.Add(10, 10);
            Assert.AreEqual(20, addResult);
         }

        [Test]
        public void TestSub()
        {
            int subResult = c1.Sub(10, 2);
            Assert.AreEqual(8, subResult);
        }
}


在撰寫測試程式碼的時候,記得先把Calculator這個Project Build成DLL引入到測試的Project中:




 執行NUnit測試結果


接著我們實際執行測試的結果,nunit提供了GUI介面,讓使用者可以很方便的檢驗測試的結果,為了方便測試,在build測試程式碼的時候,可以設定啟動nunit的GUI:




在Compile的時候應該就會把NUnit的GUI給帶出來,接著選擇File中的Open Project,把build出來的DLL(這裡叫做NUnitTestProject.dll)給開啟執行就可以看到結果,如果你的測試程式是正確的,就會顯示綠色,如果有錯的話就是紅色的結果,像這裡代表TestAdd是正確而TestSub是有問題的,如此一來就可以針對錯誤來修正:


第一篇先紀錄到這裡,下一篇來看看NUnit裡面有什麼Attributes可以用。

SVN Checksum Error

前陣子在寫程式的時候,發現了這個錯誤,當我想要commit一個檔案到SVN Server上時,他會告訴我【SVN Checksum Error】的訊息,結果就無法commit檔案上去了。

網路上找到的方法:
但是我是了還是不行,囧。我自己的解決方法很簡單,順序是這樣:

(1) 除了有checksum error的檔案之外,先commit所有其他的檔案
(2) 把無法commit上去的檔案先複製一份到別的資料夾
(3) 刪除有問題的檔案
(4) 重新把剛剛複製到別的資料夾的檔案copy過來,重新commit,這樣就解決了

打完收工!

Minimalist Gmail - 好用的Chrome套件,讓你的GMail更強大

Minimalist Gmail是一個相當強大的Google Chrome瀏覽器套件,他可以讓你自己打造相當客製化的GMail介面,看到Minimalist你可能會覺得這個套件只是讓介面更簡潔,但是除了簡化介面之外,他還可以讓你增加許多原本沒有的功能,讓我們來安裝玩玩看吧!
安裝好之後,會跳出這樣的設定畫面,裡面包羅萬象,可以設定的項目可多著呢:


比如說,在General的選項裡面,你可以去更改按鈕的顏色:


此外,我覺得最方便的是,當你的滑鼠移動到該項目上面時,他會show出一張圖讓你可以清楚的了解到目前所更改的部分是對應到GMail的哪個部位,如此一來,你就不用憑空猜想勾選這個選項後會有什麼改變了,我覺得這真的是一個很好的設計概念。比如說,下面的圖是我把滑鼠游標移動到【Enable custom buttons】選單上所顯示的圖:


還有選項是可以在標籤上顯示目前未讀的郵件:


這個是讓你自訂GMail上方的連結,不喜歡都是Google產品連結的話,就自己改個喜歡的吧!


其他還有許多不同的功能,大家不妨使用看看,把GMail的介面調整成自己最喜歡的樣式吧!

Do Nothing for 2 Minutes - 兩分鐘內什麼都不要作,休息一下吧!

我們每天都在網路上接收大量的訊息,不管是來是RSS訂閱、Plurk、Facebook、Twitter上面的朋友分享連結或是各式各樣的網路新聞,其實都是在進行【ADD】資訊的動作,你有沒有曾經覺得資訊多到腦袋已經不勝負荷了呢?

其實,一直不斷的給腦袋作資訊轟炸,某些層面上並不是件好事情,每天撥一點時間來放空或放鬆,對於創造力、生產力來說,都是一件好事情。這個時候,不妨打開這個叫做【Do Nothing for 2 Minutes】的網站來幫助你放鬆兩分鐘吧!

  • Do Nothing for 2 Minutes:http://www.donothingfor2minutes.com/

顧名思義,這個網站相當相當簡單,你只需要什麼都不作,聽著海浪的聲音放空兩分鐘就對了,在放鬆的過程中,會有倒數計時器幫助你了解目前進行的時間:


如果你動了滑鼠或鍵盤,那就會出現FAIL的字眼並且重新開始倒數:


成功的話當然也會秀出一些訊息囉:


累了嗎?來休息兩分鐘吧!

Google短網址服務 - 有了專屬網站還有API

Google在去年九月的時候給自己的短網址服務【goo.gl】一個專屬的網站,網址在此:

根據pingdom的這篇文章-【Is Goo.gl really the fastest URL shortener? (chart)】顯示,goo.gl是目前最快速、最穩定的短網址服務:


Google自己在也在Blog中提到,目前的短網址服務這麼多,為什麼Google還要跳進來參與呢?因為goo.gl是強調要做就要做最好的,他們提供了穩定度、安全性和速度的三大保證,目前看起來似乎是有這麼一回事:
  • Stability: We've had near 100% uptime since our initial launch, and we've worked behind the scenes to make goo.gl even stabler and more robust.
  • Security: We've added automatic spam detection based on the same type of filtering technology we use in Gmail.
  • Speed: We've more than doubled our speed in just over nine months.

而goo.gl這個短網址服務也很有趣,他所提供的網站裡面保存著你過去的紀錄,你可以追溯每個被縮短網址的點擊情況:


點選detail進去可以看到比較詳細的統計情形,包括是從哪個網站連進來的、國家、使用的瀏覽器和作業系統等等:


甚至還提供了QR Code呢:


現在,goo.gl還有對外的API可以使用了,網址在此:

Google短網址API:http://code.google.com/intl/zh-TW/apis/urlshortener/overview.html

有興趣的人可以自己寫程式來存取短網址服務囉。

[設計模式] Strategy Pattern(策略模式) Part 1

策略模式在Head First Design Pattern這本書中,是最先被介紹到的設計模式,可見得他應該是很重要且很基本的模式之一。以下就讓我們來記錄學習的心得並且分享筆記給大家。策略模式的基本定義如下:

Define a family of algorithms, encapsulate each one, and make them interchangeable. [The] Strategy [pattern] lets the algorithm vary independently from clients that use it.

【中文版】策略模式在於觀察程式中變動的部分,並且將他們抽離出來封裝成可互相抽換的演算法家族。這個模式讓你即使任意更換實作的演算法,也不會變動到去使用者他們的客戶端程式。

在這篇文章中,我們先看看如果不使用策略模式時,撰寫出來的程式是如何,接著在下一篇文章中進行一個對比。

讓我們考量一個情境(此情境延伸自Head First Design Pattern的練習),假設我們需要設計一組遊戲角色,我們可能會先定義一個角色類別,每一個遊戲角色都可以攻擊(fight)、行動(action)和交談(chat):


public abstract class Character {
    public abstract void fight();
    public abstract void action();
    public abstract void char();
}

這是一個很簡單的角色類別,加上abstract修飾子,讓繼承Character的class必須強迫去實作fight、walk和talk這三個方法。接著就可以真正創造我們的角色,假設我們有國王(King)、皇后(Queen)和騎士(Knight)這三個角色,那我們會這樣定義三個類別:

public class King extends Character {

     @Override
     public void action() {
         System.out.println("King walk");
     }

     @Override
     public void chat() {
         System.out.println("King chat");
     }

     @Override
     public void fight() {
          System.out.println("King fight by hand");
     }
}



public class Queen extends Character {

     @Override
     public void action() {
         System.out.println("Queen walk");
     }

     @Override
     public void chat() {
         System.out.println("Queen chat");
     }

     @Override
     public void fight() {
          System.out.println("Queen fight by hand");
}



public class Knight extends Character {

     @Override
     public void action() {
         System.out.println("Knight walk");
     }

     @Override
     public void chat() {
         System.out.println("Knight chat");
     }

     @Override
     public void fight() {
          System.out.println("Knight fight by hand");
}

角色都創建好了,看起來好像都沒有問題,但假設某天我們的遊戲改版了,使用者可以購買武器來殺敵,我們需要擴充程式來滿足這樣的需求。所以老闆說需要增加【寶劍】、【斧頭】、【匕首】等三種不同的新的攻擊模式,慘了,我們需要在角色類別裡面增加三個方法:


public abstract void fightBySword();
public abstract void fightByKnife();
public abstract void fightByAxe();


但是,問題來了,所有繼承角色這個類別的子類別都必須要實作這三個方法,但是假設皇后不能用斧頭只能用匕首、國王只能用寶劍...,這樣一來就很麻煩,我們必須要在個別角色裡面新增這三個方法,然後有些方法是空的...,多麼不好的寫法!

所以,利用繼承是會有缺點的,改變父類別的內容會連帶的更動到所有繼承他的子類別。在下一篇中我們來看看Strategy Pattern可以帶來什麼改變。

隨時提醒自己保持專注的三款倒數計時器(Keep Focus、Focus Booster、Timer)

最近和同事聊天談到時間管理的話題,主要是希望能夠有一個可以倒數計時的時鐘在桌面上提醒自己,印象中之前就有看過類似的工具和介紹文章,研究了一下,目前有幾個工具可以介紹。

Keep Focus

下載:
Keep Focus是用來實踐Pomodoro工作法的小工具,主要的進行步驟如下:
  1. 從Tasks List中挑選一個工作出來
  2. 設定25分鐘的Pomodoro工作時間
  3. 開始進行工作直到25分鐘結束(不論該工作結束與否,都要稍微停止並且做記錄)
  4. 休息5分鐘
  5. 每4個Pmodoro工作時間做一次較長時間的休息
上面的方法有沒有效是因人而異,不過裡面用到了Keep Focus這個小工具來實踐Pomodoro工作法。這個小軟體功能很簡單,就是一個小小的倒數計時器:
紅色叉叉關閉、白色按鈕會暫停計時並且重新開啟一段25分鐘區塊、最左邊的灰色按鈕可以進行拖拉。Keep Focus會把你實踐的結果存成文字檔,你可以隨時進行檢視。

  • 優點:小巧不占空間,功能單純。
  • 缺點:時間區塊不能自訂,只有25分鐘的設定。

Focus Booster

下載:
Focus Booster是一款base on Adobe AIR的軟體,功能也是用來倒數計時。這個軟體就頗美觀,同時也可以設定一個工作區塊的長度和休息時間。比較有趣的是,Focus Booster可以在倒數的時候發出滴答滴答聲音(不過還蠻吵的,所以預設是關閉的),結束了可以設定鬧鐘聲音。





    • 優點:可自訂工作時間長度。
    • 缺點:必須要先安裝Adobe AIR。


    Timer

    下載:
    Timer也是一個用來倒數計時的軟體,下載安裝之後,會在常駐區出現這樣的到數計時器:


    在icon上面點右鍵選擇Settings可以進行細部設定:


    可以設定的項目包括了是否要顯示在最上層、是否要開啟鬧鈴、鬧鈴的音樂...等等。


    比較特別的是Timer的設定時間方式,產生一個新的倒數計時工作的格式是:
    時間   時間種類   顯示訊息
    比如說我輸入【30 出門】代表30分鐘後出門,就會產生下面的倒數計時器。如果時間種類不輸入預設就是分鐘,小時則要輸入【hours】、秒的話是【sec】









    • 優點:功能最強大。
    • 缺點:時間設定功能較不直覺。

    介紹了三種倒數計時的工具,大家可以挑選自己喜歡的來使用,不過記得不要一次全部都用,這樣只會更複雜喔。

    【相關閱讀】
    Timer 免費免安裝的桌面小鬧鐘軟體,幫你倒數計時重要約會
    Keep Focused 保持25分鐘專注力的Pomodoro 工作法小工具| 電腦玩物
    Focus Booster 善用桌面電子番茄鐘,讓工作專注力加速| 電腦玩物

    [設計模式] Singleton Pattern (單例模式) Part2 (解決多執行緒問題) - Update Volatile關鍵字

    [2011-1-1補充] volatile關鍵字


    感謝馮大哥留言,在運用Double-Checked locking的作法時,在Java 5.0之後必須要加上volatile的修飾子在物件的變數宣告上,也就是變成:
    •  private volatile static Singleton instance;
    這樣子的寫法。原因在於,如果不加上volatile這個關鍵字時,在Java中由"順序"的問題,還是有可能會發生問題。最顯而易見的錯誤在於,當A執行緒進入getInstance()方法後,並且得到if(instance==null)為true的結果,進入到同步區,要執行Singleton()建構子內的敘述,但還沒有執行完時,執行緒B就進入getInstance()方法中,並且得到instance不是null的結果(因為在記憶體空間中已經配置的位置給instance了),如此一來就會造成執行緒B的物件內容並沒有成功的被指派,A和B之間就會有不同步的情形了。

    詳細的過程可以參考這篇文章:Double-checked Locking (DCL) and how to fix it

    我覺得寫的還蠻清楚的,另外我也加了相關閱讀在最下方,歡迎大家參考,這幾篇對於Double Check Locking的機制都寫得蠻清楚的,值得一看囉。
    ==

    在Singleton Pattern (單例模式) Part1中的【Lazy Instantization】方法可以說是最基礎的方式,但是在多執行緒的程式當中,這樣的寫法還是有可能會產生不同的實體,也就是這樣的寫法並不是一個thread-safe的方式,我們可以寫一個小程式來檢查看看:


    public class SingletonTest extends Thread {

        String threadName = "";

        public SingletonTest(String name) {
            threadName = name;
        }

        public void run() {
            for(int i=0 ; i<10 ; i++) {
                try {
                    Thread.sleep((int)500);
                    Singleton instance1 = Singleton.getInstance();
                    System.out.println(threadName + " ==> " + instance1.hashCode());

                } catch (InterruptedException e) {
                    e.printStackTrace();
            }
        }
    }

        public static void main(String [] a) {
            Thread t1 = new SingletonTest("thread-1");
            Thread t2 = new SingletonTest("thread-2");

            t1.start();
            t2.start();
        }
    }


    兩個threads可能會產生相同的實體(相同的hashCode)或是不同的實體(但不一定每次都會發生),原因在於兩個threads可能同時呼叫Singleton.getInstance()時,在進行if(instance==null)判斷時,結果都可能會是true,以至於都產生一個新的實體,這樣就會違背Singleton Pattern的宗旨了,所以我們必須進一步的修改這個模式。

    修改的想法是,當A、B兩個執行緒同時呼叫Singleton.getInstance()這個方法來取得物件的實體時,必須要先等對方結束之後才呼叫,才不會造成問題。換句話說,getInstance()這個方法在Java中只要加上Synchronized這個修飾子就可以解決了,如此一來,整個getInstance()方法就變成一個同步等待區,可以避免多執行緒造成重複實體的問題。

    public class Singleton {

        private static Singleton instance;

        private Singleton () { }

        public static Synchronized Singleton getInstance() {
            if(instance==null)
                instance = new Singleton();
            return instance;
        }
    }


    上面提到,某個執行緒必須等到另外一個執行緒離開之後才能存取getInstance()這個method,當執行緒一多的時候,可以想像的會造成效率的低落。所以又有進一步的改良寫法,那就是採用雙重上鎖(Double-Checked locking)的方式。

    雙重上鎖的概念是,一開始先檢查instance這個變數是不是null,如果不是null代表之前已經實體化了,直接回傳就好,如果沒有實體化時,才會進入同步等待區域。實際撰寫上只要將上面的getInstance()方法改寫成以下的形式就可以了:


    public class Singleton {

        private volatile static Singleton instance;

        private Singleton () { }

        public static Singleton getInstance() {
            if(instance==null) {
                Synchronized(Singleton.class) {
                    instance = new Singleton();
                }
            }
            return instance;
        }
    }


    如此一來就可以解決多執行緒效率的問題囉!歡迎大家一起留言討論:)

    【相關閱讀】
    Double-checked locking and the Singleton pattern
    Double-checked Locking (DCL) and how to fix it
    The "Double-Checked Locking is Broken" Declaration