顯示具有 Programming 標籤的文章。 顯示所有文章
顯示具有 Programming 標籤的文章。 顯示所有文章

利用 python update 資料庫欄位,跳脫字元的方式 (escape string)

在 python 中,用 Mysqldb module 結果在 stackoverflow 一個討論串中有個很讚的做法:

What is the best escape character strategy for Python/MySQL combo?
  • row[1] 指的是 column name
  • row[3] 指的是要 insert 的 data
  • row[0] 指的是 where 條件式域比對的限制條件

比對一下原始的 sql 就很清楚了:
cursor2.execute("update myTable set `"+ str(row[1]) +"` = \"'" + str(row[3]) +"'\" where ID = '"+str(row[0])+"'")

python 在安裝 MysqlDB 時,出現找不到 mysql_config 的錯誤

使用 python 在操作 Mysql 時,會需要用到 MySQLdb 這個 library,如果你在安裝時,出現找不到 mysql_config 的錯誤,可能的原因是當初在安裝 Mysql 時,是使用 apt-get 的方法安裝,這樣就不會有 mysql_config 這個檔案。

解決的方式是安裝 dev 版本,分別執行下面的指令:

這樣就解決了。

在JPA中,將createNativeQuery的結果轉換成其他物件

在JPA中,當你使用createNativeQuery去下SQL語法時,你可能會用getResultList來取得查詢出來的結果:

但是當你執行時,會出現無法轉換的錯誤:ClassCastException occured : [Ljava.lang.Object; cannot be cast to models.Post

Tomcat 出現 JDBC Driver has been forcibly unregistered 錯誤

在deploy application的時候,偶爾會遇到 "SEVERE: A web application registered the JBDC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered." 這樣子的錯誤訊息。

查了一些資料後,發現在Tomcat 6.0.24之後增加了防止memory leak的feature,有幾個作法可以避免:

  • 忽略他
  • 使用6.0.23之前的版本
  • 將 JDBC Driver 的 library 放到 tomcat 下的 lib 目錄
  • 繼承 BasicDataSource,自己 close connection



【相關閱讀】
To prevent a memory leak, the JDBC Driver has been forcibly unregistered
Memory Leak Protection
MySQL create memory leak in Tomcat

Spring Bean Scope 學習

在Spring中定義一個Bean時,可以針對其scope加以設定。在新版的Spring中,共有五種不同的scope可以設定,分別為:

Spring Bean Definition

在Spring中,Bean是一個物件,藉由Spring IoC Container來初始化(instantiated)、管理組裝(assembled)。

Bean會由定義的設定檔(configuration metadata)來建立。例如,藉由在XML檔案中,<bean>的設定來建立。

設定檔(configuration metadata)需要瞭解下列事項:

  • 如何建立Bean
  • Bean的生命週期
  • Bean的相依關係(dependencies)

在一個Bean的設定檔中,透過下列的properties來進行設定:

  • class:必定存在。定義用來建立此顆bean的class
  • name:用來建立Bean的識別(identifier)
  • scope:定義Bean的Scope,包含:singleton、protopype、request、session和global-session
  • constructor-arg:用來注入dependencies
  • properties:用來注入dependencies
  • autowiring mode:用來注入dependencies
  • lazy-initialization mode:用來告知IoC Container在第一次request這個bean的時候再建立instance,而不是在startup時
  • initialization method:一個callback。在所有必要的properties被呼叫後執行
  • destructor method:一個callback。在bean被destroyed時後被呼叫

一個典型的Bean設定檔大致如下所示:

在該設定檔中,有一個HelloWorld的Bean,分別在初始和結束時,會去呼叫init和destroy方法。同時把message這個參數注入Hello World!的值。

設計良好的Web API

最近由於工作的關係,需要設計API提供給User使用,我們採用的是HTTP + RESTful + JSON Response的方式,剛好和近期讀到的一篇文章所建議的方法相同,在這邊稍微記錄一下。

這篇文章是:Designing robust web API

根據作者過去的經驗,提供幾個在設計API的Best Practice或個人經驗。分別為:

  • Use a RESTful Model:使用HTTP + RESTful + JSON作為API的開發架構
  • Stabilize your API:Expose the API as minimal as possible. 保持API的穩健,不應該有大量變動。已經釋出的功能很難被刪減。
  • Version your API:在API的Request URL中加入版本資訊方便使用者做區別。
  • Asynchronous Invocation:如果你的response需要很長的時間,採用asyn的方法。實作上有兩種模式可以參考:(1) Client在request之後,server response是一個receipt,用來向server詢問response是否已經處理完畢。(2) Client提供callback address,當server處理完response之後,會丟回callback的位置讓client接收。

【相關閱讀】

數個JSON Library效能比較

今天看到一篇比較各種不同JSON library performance的文章:Json Java parsers / generators microbenchmark

文章中比較了八種常見的JSON Library用來 parse/generate JSON的效能,分別是:

  • FlexJson (2.1) 
  • GSon (2.1) 
  • Jackson (1.9.4) 
  • JsonLib (2.4) 
  • JsonMarshaller (0.21) 
  • JsonSmart (2.0-beta2) 
  • Protostuff JSON (1.0.4) 
  • XStream (1.4.2)

RESTful URL Design 準則

要設計RESTful URL,有一些準則可以參考,以下列出一些我覺得比較重要的部分,剩下的可以參考相關閱讀的兩篇文章,寫的都不錯。
  • Short
  • Lowercase, without mix-cases
  • Use plural path for collections, ex : /cars for all cars
  • Put individual resource under plural path. ex: /cars/car-1 or /cars/1
  • Use URL parameters ONLY with form-driven queries. ex: /cars/car/1, NOT /cars/car?id=1
  • Readable, Hierarchical, Simple.
  • Meaningful, ex: /cars/toyota/cr-z, NOT /cars/brand1/1
  • Hackable URL, ex: /cars/toyota/cr-z should have /cars/toyota/ and /cars
【相關閱讀】
Common REST Design Pattern
REST-ful URI design | RedRata

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

[設計模式] 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方法就可以輕鬆的替換攻擊的方式,這就是策略模式的用途所在。

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

在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,這樣就解決了

打完收工!

[設計模式] 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可以帶來什麼改變。

[設計模式] 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

[設計模式] Singleton Pattern (單例模式) Part1

最近在學習Hibernate的時候,發現在原廠的Documentation裡面,使用了Singleton Pattern這樣的模式,就讓我藉由這篇文章複習一下Design Pattern吧。

設計模式在軟體開發中,指的是如何運用一個良好的思維邏輯來進行程式碼架構的規劃及撰寫。提到設計模式,一定會提到Gof等四位作者所撰寫的這本書吧:


今天想要介紹並且讓我自己複習的正是Singleton Pattern(單例模式)。Singleton Pattern在設計上是希望確保一個類別在系統運行的時候,只有一個實體(instance)產生,同時,這個類別必須要提供一個公開的方法讓其他人取得自己的實體。為什麼我們要使用者這個模式?

在某些情況下,你的程式只會希望有一個物件的實體存在,比如說,連接資料庫的物件、程式管理員的物件、處理印表機列印的類別等等。如果這些物件可以有多個實體,那每次需要這些功能的時候,我們都可以任意的new一個實體出來進行操作,這樣會造成相當恐怖的結果。

如果把Singleton Pattern實作出來,長相會是這樣


public class Singleton {

    private static Singleton instance;

    private Singleton () { }

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

這段程式碼的重點有三個:

  1. 要有一個私有(private)的靜態(static)方法:用來紀錄類別的實體。因為是私有的,所以外部沒辦法直接透過Singleton.instance來存取。
  2. 類別擁有一個私有的建構子:其他的方法沒辦法直接產生這個類別的實體,說的白話一點,就是不能夠用new Singleton()這樣的方式來產生實體,這是重點所在。
  3. 擁有一個公開取得物件實體的方法:由於是私有建構子(private constructor)的原因,要產生這個類別的實體,只能靠自己類別內的方法產生。但是又必須要讓外部能夠呼叫,所以要設定為公開的靜態方法
這種方式又稱為【Lazy Instantization】,中文可以翻作【延遲實體化】。為什麼呢?因為我們可以看到,我們只有需要這個物件的時候,利用Singleton.getInstance()這樣的方法來取得Singleton這個類別的實體,不需要的時候就不會產生,所以叫做延遲的實體化方法。

要怎麼驗證呢?很簡單,寫一個小程式測試一下就好了,兩個實體的hashcode應該是相同的囉:

Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1.hashCode());
System.out.println(instance2.hashCode());

Lazy Instantization的方法在Single Thread的程式中是可以正確運作的,但是當你的程式有兩個或兩個以上的threads在跑的時候,就會出現問題,這個部份我們留到part2再談囉!