<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>IKniGht&#039;s Blog</title>
	<atom:link href="http://iknight.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://iknight.wordpress.com</link>
	<description>Java, Investment, Tao Philosophy, Lionhead</description>
	<lastBuildDate>Fri, 04 Dec 2009 06:44:07 +0000</lastBuildDate>
	<language>th</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='iknight.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>IKniGht&#039;s Blog</title>
		<link>http://iknight.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://iknight.wordpress.com/osd.xml" title="IKniGht&#039;s Blog" />
	<atom:link rel='hub' href='http://iknight.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Use enums instead of int constants</title>
		<link>http://iknight.wordpress.com/2009/08/01/use-enums-instead-of-int-constants/</link>
		<comments>http://iknight.wordpress.com/2009/08/01/use-enums-instead-of-int-constants/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 05:10:15 +0000</pubDate>
		<dc:creator>iknight</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://iknight.wordpress.com/2009/08/01/use-enums-instead-of-int-constants/</guid>
		<description><![CDATA[ก่อนที่จะมีการใช้ enum ใน Java5 Java Version ก่อนหน้านี้ก็มีการใช้ constants ที่เรียกว่า int enum pattern หน้าตาจะเป็นแบบนี้นะครับ public static final int APPLE_FUJI = 0; public static final int APPLE_PIPPIN = 1; public static final int APPLE_GRANNY_SMITH = 2; มาดูข้อเสียของมันดีกว่า 1. มันไม่ type safety เราสามารถจะ assign ค่าอะไรให้มันก็ได้ 2. มันไม่มี namespaces โดยเราต้องใช้ parameter name ที่มี prefixe เหมือนกันในการจักกลุ่ม 3. มันเป็น compile-time constant [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=268&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>ก่อนที่จะมีการใช้ enum ใน Java5 Java Version ก่อนหน้านี้ก็มีการใช้<br />
constants ที่เรียกว่า int enum pattern หน้าตาจะเป็นแบบนี้นะครับ</p>
<pre>
public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_GRANNY_SMITH = 2;
</pre>
<p><b>มาดูข้อเสียของมันดีกว่า</b><br />
<i><b>1. มันไม่ type safety</b></i><br />
เราสามารถจะ assign ค่าอะไรให้มันก็ได้</p>
<p><i><b>2. มันไม่มี namespaces</b></i><br />
โดยเราต้องใช้ parameter name ที่มี prefixe เหมือนกันในการจักกลุ่ม</p>
<p><i><b>3. มันเป็น compile-time constant</b></i><br />
ถ้า build client หรือ class ที่เรียกใช้มัน มันจะ build โดยไปเอาค่า<br />
constant มาเก็บไว้ที่ class มันเลย ลองดูตัวอย่างนี้หน่อยดีกว่า</p>
<p><b>int enum pattern &#8220;Apple.java&#8221;</b></p>
<pre>
public interface Apple{
	public static final int APPLE_FUJI = 0;
	public static final int APPLE_PIPPIN = 1;
	public static final int APPLE_GRANNY_SMITH = 2;
}
</pre>
<p>class ที่ต้องการใช้ constant ก็ impliments มา <b>&#8220;TestApple.java&#8221;</b></p>
<pre>
public class TestApple <b>implements Apple</b>{
	public static void main(String[] args) {
		System.out.print(APPLE_FUJI);
		System.out.print(APPLE_PIPPIN);
		System.out.print(APPLE_GRANNY_SMITH);
	}
}
</pre>
<p>ค่าที่ได้จะเป็น 012 นะครับ แต่ถ้าลองแก้ไขค่าของ constant ของ Interface Apple แล้ว build ใหม่(build แต่  Interface Apple นะครับ)แล้วลอง run class TestApple ค่าที่ได้ก็จะได้ค่าเหมือนเดิม แต่ถ้าอยากได้ค่า constant ใหม่ก็ต้อง build class TestApple ใหม่ด้วยเพื่อให้มันไปอ่านค่า constant มาใหม่ </p>
<p><i><b>4. มัน print value ของ constant ได้เท่านั้น</b></i><br />
เวลา print ออกมาจะได้แต่ค่าที่ constant เก็บไว้เท่านั้นนะครับ</p>
<p>หรืออาจจะเจอ pattern คล้ายๆกัน โดย constant เก็บค่า String เรียกว่า string enum constant แต่มันจะนำไปสู่ปัญหาของ performance ยิ่งกว่านั้นมันทำให้ programmer สามารถ hard-code value ของ string constant แทนการใช้ field name และมันจะมีโอกาศพิมพ์ผิด มันจะเกิดข้อผิดพลาดตอน runtime ทั้งๆที่ มันสามารถค้นหา ข้อผิดพลาดได้ตอน compile time</p>
<p><b>java5 แก้ไขปัญหาของ pattern นี้ โดยการนำ enum มาใช้</b></p>
<pre>
	public enum Apple { FUJI, PIPPIN, GRANNY_SMITH }
	public enum Orange { NAVEL, TEMPLE, BLOOD }
</pre>
<p>ความแตกต่างที่สำคัญ ของ enum ในภาษา java กับภาษาอื่นใน java enum เป็น class  ในขณะที่ภาษาอื่น เช่น  C, C++, and C# เก็บข้อมูลเป็น int ลักษณะของ enum ในภาษา java คือเป็น class ที่ export instance ของแต่ละ constanct ที่ประกาศใน enum นั้นโดยทาง &#8220;public static final field&#8221;</p>
<p><i><b>1. type safety</b></i><br />
เราสามารถจะ assign ค่าที่ประกาศไว้ใน enum เท่านั้น</p>
<p><i><b>2. namespaces</b></i><br />
แก้ปัญหา named constants เพราะ enum มี namespace (ก็ชื่อของมันเอง)</p>
<p><i><b>3. มันไม่ได้ เอาค่า constant มาเก็บไว้แต่มันจะ reference ไปแทน</b></i><br />
สามารถแก้ไขหรือ เพิ่ม constants โดยไม่ต้อง build class ที่เรียกใช้มันใหม่<br />
เหมือนกับว่าตอน build มันไม่ได้เอาค่า constant มาเก็บไว้ที่ class ของมันเลยแต่จะสร้าง reference ไปหา class enum แทน</p>
<p><i><b>4. เราสามารถ print ชื่อ constant, value หรือค่าอะไรก็ได้ที่เกี่ยวข้องกับ constant</b></i> method toString ของมันจะ return ชื่อของ constant หรือถ้าไม่ต้องการชื่อ constant เราก็ยังสามารถ override method toString ได้แล้ว get ข้อมูลของแต่ละ enum มาได้ด้วยนะครับ</p>
<p><i><b>5. can use == operation</b></i></p>
<p><i><b>6. สามารถเพิ่ม method หรือ property ที่มีความสำพันธ์กับ constant ได้</b></i></p>
<p><b>มาดูตัวอย่างกันดีกว่า</b><br />
จัดกลุ่ม constant ของ Apple จากตัวอย่างข้างบน <b>enum &#8220;Apple.java&#8221;</b></p>
<pre>
	FUJI(0, "ฟูจิ"), PIPPIN(1, "พิพพิน"), GRANNY_SMITH(2, "แกรนนี่ สมิท");
	private Integer appleType;
	private String description;

	Apple(Integer appleType, String description) {
		this.appleType = appleType;
		this.description = description;
	}
</pre>
<p>เริ่มด้วยการกำหนดชื่อ constant &#8220;FUJI&#8221; ส่ง parameter ไป 2 ตัวคือ value และ description ของมันไปทาง constructor เป็นการผูก constant name, value, description เข้าด้วยกัน<br />
เพิ่ม method</p>
<pre>
	public Integer getAppleType() {
		return appleType;
	}
	public String getDescription() {
		return description;
	}
</pre>
<p>เพิ่ม method &#8220;getApples()&#8221; เพื่อเอาไว้ get instant ของ enum ทั้งหมด</p>
<pre>
	public static List getApples() {
		return Arrays.asList(Apple.values());
	}
</pre>
<p>เพิ่ม method getApple(Integer appleType)&#8221; เพื่อเอาไว้ get instant โดย value</p>
<pre>
	public static Apple getApple(Integer appleType) {
		List apples = getApples();
		for (Apple apple : apples)
			if (appleType.compareTo(apple.getAppleType()) == 0)
				return apple;
		throw new AssertionError("Unknown Apple type : " + appleType);
	}
</pre>
<p>มาลอง test กันดีกว่า <b>&#8220;Test.java&#8221;</b><br />
สามารถ get instanct ทั้งหมดได้</p>
<pre>
	List apples = Apple.getApples();
	for (Apple apple : apples)
		log.debug(apple);
</pre>
<p>สามารถ get ค่าอื่นๆที่มีความสำพันธ์กับ constant ได้ </p>
<pre>
	Apple apple1 = Apple.FUJI;
	log.debug(apple1);
	log.debug(apple1.getAppleType());
	log.debug(apple1.getDescription());
</pre>
<p>สามารถ get instanct โดย value ของมันได้</p>
<pre>
	Apple apple2 = Apple.getApple(0);
</pre>
<p>สามารถใช้ operation == ได้</p>
<pre>
	log.debug(apple1 == apple2);
</pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iknight.wordpress.com/268/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iknight.wordpress.com/268/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iknight.wordpress.com/268/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iknight.wordpress.com/268/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iknight.wordpress.com/268/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iknight.wordpress.com/268/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iknight.wordpress.com/268/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iknight.wordpress.com/268/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iknight.wordpress.com/268/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iknight.wordpress.com/268/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iknight.wordpress.com/268/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iknight.wordpress.com/268/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iknight.wordpress.com/268/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iknight.wordpress.com/268/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=268&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iknight.wordpress.com/2009/08/01/use-enums-instead-of-int-constants/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d2a8255a0478cf3c58c9bd829d1f7ba2?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">iknight</media:title>
		</media:content>
	</item>
		<item>
		<title>ClassNotFoundException: org.hibernate.hql.ast.HqlToken on OC4J</title>
		<link>http://iknight.wordpress.com/2009/07/26/classnotfoundexception-org-hibernate-hql-ast-hqltoken-on-oc4j/</link>
		<comments>http://iknight.wordpress.com/2009/07/26/classnotfoundexception-org-hibernate-hql-ast-hqltoken-on-oc4j/#comments</comments>
		<pubDate>Sun, 26 Jul 2009 08:15:57 +0000</pubDate>
		<dc:creator>iknight</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://iknight.wordpress.com/?p=251</guid>
		<description><![CDATA[เจอ exception นี้ตอนที่ลองหัด spring แล้วเขียน hql qurey ข้อมูลขึ้นมา เขียน unitTest ก็ใช้งานได้ตามปกตินะไม่มีปัญหาอะไร แต่พอลองเรียกจาก Controller ดันมาเจอ exception นี้ org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken ก็เลยลองถามอาจารย์กูดู สรุปว่า เกิดจากการ conflicts กันระหว่าง libraries TopLink กับ libraries Hibernate การแก้ปัญหาก็คือเอา libraries ของ TopLink ออก โดยการแก้ไข file orion-application.xml ของ application โดยเพิ่ม tag &#60;imported-shared-libraries&#62; &#60;remove-inherited name="oracle.toplink"/&#62; &#60;/imported-shared-libraries&#62; แต่ปัญหานี้ก็ยังไม่จบนะครับ เพราะทุกครั้งที่ publish มันก็จะลบ application ออกแล้วเราก็จะได้ orion-application.xml ใหม่ (ก็คือเป็นเหมือเดิม) การแก้ไขก็ [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=251&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>เจอ exception นี้ตอนที่ลองหัด spring แล้วเขียน hql qurey ข้อมูลขึ้นมา<br />
เขียน unitTest ก็ใช้งานได้ตามปกตินะไม่มีปัญหาอะไร<br />
แต่พอลองเรียกจาก Controller ดันมาเจอ exception นี้</p>
<pre>org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken</pre>
<p>ก็เลยลองถามอาจารย์กูดู สรุปว่า<br />
เกิดจากการ conflicts กันระหว่าง libraries TopLink กับ libraries Hibernate </p>
<p>การแก้ปัญหาก็คือเอา libraries ของ TopLink ออก<br />
โดยการแก้ไข file orion-application.xml ของ application โดยเพิ่ม tag</p>
<pre>
&lt;imported-shared-libraries&gt;
	&lt;remove-inherited name="oracle.toplink"/&gt;
&lt;/imported-shared-libraries&gt;
</pre>
<p>แต่ปัญหานี้ก็ยังไม่จบนะครับ เพราะทุกครั้งที่ publish มันก็จะลบ application<br />
ออกแล้วเราก็จะได้ orion-application.xml ใหม่ (ก็คือเป็นเหมือเดิม)</p>
<p>การแก้ไขก็ แก้ไขที่ Configure Class Loading<br />
<a href="http://download.oracle.com/docs/cd/B25221_04/web.1013/b14433/classload.htm#CIHFABFI" target="_blank">Example: Removing an Oracle Shared Library at Deployment Time </a><br />
จะทำให้ทุกครั้งที่ publish จะได้มันจะได้ไม่ import libraries ของ TopLink<br />
ไปด้วยครับ</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iknight.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iknight.wordpress.com/251/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iknight.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iknight.wordpress.com/251/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iknight.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iknight.wordpress.com/251/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iknight.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iknight.wordpress.com/251/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iknight.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iknight.wordpress.com/251/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iknight.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iknight.wordpress.com/251/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iknight.wordpress.com/251/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iknight.wordpress.com/251/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=251&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iknight.wordpress.com/2009/07/26/classnotfoundexception-org-hibernate-hql-ast-hqltoken-on-oc4j/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d2a8255a0478cf3c58c9bd829d1f7ba2?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">iknight</media:title>
		</media:content>
	</item>
		<item>
		<title>Use interfaces only to define types</title>
		<link>http://iknight.wordpress.com/2009/07/19/use-interfaces-only-to-define-types/</link>
		<comments>http://iknight.wordpress.com/2009/07/19/use-interfaces-only-to-define-types/#comments</comments>
		<pubDate>Sun, 19 Jul 2009 10:45:57 +0000</pubDate>
		<dc:creator>iknight</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://iknight.wordpress.com/2009/07/19/use-interfaces-only-to-define-types/</guid>
		<description><![CDATA[ก็เป็นที่รู้ๆ กันอยู่แล้วนะครับ variable ของ interface เป็น public static final เสมอ เพียงแค่ ประกาศแบบนี้ String CONSTANT_VALUE = "constantValue"; มันก็จะเป็น public static final String CONSTANT_VALUE = "constantValue"; ด้วยเหตุที่มันเป็น final เสมอเราก็ต้อง assign ค่าให้มันเสมอ อีกเช่นกัน (ดูดิมันช่างเหมาะจะเอาไว้เก็บ constant จริงๆ) แล้ว java ก็ extends ได้ 1 class แต่ implements ได้หลาย interface มันก็ดูจะเข้าท่าดีนะที่จะเขียน interface ไว้เก็บ constant เพราะเวลาเรา implements interface นี้แล้ว ก็สามารถใช้ constant ใน [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=246&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>ก็เป็นที่รู้ๆ กันอยู่แล้วนะครับ variable ของ interface เป็น public static final เสมอ<br />
เพียงแค่ ประกาศแบบนี้</p>
<pre>
	String CONSTANT_VALUE = "constantValue";
</pre>
<p>มันก็จะเป็น </p>
<pre>
	public static final String CONSTANT_VALUE = "constantValue";
</pre>
<p>ด้วยเหตุที่มันเป็น final เสมอเราก็ต้อง assign ค่าให้มันเสมอ อีกเช่นกัน<br />
(ดูดิมันช่างเหมาะจะเอาไว้เก็บ constant จริงๆ)</p>
<p>แล้ว  java ก็ extends ได้ 1 class แต่ implements ได้หลาย interface<br />
มันก็ดูจะเข้าท่าดีนะที่จะเขียน interface ไว้เก็บ constant เพราะเวลาเรา<br />
implements interface นี้แล้ว ก็สามารถใช้ constant ใน interface ได้ทันที<br />
subclass ก็สามารถใช้ได้ทันทีเช่นกัน และยังสามารถ extends class อื่นได้อีก</p>
<p>มันจึงเกิด pattern (antipattern) หนึ่ง ชื่อว่า interface constant</p>
<p>ลักษณะก็จะมีแต่ property และไม่มีการประกาศ method ให้ class ที่<br />
implement ไปต้อง implements อะไรเลย class ที่จะใช้ constant<br />
ก็ implements constant interface และเพื่อจะหลีกเลี่ยงการอ้าง<br />
ถึง constant ด้วย namespace</p>
<pre>
public interface PhysicalConstants {
	static final double AVOGADROS_NUMBER = 6.02214199e23;
	static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
}
</pre>
<p><i><b>&#8220;The constant interface pattern is a poor use of interfaces.&#8221;</b></i></p>
<p>ถ้าดูให้ดีแล้วนะครับถ้า class ที่ implements constant interface ไม่ได้เป็น final (ซึ่ง final class ก็เป็นอะไรที่ไม่ควรเขียนอีก) ซึ่งมันอาจจะถูก extends ได้อีก sub class ของมัน ก็สามารถอ้าง constant interface ได้ แล้วถ้าวันหน้า class ที่ implements นี้มาโดยตรงไม่จำเป็นต้องใช้ constant นี้แล้ว !!แต่ก็ยังต้อง implements อยู่ดีเพราะ sub class ของมันอาจจะใช้ constant อยู่</p>
<p>แล้วขณะที่บาง sub class ไม่จำเ็ป็นต้องใช้ constant<br />
ก็จะสามารถอ้างถึง constant ได้ทั้งที่ไม่จำเป็น</p>
<p><b>ถ้าต้องการใช้ constant ทางเลือกคือ</b></p>
<p>เขียน utilities class เพื่อเก็บ constant แล้วหลีกเลี่ยงการอ้างถึง constant<br />
ด้วย namespace โดยใช้ static import</p>
<pre>
import static PhysicalConstants.*;
public class Test {
	double atoms(double mols) {
		return AVOGADROS_NUMBER * mols;
	}
}
</pre>
<p>หรือถ้ามันควรจะอยู่ที่ interface ก็ได้ถ้ามองว่า class ที่ implements นี้ไป<br />
ควรใช้ constant เหมือนกัน (แต่ให้คิดว่าใช้ interface เป็นการประกาศชนิดของ class ก่อนส่วนจะมี constant มันก็เป็นอีกเรื่องหนึ่ง ไม่ใช่เขียน interface เพื่อที่จะเก็บ constant ก่อน )</p>
<p><i><b>&#8220;interfaces should be used only to define types.&#8221;</b><br />
They should not be used to export constants.</i></p>
<p>reference : <a href="http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1248596302&amp;sr=8-1" target="_blank">Effective Java</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iknight.wordpress.com/246/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iknight.wordpress.com/246/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iknight.wordpress.com/246/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iknight.wordpress.com/246/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iknight.wordpress.com/246/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iknight.wordpress.com/246/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iknight.wordpress.com/246/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iknight.wordpress.com/246/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iknight.wordpress.com/246/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iknight.wordpress.com/246/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iknight.wordpress.com/246/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iknight.wordpress.com/246/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iknight.wordpress.com/246/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iknight.wordpress.com/246/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=246&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iknight.wordpress.com/2009/07/19/use-interfaces-only-to-define-types/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d2a8255a0478cf3c58c9bd829d1f7ba2?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">iknight</media:title>
		</media:content>
	</item>
		<item>
		<title>Get start Spring with Hibernate</title>
		<link>http://iknight.wordpress.com/2009/07/11/get-start-spring-with-hibernate/</link>
		<comments>http://iknight.wordpress.com/2009/07/11/get-start-spring-with-hibernate/#comments</comments>
		<pubDate>Sat, 11 Jul 2009 06:29:15 +0000</pubDate>
		<dc:creator>iknight</dc:creator>
				<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://iknight.wordpress.com/?p=150</guid>
		<description><![CDATA[ก่อนอื่นอ่านเรื่อง DI จากเวปนี้ก่อนนะครับ Inversion of Control Containers and the Dependency Injection pattern Librarise : aopalliance.jar aspectjrt.jar aspectjweaver.jar cglib-nodep-2.1_3.jar commons-*.jar dom4j-1.6.1.jar hibernate3.jar hibernate-*.jar junit.jar log4j-1.2.13.jar ojdbc14.jar spring-*.jar Database : Oracle 10g เริ่มต้นด้วย การ configure pool &#8220;Datasource&#8221; กันเลยดีกว่า Spring ไม่มี pool data source นะครับ เราก็เลยต้องไปใช้ data source ของ Jakarta Commons ที่ชื่อว่า BasicDataSource หรือจะใช้ ComboPooledDataSource ก็ได้นะครับ Spring มี [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=150&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>ก่อนอื่นอ่านเรื่อง DI จากเวปนี้ก่อนนะครับ<br />
<a href="http://www.martinfowler.com/articles/injection.html" target="_blank">Inversion of Control Containers and the Dependency Injection pattern</a></p>
<p><b>Librarise :</b><br />
aopalliance.jar<br />
aspectjrt.jar<br />
aspectjweaver.jar<br />
cglib-nodep-2.1_3.jar<br />
commons-*.jar<br />
dom4j-1.6.1.jar<br />
hibernate3.jar<br />
hibernate-*.jar<br />
junit.jar<br />
log4j-1.2.13.jar<br />
ojdbc14.jar<br />
spring-*.jar</p>
<p><b>Database :</b> Oracle 10g</p>
<p>เริ่มต้นด้วย การ configure pool <b>&#8220;Datasource&#8221;</b> กันเลยดีกว่า<br />
Spring ไม่มี pool data source นะครับ เราก็เลยต้องไปใช้ data source<br />
ของ Jakarta Commons ที่ชื่อว่า BasicDataSource หรือจะใช้ ComboPooledDataSource ก็ได้นะครับ<br />
Spring มี connection  2 อันนะครับ คือ<br />
1. DriverManagerDataSource จะ return connection ใหม่ทุกครั้งที่มีการเรียกใช้<br />
2. SingleConnectionDataSource มี connection อันเดียว ทุกครั้งที่เรียกจะได้ connection อันเดิมเสมอ<br />
(เขียนไปงั้น ไม่น่าใช้ทั้งคู่อะ)</p>
<p>ตัวอย่างผมใช้ BasicDataSource นะครับ</p>
<pre>
&lt;bean id="dataSource"
	class="org.apache.commons.dbcp.BasicDataSource"&gt;
	&lt;property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /&gt;
	&lt;property name="url" value="jdbc:oracle:thin:@192.168.1.101:1521:orcl" /&gt;
	&lt;property name="username" value="xxxx" /&gt;
	&lt;property name="password" value="xxxx" /&gt;
	&lt;property name="initialSize" value="5" /&gt;
	&lt;property name="maxActive" value="10" /&gt;
&lt;/bean&gt;
</pre>
<p>ค่าที่ set ให้กับ property ก็เหมือนกับการที่ set ให้กับ connection pool ทั่วไปนะครับ</p>
<p><b>&#8220;sessionFactory&#8221;</b> ขอยกตัวอย่างโดยการใช้ xml mapping file ธรรมดา<br />
เราก็ต้องใช้ LocalSessionFactoryBean ของ spring ในการสร้าง sessionFactory</p>
<pre>
&lt;bean id="sessionFactory"
	class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;
	&lt;property name="dataSource" ref="dataSource" /&gt;
	&lt;property name="mappingResources"&gt;
		&lt;list&gt;
			&lt;value&gt;domain/Signon.hbm.xml&lt;/value&gt;
		&lt;/list&gt;
	&lt;/property&gt;
	&lt;property name="hibernateProperties"&gt;
		&lt;props&gt;
			&lt;prop key="hibernate.dialect"&gt;org.hibernate.dialect.Oracle10gDialect&lt;/prop&gt;
		&lt;/props&gt;
	&lt;/property&gt;
&lt;/bean&gt;
</pre>
<p>โดยจะ inject dataSource ที่เราพึ่งสร้างไปให้มันด้วย<br />
property mappingResources : เป็น List เอาไว้กำหนด path ของ<br />
mapping files ที่ต้องการให้มัน map Domain Class กับ Table<br />
property hibernateProperties : เป็น prop เอาไว้กำหนดค่า config ต่างของ hibernate session</p>
<p><b>&#8220;hibernateTemplate&#8221;</b> หน้าที่หลักของ hibernateTemplate<br />
คือ open,close hibernateSession และแปลง hibernateException เป็น<br />
Data access Exception ของ Spring ที่เป็น uncheck Exception ทั้งหมด</p>
<pre>
&lt;bean id="hibernateTemplate"
	class="org.springframework.orm.hibernate3.HibernateTemplate"&gt;
	&lt;property name="sessionFactory" ref="sessionFactory" /&gt;
&lt;/bean&gt;
</pre>
<p>inject sessionFactory เข้าไปให้มัน</p>
<p>Table ที่ใช้เอามาจาก ตัวอย่าง jpetstore ของ spring ชื่อ Table &#8220;signon&#8221;<br />
ผมมาแก้ไขนิดหน่อย โดยเพิ่ม field signon_gen เป็น surrogate key<br />
(ไม่เกี่ยวกันตัวอย่างที่ผมจะทำหลอกนะครับ เพียงแต่เห็น Table ไหนไม่มี<br />
surrogate key แล้วมันขัดใจยังไงไม่รู้)<br />
<strong>Domain Class &#8220;Signon.class&#8221;</strong></p>
<pre>package domain;
public class Signon implements java.io.Serializable {
	private Long signonGen;
	private String username;
	private String password;
	public Signon() {
	}
	public Signon(String username, String password) {
		this.username = username;
		this.password = password;
	}
	// stripped out the accessor method and mutator method
}</pre>
<p><strong>Hibernate XML Mappings &#8220;signon.hbm&#8221;</strong></p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt;
&lt;hibernate-mapping&gt;
&lt;class name="domain.Signon" table="SIGNON" schema="SYSTEM"&gt;
	&lt;id name="signonGen" type="java.lang.Long"&gt;
		&lt;column name="SIGNON_GEN" precision="22" scale="0" /&gt;
		&lt;generator  class="assigned"  /&gt;
	&lt;/id&gt;
	&lt;property name="username" type="java.lang.String"&gt;
		&lt;column name="USERNAME" length="25" not-null="true" /&gt;
	&lt;/property&gt;
	&lt;property name="password" type="java.lang.String"&gt;
		&lt;column name="PASSWORD" length="25" not-null="true" /&gt;
	&lt;/property&gt;
&lt;/class&gt;
&lt;/hibernate-mapping&gt;</pre>
<p><strong>Data Access Object (DAO) &#8220;SignonDao.class&#8221;,&#8221;SignonDaoImpl.class&#8221;</strong></p>
<pre>package dao;
public interface SignonDao {
	public Signon findByUsername(String username) ;
}
package dao;
// stripped out the import statement
public class SignonDaoImpl extends HibernateDaoSupport implements SignonDao {
	public Signon findByUsername(String username) {
		String hql = " from Signon s where s.username = :username ";
		List signons = (List)
			getHibernateTemplate().findByNamedParam(hql, "username", username);
		return signons != null ? signons.get(0) : null;
	}
}</pre>
<p>DAO นี้มี method เดียวนะครับ คือ findByUsername เอาไว้ค้นหา User จาก username<br />
ตัวอย่าง เขียน hql ค้นหา class Signon where ด้วย username<br />
แล้ว getHibernateTemplate ที่ได้มาจากการ extends HibernateDaoSupport ของ Spring<br />
แล้วใช้ method findByNamedParam จาก hibernateTemplate ส่ง parameter ไป 3 ตัว คือ<br />
1. hql : hql<br />
2. &#8220;username&#8221; : ชือ parameter ใน hql ที่ต้องการ binding parameter<br />
3. username : value ที่ต้องการ binding<br />
จะได้ return กลับมาเป็น List ของ Object แล้วก็มา cast เป็น List&lt;Signon&gt;</p>
<p>สร้าง instance <b>signonDao</b> </p>
<pre>
&lt;bean id="signonDao" class="dao.SignonDaoImpl"&gt;
	&lt;property name="hibernateTemplate" ref="hibernateTemplate" /&gt;
&lt;/bean&gt;
</pre>
<p>โดยส่ง hibernateTemplate เข้าไปด้วย<br />
หรือจะฉีด sessionFactory เข้าไปใน class ที่ extends HibernateDaoSupport<br />
เลยก็ได้นะครับ ตอนนี้เราก็มี Dao พร้อมใช้งานแล้วครับ<br />
(class ที่ extends มาจาก  HibernateDaoSupport จะได้รับการสืบทอด ็็setHibernateTemplate,setSessionFactory มาด้วย )</p>
<p><b>Data Access Context &#8220;application-data.xml&#8221;</b><br />
เสร็จแล้วหน้าตาของ context ของ Data access Layer จะมีหน้าตาแบบนี้นะครับ</p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd"&gt;
&lt;!-- config data source and hibernate session --&gt;
&lt;bean id="dataSource"
	class="org.apache.commons.dbcp.BasicDataSource"&gt;
	&lt;property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /&gt;
	&lt;property name="url" value="jdbc:oracle:thin:@192.168.1.101:1521:orcl" /&gt;
	&lt;property name="username" value="xxxx" /&gt;
	&lt;property name="password" value="xxxx" /&gt;
	&lt;property name="initialSize" value="5" /&gt;
	&lt;property name="maxActive" value="10" /&gt;
&lt;/bean&gt;
&lt;bean id="sessionFactory"
	class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;
	&lt;property name="dataSource" ref="dataSource" /&gt;
	&lt;property name="mappingResources"&gt;
		&lt;list&gt;
			&lt;value&gt;domain/Signon.hbm.xml&lt;/value&gt;
		&lt;/list&gt;
	&lt;/property&gt;
	&lt;property name="hibernateProperties"&gt;
		&lt;props&gt;
			&lt;prop key="hibernate.dialect"&gt;org.hibernate.dialect.Oracle10gDialect&lt;/prop&gt;
		&lt;/props&gt;
	&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="hibernateTemplate"
	class="org.springframework.orm.hibernate3.HibernateTemplate"&gt;
	&lt;property name="sessionFactory" ref="sessionFactory" /&gt;
&lt;/bean&gt;
&lt;!-- config data source and hibernate session --&gt;
&lt;!-- declare DAO --&gt;
&lt;bean id="signonDao" class="dao.SignonDaoImpl"&gt;
	&lt;property name="hibernateTemplate" ref="hibernateTemplate" /&gt;
&lt;/bean&gt;
&lt;!-- declare DAO --&gt;
&lt;/beans&gt;
</pre>
<p>มาถึงตอนนี้ resource ของ Data access Layer ก็เสร็จหมดแล้วนะครับ<br />
มาต่อกันที่ Service Layer ดีกว่า</p>
<p><strong>Service Object (หรือ BO) &#8220;UserService .class&#8221;,&#8221;UserServiceImpl .class&#8221;</strong></p>
<pre>package service;
public interface UserService {
	public Signon signon(String userName, String password);
}
package service;
public class UserServiceImpl implements UserService {
	SignonDao signonDao;
	public UserServiceImpl(SignonDao signonDao) {
		this.signonDao = signonDao;
	}
	public Signon signon(String userName, String password) {
		if (GenericValidator.isBlankOrNull(username))
			throw new IllegalArgumentException();
		if (GenericValidator.isBlankOrNull(password))
			throw new IllegalArgumentException(); 

		Signon signon = signonDao.findByUsername(username);
		return signon != null &amp;&amp; signon.getPassword().equals(password ) ? signon : null ;
	}
}</pre>
<p>Service นี่ก็มี method เดียวเหมือนกัน คือ signon<br />
ก่อนอื่นก็ validate ก่อนเลยนะครับ<br />
แล้วก็ส่ง username ไปค้นหา Object Signon return ออกไป</p>
<p><b>transactionManager:</b></p>
<pre>
&lt;bean id="transactionManager" class="orm.hibernate3.HibernateTransactionManager"&gt;
	&lt;property name="sessionFactory" ref="sessionFactory" /&gt;
&lt;/bean&gt;
</pre>
<p>สร้าง instance ของ HibernateTransactionManager โดยส่ง sessionFactory เข้าไป<br />
(instance เดียวกับ ที่ฉีดเข้าไปใน HibernateTemplate )</p>
<p><b>tag tx:advice:</b></p>
<pre>
&lt;tx:advice id="txAdvice" transaction-manager="transactionManager"&gt;
	&lt;tx:attributes&gt;
		&lt;tx:method name="signon" propagation="REQUIRED" /&gt;
	&lt;/tx:attributes&gt;
&lt;/tx:advice&gt;
</pre>
<p>tx:method ใช้กำหนดรายละเอียดของ Transection ของแต่ละ Method</p>
<p><b>tag aop:config:</b></p>
<pre>
&lt;aop:config&gt;
	&lt;aop:pointcut id="userServiceOperation"
		expression="execution(* *..UserServiceImpl.*(..))" /&gt;
	&lt;aop:advisor pointcut-ref="userServiceOperation" advice-ref="txAdvice" /&gt;
&lt;/aop:config&gt;
</pre>
<p>pointcut ใช้ AspectJ ประกาศ expression ที่จะ control Transection</p>
<p><b>userService:</b></p>
<pre>
&lt;bean id="userService" class="service.UserServiceImpl"&gt;
	&lt;constructor-arg ref="signonDao" /&gt;
&lt;/bean&gt;
</pre>
<p>สร้าง instance UserServiceImpl ส่ง signonDao เข้าไป</p>
<p><b>Service Context &#8220;application-service.xml&#8221;</b><br />
เสร็จแล้วหน้าตาของ context ของ Service Layer จะมีหน้าตาแบบนี้นะครับ</p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop.xsd

http://www.springframework.org/schema/tx

	http://www.springframework.org/schema/tx/spring-tx.xsd"&gt;

&lt;!-- declare transection --&gt;
&lt;bean id="transactionManager" class="orm.hibernate3.HibernateTransactionManager"&gt;
	&lt;property name="sessionFactory" ref="sessionFactory" /&gt;
&lt;/bean&gt;

&lt;tx:advice id="txAdvice" transaction-manager="transactionManager"&gt;
	&lt;tx:attributes&gt;
		&lt;tx:method name="signon" propagation="REQUIRED" /&gt;
	&lt;/tx:attributes&gt;
&lt;/tx:advice&gt;

&lt;aop:config&gt;
	&lt;aop:pointcut id="userServiceOperation"
		expression="execution(* *..UserServiceImpl.*(..))" /&gt;
	&lt;aop:advisor pointcut-ref="userServiceOperation" advice-ref="txAdvice" /&gt;
&lt;/aop:config&gt;
&lt;!-- declare transection --&gt;

&lt;!-- declare service --&gt;
&lt;bean id="userService" class="service.UserServiceImpl"&gt;
	&lt;constructor-arg ref="signonDao" /&gt;
&lt;/bean&gt;
&lt;!-- declare service --&gt;
&lt;/beans&gt;
</pre>
<p><b>UnitTest &#8220;UnitTest.class&#8221;</b></p>
<pre>
package test;
public class UnitTest {
	Logger log = LogManager.getLogger(this.getClass());
	@Test
	public void test() {
		String[] contextFile = { "application-data.xml", "application-service.xml" };
		ApplicationContext context = new ClassPathXmlApplicationContext(contextFile);
		UserService userService = (UserService) context.getBean("userService");
		Signon signon = userService.signon("j2ee", "j2ee");
		log.debug(signon.getUsername() + signon.getPassword());
	}
}
</pre>
<p>กำหนด context file  ของ spring ที่จะใช้งาน<br />
create instance ClassPathXmlApplicationContext ส่ง array ที่เก็บ ชื่อของ context file เข้าไป<br />
(ClassPathXmlApplicationContext มันจะไปหา file ที่ส่งเข้าไปจาก classPath)<br />
return ออกมาเป็น ApplicationContext แล้วก็ Get Bean ที่ต้องการใช้งาน</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iknight.wordpress.com/150/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iknight.wordpress.com/150/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iknight.wordpress.com/150/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iknight.wordpress.com/150/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iknight.wordpress.com/150/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iknight.wordpress.com/150/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iknight.wordpress.com/150/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iknight.wordpress.com/150/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iknight.wordpress.com/150/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iknight.wordpress.com/150/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iknight.wordpress.com/150/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iknight.wordpress.com/150/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iknight.wordpress.com/150/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iknight.wordpress.com/150/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=150&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iknight.wordpress.com/2009/07/11/get-start-spring-with-hibernate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d2a8255a0478cf3c58c9bd829d1f7ba2?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">iknight</media:title>
		</media:content>
	</item>
		<item>
		<title>Favor composition over inheritance</title>
		<link>http://iknight.wordpress.com/2009/04/18/favor-composition-over-inheritance/</link>
		<comments>http://iknight.wordpress.com/2009/04/18/favor-composition-over-inheritance/#comments</comments>
		<pubDate>Sat, 18 Apr 2009 11:35:58 +0000</pubDate>
		<dc:creator>iknight</dc:creator>
				<category><![CDATA[OOAD]]></category>

		<guid isPermaLink="false">http://iknight.wordpress.com/?p=115</guid>
		<description><![CDATA[Inheritance is a powerful way to achieve code reuse, but it is not always the best tool for the job. Used inappropriately, it leads to fragile software. ตอนแรกว่าจะยกตัวอย่างจาก Effective Java แต่อ่านแล้วงงๆ อ่านยาก ตัวอย่างอ่านแล้วไม่ค่อยเห็นภาพเท่าไหร่ เลยเอาตัวอย่างจาก Head First Design Pattern ดีกว่า เป็น ตัวอย่างที่อธิบายเรื่อง Strategy Pattern แต่เนื้อหาพูดถึงเรื่อง การใช้ composition แทนการใช้ inheritence ได้ดีทีเดียว ผมจะ focus เรื่องการใช้ composition แทน inheritance [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=115&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><b><i>Inheritance is a powerful way to achieve code reuse,<br />
but it is not always the best tool for the job.<br />
Used inappropriately, it leads to fragile software.</i></b></p>
<p>ตอนแรกว่าจะยกตัวอย่างจาก Effective Java แต่อ่านแล้วงงๆ อ่านยาก<br />
ตัวอย่างอ่านแล้วไม่ค่อยเห็นภาพเท่าไหร่ เลยเอาตัวอย่างจาก Head First Design Pattern ดีกว่า</p>
<p>เป็น ตัวอย่างที่อธิบายเรื่อง  Strategy Pattern แต่เนื้อหาพูดถึงเรื่อง การใช้<br />
composition แทนการใช้ inheritence ได้ดีทีเดียว ผมจะ focus เรื่องการใช้<br />
composition แทน inheritance ยังไง และทำไมการใช้ inheritance<br />
ถึงไม่สมควรทำ(จริงๆแล้ว พื้นฐานการออกแบบก็สำคัญกว่า Pattern ต่างอยู่แล้วหละครับ)</p>
<p>ตัวอย่าง พูดถึง duck simulation game ที่เป็ดมีความสามารถหลากหลาย<br />
เช่น swim,quack การออกแบบ เริ่มต้นคือการ เขียน superclass เป็น class<br />
ต้นแบบของเป็ด(Duck) แล้วก็ให้เป็ดแต่ละชนิด extends ไป</p>
<pre>
public abstract class Duck {
abstract void display();
	public void quack() {
	}
	public void swim() {
	}
}
</pre>
<p>ต่อมาก็มีความต้องการให้เป็ด บินได้ ก็ไม่ยากอะไรครับ ก็เพิ่ม method fly<br />
ที่  Class Duck,subclass ที่ extends ไปก็ได้รับการ สืบทอด method fly</p>
<pre>
	public void fly() {
	}
</pre>
<p>ต่อมาก็มีความต้องการ เป็ดตัวใหม่ ก็ไม่น่าจะยากอะไรครับ ก็ extends Class Duck ไป<br />
แต่เป็ดที่ต้องการเป็น &#8220;robber duckies&#8221;(robber duckies เป็นเป็ดที่ ร้องไม่ได้ )<br />
ปัญหาก็เริ่มเกิดแล้วครับ เพราะ เป็ดทุกตัวที่ extends Duck จะได้รับการ สืบทอด method quack</p>
<p>หรือแม้กระทั่ง method fly ที่พึ่งเพิ่มเข้าไป subclass ของ Duck ก่อนหน้านี้<br />
ก็ไม่เคยมีความต้องการ method fly เลย </p>
<p>&#8221; เมื่อคุณเพิ่ม method ที่ super class ก็เท่ากับว่าคุณเพิ่ม method ที่ไม่สมควรให้กับ บาง subclass &#8220;</p>
<p><b><i>&#8220;What he thought was a great use of inheritance for the<br />
purpose of reuse hasn&#8217;t turned out so well when it comes to maintenance &#8220;</i></b></p>
<p>ทำไงดี ก็ต้องไป overide method ที่ไม้ต้องการ ให้มันไม่ต้องทำงานอะไร<br />
ก็ดูเหมือนดีนะครับแต่แค่คิดก็เหนื่อยแล้วครับ ต้องทำ subclass ทุกตัวที่<br />
extends Duck (เป็ดตัวไหนไม้ต้องการให้ทำอะไรก็ตาม overide เอา)</p>
<pre>
	@Overide
	public void fly(){
		//...
	}
</pre>
<p>ถ้ามีเป็ด 5 ตัวที่บินไม่ได้ ก็ต้อง copy paste ไปทุกตัวก็เริ่ม douplicated code</p>
<p>ทำไงดี สร้าง interface สำหรับ method ที่บาง subclass ไม่ต้องการ<br />
แล้วถ้า subclass ไหนต้องการ method นี้ก็ให้ implement ไป </p>
<pre>
public abstract class Duck {
	abstract void display();
		public void swim() {
	}
}
public interface FlyAble {
	public void fly();
}
public interface QuackAble {
	public void quack();
}
</pre>
<p>เป็ดทุกตัวต้อง extends Duck แล้วถ้าตัวไหนต้องการให้ fly หรือ quack<br />
ก็ implement FlyAble หรือ QuackAble  เอาครับ</p>
<p>ทำแบบนี้ก็ดูเหมือนดีนะครับ แต่ลองคิดดูถ้าเป็ดตัวไหนมีพฤติกรรมการบินที่เหมือนกัน<br />
ก็ต้อง implement method fly เหมือนกัน และมี code เหมือนกัน</p>
<pre>
public class MallardDuck extends Duck implements FlyAble {
	public void fly(){
		// same perform fly
	}
}
public class RedheadDuck extends Duck implements FlyAble {
	public void fly(){
  		// same perform fly
	}
}
</pre>
<p>วิธีนี้ทำให้ ไม่สามารถ reuse code ได้นะครับ แต่ที่แย่กว่า คือ douplicated code<br />
ถ้าพฤติกรรมการบินแบบนี้เปลี่ยน ก็ต้องตามแก้ ทุก subclass<br />
<b><i>&#8220;Identify the aspects of your application<br />
that vary and separate them from what stays the same&#8221;</i></b><br />
ทำไงดี เขียน interface FlyBehavior แล้วก็ให้ fly แต่ละชนิด implements ไป</p>
<pre>
public interface FlyBehavior {
	public void   fly();
}
public class FlyNoWay implements FlyBehavior {
	public void fly() {
    		System.out.println("I can't fly");
	}
}
public class FlyRocketPowered implements FlyBehavior {
	public void fly() {
		System.out.println("I'm flying with a     rocket");
	}
}
</pre>
<p>class Duck ก็ถือ reference ของ FlyBehavior แล้วก็เขียน setFlyBehavior<br />
เพื่อรอรับ instance ของ class ที่ implements FlyBehavior ไป<br />
เวลาจะใช้ FlyBehavior ไหนก็ set ให้กับ class Duck</p>
<p><b><i>&#8220;Program to an interface, not an implementation&#8221;</i></b></p>
<pre>
public abstract class Duck {
	FlyBehavior flyBehavior;
	public void setFlyBehavior (FlyBehavior fb) {
		flyBehavior = fb;
	}
	public void performFly() {
		flyBehavior.fly();
	}
}
</pre>
<p>เสริมนิดๆ อย่างให้มอง interface เป็น type ของ class<br />
เหมือนกับ ที่มอง class เป็น type ของ instance นะครับ<br />
ตรงนี้สำคัญนะครับ จะทำให้ไม่สับสนการเลือกใช้ ระหว่าง<br />
interface กับ abstact class อืม อ่านแล้วงงๆ เดี๋ยวมาเล่าต่อ</p>
<p>การถือ reference ของ FlyBehavior นี้หละครับคือการ <strong>composition</strong><br />
การได้มาของ method fly มาจากการที่ FlyBehavior เป็นส่วนประกอบของ<br />
Duck ไม่ใช้ ได้รับจากการสืบทอด</p>
<p>จริงๆแล้ว การเขียน แบบ composition จะสามารถ reuse ได้มากกว่านะครับ<br />
คือถ้าเราเขียน แบบ composition ก็เหมือนกับว่าเราเขียนโปรแกรมเป็น<br />
componance เราสามารถเอา componance เหล่านี้ไป reuse ได้<br />
เรียกว่า componance reuse ไม่ใช้ code reuse<br />
spring ก็ promote การเขียนโปรแกรมให้เป็น componance ด้วย DI</p>
<p>แล้ว dependency ระหว่าง class ก็น้อยกว่ามากครับ<br />
แล้ว code ก็เข้าใจง่ายกว่าด้วยนะครับ</p>
<p><b><i>&#8220;Favor composition over inheritance&#8221;</i></b></p>
<p>เขียนไป เขียนมาไม่รู้จะเข้าใจหรือปล่าว เอาว่าน่าจะเห็นประโยชน์ของการใช้ composition แทนการใช้ inheritance บ้างนะครับ</p>
<p>reference :<br />
Effective Java(แค่ประโยคแรกครับ อ่านแล้วชอบเลยเอามาแปะไว้)<br />
Head First Design Pattern</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iknight.wordpress.com/115/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iknight.wordpress.com/115/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iknight.wordpress.com/115/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iknight.wordpress.com/115/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iknight.wordpress.com/115/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iknight.wordpress.com/115/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iknight.wordpress.com/115/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iknight.wordpress.com/115/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iknight.wordpress.com/115/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iknight.wordpress.com/115/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iknight.wordpress.com/115/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iknight.wordpress.com/115/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iknight.wordpress.com/115/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iknight.wordpress.com/115/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=115&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iknight.wordpress.com/2009/04/18/favor-composition-over-inheritance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d2a8255a0478cf3c58c9bd829d1f7ba2?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">iknight</media:title>
		</media:content>
	</item>
		<item>
		<title>Row Data Gateway</title>
		<link>http://iknight.wordpress.com/2009/03/22/row-data-gatway/</link>
		<comments>http://iknight.wordpress.com/2009/03/22/row-data-gatway/#comments</comments>
		<pubDate>Sun, 22 Mar 2009 14:16:35 +0000</pubDate>
		<dc:creator>iknight</dc:creator>
				<category><![CDATA[Pattern]]></category>

		<guid isPermaLink="false">http://iknight.wordpress.com/?p=100</guid>
		<description><![CDATA[ลักษณะของ Object จะมี method insert, update, delete เพื่อทำงานกับ Table ได Table หนึ่ง หรือ view ได view หนึ่ง และมีโครงสร้างข้อมูลเหมือนกับ row ใน table โดยแต่ละ column จะเป็น attribute ใน object แต่ละ instance จะเก็บข้อมูล 1 row ใน table หรือ view (ก็คล้ายๆกับ Table Data Gateway อะครับมี method insert, update, delete เหมือนกัน เพียงแต่ว่า Row Data Gateway จะเก็บข้อมูลด้วย ก็เหมือนกับเอา domain class กับ [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=100&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-thumbnail wp-image-103" title="22-3-2552-20-59-261" src="http://iknight.files.wordpress.com/2009/03/22-3-2552-20-59-261.png?w=200&#038;h=300" alt="22-3-2552-20-59-261" width="200" height="300" /></p>
<p>ลักษณะของ Object จะมี method insert, update, delete เพื่อทำงานกับ Table ได Table หนึ่ง หรือ view ได view หนึ่ง และมีโครงสร้างข้อมูลเหมือนกับ row ใน table โดยแต่ละ column จะเป็น attribute ใน object แต่ละ instance จะเก็บข้อมูล 1 row ใน table หรือ view (ก็คล้ายๆกับ Table Data Gateway อะครับมี method  insert, update, delete เหมือนกัน เพียงแต่ว่า Row Data Gateway จะเก็บข้อมูลด้วย ก็เหมือนกับเอา domain class กับ Table Data gateway มารวมกัน) โดย pattern นี้จะต้องมี finder object เอาไว้ค้นหาข้อมูล เพราะ method find ไม่ควรอยู่ใน Row Data Gatway (instance ของ Row Data Gatway จะเกิดได้ขึ้นก็ควรมีข้อมูล จาก row ใน base แล้ว)</p>
<p>ถ้าดูให้ดีแล้วนะครับมันก็เท่ากับว่าเอา Data Access Logic ไปใส่ไว้ใน domain class<br />
แล้วก็เขียน finder object ขึ้นมาเพื่อค้นหาข้อมูล ซึ่งก็เท่ากับว่าการใช้ pattern นี้ก็เหมือนกับบังคับให้ใช้ Value Object เพื่อส่งข้อมูลไป presentation layer เพราะ Data Access Logic ไม่ควรไปอยู่ที่  presentation layer</p>
<p>อย่าสับสนระหว่าง Row Data Gateway กับ Rich Domain Model นะครับ<br />
ความแตกต่างชัดเจนคือ Row Data Gateway เป็น anemic domain ที่ใส่<br />
Data Access Logic ลงไป แล้วเอา Business Logic ไปไว้ที่ Transaction Script<br />
ในขณะที่ Rich Domain Model เป็น domain ที่เก็บข้อมูลและใส่ Business Logic<br />
ลงไป แล้วเอา Data Access Logic เอาไปไว้ที่ Data Mapper</p>
<table width="100%" align="center" bgcolor="#CCCCCC" border="0" cellpadding="0" cellspacing="0">
<tr bgcolor="#AAAAAA">
<td align="center"><b>Data Access Layer</b></td>
<td><b>Business Layer</b></td>
<td rowspan="2"><b>include</b></td>
</tr>
<tr bgcolor="#AAAAAA">
<td align="center"><b>Date Source layer</b></td>
<td><b>Domain Layer</b></td>
</tr>
<tr>
<td align="center">Table Data Gateway</td>
<td align="center">Transaction Script</td>
<td>Anemic Domain</td>
</tr>
<tr>
<td align="center">Row Data Gateway</td>
<td align="center">Transaction Script</td>
<td>Anemic Domain  + Value Object</td>
</tr>
<tr>
<td align="center">Data Mapper</td>
<td align="center">Rich Domain</td>
<td>Value Object</td>
</tr>
</table>
<p>Rich Domain Model หาอ่านเอาใน PEAA นะครับเรื่อง Domain Model นั้นหละครับ<br />
Domain Model ของ martin flower rich เสมอไม่มี Anemic Domain Model เลยไม่ได้เขียนถึง แต่ไปเขียนใน bliki ว่า Anemic Domain Model เป็น anti-patterns (กำ ผมก็ใช้อยู่)</p>
<p>แนะนำให้อ่าน PEAA ของ martin flower นะครับมี Pattern ของ Enterprise Application ให้เลือกใช้มากมาย และที่พูดคุยกันในเว็บบอร์ดทั่วไปถ้าพูดถึง Pattern ในหนังสือเล่มนี้มักจะไม่ค่อยอธิบายกันส่วนมากแนะให้ไปอ่านกันเอง (ราวกับว่าทุกต้องมียังไงอย่างนั้น) แต่ที่สำคัญมากๆๆๆ คือหนังสือเล่มนี้เก่ามากแล้วครับอ่านแล้วคนอ่านก็จะเก่าไปด้วยเลยครับ บางอย่างก็มีคนเอามา implement แล้ว Hibernate, EJB, Spring, Struts<br />
ซึ่งก็รู้สึกว่าถ้าได้ใช้ tecnology อยู่แล้วก็ไม่จำเป็นต้องอ่านก็ได้มั้ง (ขี้เกียจอ่าน) หรือจะว่าก็ดีเหมือนกันจะได้ไม่ใช้ tecnology ในทางที่ผิดๆ แต่ก็จะได้รู้ pattern ที่จำเป็นต้องรู้ เช่นเรื่อง Concurrency, Lazy Load แบบดั่งเดิมเป็นยังไง, Money Pattern จะได้คิดตังไม่ผิด</p>
<p>ส่วนผมไม่ได้อ่านทั้งหมดเอาเป็น reference มากกว่า อ่านเท่าที่จำเป็นจำเท่าที่จำได้<br />
มิงั้นตั้งหน้าตั้งตาตะบันอ่านมีหวังหลับแน่นอน ไว้คุ้นๆจะใช้แล้วค่อยมาอ่านดีกว่า</p>
<p>กลายเป็นเชียร์ให้ซื้อหนังสือไปซะงั้น ได้ไงก็ไม่รู้(พิมพ์เพลิน)<br />
reference : PEAA</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iknight.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iknight.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iknight.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iknight.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iknight.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iknight.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iknight.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iknight.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iknight.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iknight.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iknight.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iknight.wordpress.com/100/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iknight.wordpress.com/100/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iknight.wordpress.com/100/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=100&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iknight.wordpress.com/2009/03/22/row-data-gatway/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d2a8255a0478cf3c58c9bd829d1f7ba2?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">iknight</media:title>
		</media:content>

		<media:content url="http://iknight.files.wordpress.com/2009/03/22-3-2552-20-59-261.png?w=60" medium="image">
			<media:title type="html">22-3-2552-20-59-261</media:title>
		</media:content>
	</item>
		<item>
		<title>Table Data Gateway</title>
		<link>http://iknight.wordpress.com/2009/03/18/table-date-gateway/</link>
		<comments>http://iknight.wordpress.com/2009/03/18/table-date-gateway/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 05:47:30 +0000</pubDate>
		<dc:creator>iknight</dc:creator>
				<category><![CDATA[Pattern]]></category>

		<guid isPermaLink="false">http://iknight.wordpress.com/2009/03/18/test-syntax-highlighter/</guid>
		<description><![CDATA[Table Date Gateway คือ Object ที่ไว้จัดการกับ Database (CRUD) โดยลักษณะของ Object จะมี method find, insert, update, delete เพื่อทำงานกับ Table ได Table หนึ่ง หรือ view ได view หนึ่ง โดยแต่ละ method จะ map input parameter ใส่ SQL แล้วสั่ง excute การทำงานจะเป็นแบบ stateless คือไม่เก็บสถานะไว้ทำงานครั้งเดียวจบ ลักษณะการทำงานการเรียก function ส่วนมากแล้วเวลาใช้ pattern นี้จะใช้ 1 Object ต่อ 1 Table แต่จริงแล้ว สามารถใช้ 1 Object ต่อ 1 [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=82&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-89" title="21-3-2552-15-45-49" src="http://iknight.files.wordpress.com/2009/03/21-3-2552-15-45-49.png?w=250" alt="21-3-2552-15-45-49" width="250" height="" /></p>
<p>Table Date Gateway คือ Object ที่ไว้จัดการกับ Database (CRUD) โดยลักษณะของ Object จะมี method find, insert, update, delete เพื่อทำงานกับ Table ได Table หนึ่ง หรือ view ได view หนึ่ง โดยแต่ละ method จะ map input parameter ใส่ SQL แล้วสั่ง excute การทำงานจะเป็นแบบ stateless คือไม่เก็บสถานะไว้ทำงานครั้งเดียวจบ ลักษณะการทำงานการเรียก function ส่วนมากแล้วเวลาใช้ pattern นี้จะใช้ 1 Object ต่อ 1 Table แต่จริงแล้ว สามารถใช้ 1 Object ต่อ 1 view ที่สนใจ หรือ 1 Object ต่อ Table ทั้งหมดใน base ก็ได้ แต่ที่แน่ๆ ใช้ 1 Object ต่อ 1 Domain Class (anemic domain นะ มิใช่ rich domain) หน้าที่หลักของ Table Date Gateway คือจัดการกับ Data Access Logic ไม่ควรมี Business Logic ปน (เคยอ่านเจอว่า สามารถมี Business ปนได้ แต่เท่าที่จำเป็น) แต่ผมว่าไม่ควรมีเลยมากกว่า ยังไงก็แล้วแต่สดวกครับงานใครงานมัน ถ้ามีแล้วทำงานง่ายขึ้น ประสิทธิภาพดีขึ้นก็แล้วแต่ แต่อย่าลืมว่า Table Date Gateway ต้อง Focus การทำงานที่ Data Access Logic</p>
<p>reference : PEAA</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/iknight.wordpress.com/82/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/iknight.wordpress.com/82/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/iknight.wordpress.com/82/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/iknight.wordpress.com/82/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/iknight.wordpress.com/82/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/iknight.wordpress.com/82/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/iknight.wordpress.com/82/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/iknight.wordpress.com/82/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/iknight.wordpress.com/82/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/iknight.wordpress.com/82/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/iknight.wordpress.com/82/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/iknight.wordpress.com/82/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/iknight.wordpress.com/82/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/iknight.wordpress.com/82/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=iknight.wordpress.com&amp;blog=5323556&amp;post=82&amp;subd=iknight&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://iknight.wordpress.com/2009/03/18/table-date-gateway/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/d2a8255a0478cf3c58c9bd829d1f7ba2?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">iknight</media:title>
		</media:content>

		<media:content url="http://iknight.files.wordpress.com/2009/03/21-3-2552-15-45-49.png" medium="image">
			<media:title type="html">21-3-2552-15-45-49</media:title>
		</media:content>
	</item>
	</channel>
</rss>
