AOP :: Aspect-Oriented Programming
Posted by PunNeng, Thu Apr 12 03:30:00 UTC 2007
Aspect-Oriented Programming หรือ การโปรแกรมเชิงลักษณะ(พี่ใหม่เรียกว่างั้น) อธิบายยากจริงวุ้ย เอากรณีตัวอย่างเลยละกัน สุดฮิตเรื่อง logging
เริ่มต้นจาก อยากจะจัดการกับ product ของตัวเอง โดยมีความต้องการให้มันทำหน้าที่(concern) ดังนี้
- เก็บราคาขายของ product ต่างๆ
- เมื่อมีการเปลี่ยนแปลงราคา จะต้องถูกบันทึกข้อมูล
ก็สร้าง product กันก่อน
1 2 3 4 5 6 7 8 9 | class Product attr_reader :price def initialize price = 0.0 end def setPrice(p) price = p end end |
concern ข้อที่หนึ่ง ก็จัดการไปได้ละ (ในความเป็นจริงจะมี method ที่ีจำเป็นมากกว่านี้) มาดูข้อสองบ้าง จะต้องบันทึกข้อมูล เอาเป็นเขียนใส่ log file ละกัน(สุดฮิต) เวลามันเปลี่ยนแปลง ก็ให้มันบันทึกทีนึง
1 2 3 4 5 6 7 8 | class Logger def initialize # open log file end def writeLog(msg) # write msg to log file end end |
ทีนี้ก็เรียก writeLog ใน Product class
1 2 3 4 5 6 7 8 9 10 11 | class Product attr_reader :price def initialize @price = 0.0 @logger = Logger.new end def setPrice(p) @logger.writeLog("#{price} is changed to #{p}") @price = p end end |
มาถึงตรงนี้ มันก็ยังไม่มีปัญหาหรอกครับ แต่มันดูผิดแนวคิดจาก Encapsulation ไปหน่อย จาก Managing Software Defects in an Object-Oriented Environment ตรงส่วนของ encapsulation เขาบอกประมาณว่า
ใน encapsulation นั้น ก้อน object จะถูกประกาศเป็นชุดหรือกลุ่มของ concern ที่ีมีความสัมพันธ์กัน
หรืออีกนัยหนึ่งคือ Object น้ันๆ ก็ควรจะเกี่ยวกับ Object น้ันๆ(เป็น modular) อย่าเอาอย่างอื่นมาเกี่ยว(เป็นไปได้ยาก) แต่ดู concern ตัวที่สองแล้ว มันไม่ค่อยจะสัมพันธ์กันเท่าไหร่ class นี้ จึงเกิดการ crosscut ขึ้น ซึ่งเกิดจากไอ้ concern ตัวที่สองนี่แหละ ไอ้นี่แหละ เรียกว่า crosscutting concern
crosscutting concern หมายความว่า ลักษณะหนึ่งๆ ที่ไปขวาง ไปกระทบ ไปกวนประสาท concern หลัก ซึ่งในที่นี้ ก็น่าจะเกี่ยวกับ product เท่านั้น
เมื่อมี concern เพิ่มมาเรื่อยๆ ทั้งที่สัมพันธ์และไม่สัมพันธ์กับ concern หลัก จะทำให้ code เรามันกระจัดกระจาย(Code Scattering) และยุ่งเหยิง(Tangled code) เพิ่มนั่น ปะนี่ เอาไอ้นั่นเข้า เอาไอ้นี่ออก เพื่อทำให้ concern มันสมบูรณ์ คนออกแบบกับโปรแกรมเมอร์มันก็ตายสิครับ =='
โอ้ววว กิจการขายดิบขายดี จนต้องขายของอย่างอื่นอีก ก็ต้องขอขอบคุณ OO ละครับ ที่มันกลไก Inheritance ไว้ให้ใช้ ก็ทำการ extend Product class ไปเลย
ผมเล็งเห็นว่าการบันทึกข้อมูลต่างๆ มันสำคัญ เพราะฉะนั้น ใน product ชิ้นใหม่ ผมจะเพิ่ม concern ไปอีก คือ จะเพิ่มการบันทึกเพิ่มมากขึ้นในส่วนที่จำเป็น และจะมี method อย่างอื่นเสริมเข้ามาด่้วย แต่ไม่เกี่ยวกับ Product class ตัวแรกนะ
ปัญหามาแล้ว มองกันไกลๆ code มันจะไม่น้อยอย่างนี้ มันจะอิรุงตุงนัง ยุ่งเหยิงไปหมด เพียงแค่เติมเต็มเจ้า concern ที่เพิ่มเติมเข้ามาเท่าน้ัน ตัว AOP นี้แล จะมาช่วยลดความยุ่งเหยิงพวกนี้ออกไป
จัดการมันใหม่(refactor) ดีไหม ??
มาดูว่า AOP จะช่วยแก้ไขปัญหานี้ได้ยังไง
ถ้าใช้ AOP แล้ว เราจะต้องแยกไอ้ concern ต่างๆ นานา ออกมาจัดการได้ ตามความเหมาะสมก่อน แล้วค่อยเตรียมกลไกการจัดการ concern ที่มันเกิดการ crosscut
AOP ต้องใช้ tools ช่วย โดยมีสองส่วนหลักๆ คือ
- ภาษาที่ใช้เขียน code ปกติ เรียกว่า component language
- ภาษาที่ใช้เขียน code ฝั่ง concern เพื่อเอาไปต่อกับ component language จะเรียกว่า aspect language
หลังจากได้ tools มาแล้ว จะทำอะไรกับมันได้บ้าง1 เราต้องมี
- Join point คือ จุดเชื่อม เป็นจุดที่เราจะระบุว่าจะให้ aspect ของเราทำงานที่ไหนบน source code ซึ่งเราจะระบุได้ ณ จุดที่เห็นกันจะๆ เช่น class, method หรือ exception เป็นต้น
- Pointcut คือ จุดตัด เป็นที่ที่เราจะระบุ join point ว่าจะให้ join point อันไหน ทำงานอะไร(จัดการกับ concern อะไร) ก็ตรงนี้แล
- Advice คือ การลำดับเหตุการณ์ เป็นตัวบอกว่าจะให้ทำก่อน(before) หรือหลัง(after)การเรียก pointcut ซึ่งใน AspectJ มีหลายรูปแบบ เช่น before, after หรือ around เป็นต้น
- Inner-Type Declaration คือ การประกาศในก้อน aspect ของเรา อาจจะเป็น method หรือตัวแปร ที่ไว้ใช้ในการทำงานที่เราระบุไว้กับ pointcut
คราวหน้าผมจะมา implement ให้ดู
สรุปเล็กน้อย
AOP เป็น concept ของการเขียนโปรแกรมอีกอย่างหนึ่ง ถูกคิดค้นโดย Gregor Kiczales และทีมของเขาที่ Xerox PARC มีจุดประสงค์เพื่อแยก concern ออกมา โดยเฉพาะสิ่งที่เรียกว่า crosscutting concern ให้ตัว class ที่เราใช้งานมันมีลักษณะเป็น module มากขึ้น
AOP จะไม่มาแทนที่ OOP แต่มันเป็นส่วนเสริมที่ทำให้ OOP มีประสิทธิภาพมากยิ่งขึ้น
1ข้ออ้างอิงมาจาก AspectJ ก่อนละกัน เพราะที่ผมใช้ จะใช้ AspectR มันค่อนข้างจะเหมือนกัน
ข้อมูลจาก
http://en.wikipedia.org/wiki/Cross-cutting_concern
http://en.wikipedia.org/wiki/Aspect-oriented_programming
http://en.wikipedia.org/wiki/Cross-cutting_concern
http://en.wikipedia.org/wiki/Aspectj
ฯลฯ มันเยอะครับ 4 เว็บหลัก แล้วตาม link ใน page ไปเรื่อยๆ ละกันนะครับ
ขอบคุณมากครับ อธิบายได้เข้าใจดีมาก