Group Blog
 
All Blogs
 
Bad OOP Design

วันนี้เป็นวันที่เริ่ม Implement Windows Service แบบจริงๆ จังๆ ดู พอดูโค้ดเก่าที่เคยทำไว้ ผมพบว่าบางสิ่งที่ผมคิดว่าเป็น Bad Design ใน OOP 

- การนำ ErrorMessage เข้าไปรวมในคลาสรับส่งข้อมูล

จริงอยู่ว่าการรับส่งข้อมูลระหว่างฐานข้อมูล เน็ตเวิร์ก หรือ Thread ต่างๆ บนโปรแกรมเดียวกัน ควรจะมีตัวบ่งบอกว่าการรับส่งข้อมูลสำเหร็จมั้ย และถ้าไม่สำเร็จเกิดจากอะไร แต่ที่ผมพบคือ การรวม ErrorMessage และ Error ที่เกิดเข้าไปในคลาสรับส่งข้อมูลเลยทันที เช่น

class SomeMessage

{

object Content1;

object Content2;

bool IsSuccess;

string ErrorMessage;

}

การ Design Class แบบนี้นั้นถึงใครจะมองว่ายังไง แต่ผมคิดว่ามันแย่มากๆ เหตุผลเพราะเมื่อมี Instance ของคลาสดังกล่าวออกมา เราจำเป็นต้องเช็คตลอดเวลาว่ามันมี ErrorMessage ติดมาด้วยหรือเปล่าก่อนใช้ ซึ่งเรามีเครื่องมือที่มีประสิทธิภาพอย่าง OOP แล้วทำไมเราต้องมานั่งเช็คแบบนี้อีก ลองนึกภาพของหลักการ OOP ที่มองทุกๆ Instance เป็นวัตถุ ถ้าเราต้องมานั่งเช็คด้วยมือตลอดเวลาว่าวัตถุที่เราใช้งานมีตำหนิหรือเปล่า (Error หรือไม่) มันก็ดูผิดประหลาด

ถ้าเอาให้เห็นภาพผมลองยกตัวอย่างว่าเรามีคำสั่ง

ProcessMessage(SomeMessage Parameter)

ถ้าเรา Design แบบข้างบนแปลว่าทุกครั้งที่เราเรียก ProcessMessage ต้องใช้อย่างน้อย 2 บรรทัดเสมอ

If (Message.IsSuccess) ProcessMessage(Message);

  ซึ่งถ้าเรามี Method ที่รับ SomeMessage เยอะๆ แล้วเราจะทำยังไงล่ะ มานั่งเช็คทุกรอบเหรอ??? จริงๆ เราอาจจะเช็คแต่แรกก็ได้ เช่น var message=GetMessage(); if (!message.IsSuccess) message=null; แต่เราจะมั่นใจได้อย่างไรว่าเราจะไม่เผลอพลาดลืมเช็คไปเมื่อเขียนโค้ดเยอะๆ แถม null reference นี่เป็นปัญหา debug ยากอันดับต้นๆ

วิธีการออกแบบที่ดีเราควรจะแยกส่วน Content และ ErrorMessage ออกจากกัน แล้วคลาสที่รับส่งข้อมูลผ่านเน็ตเวิร์ก ฐานข้อมูล หรือ Threading ควรจะไม่สามารถทำอย่างอื่นได้เลยจนกว่าจะเช็คแล้วว่าการรับส่งสมบูรณ์ ถ้าการ Design แบบสมบูรณ์จริงๆ ผมคิดว่าน่าจะเป็นแบบนี้

class SomeMessage

{

object Content1; 

object Content2;

}

class ConnectionMessage

{

private object Content;

int ErrorCode;

string ErrorMessage;

public object GetContent()

{

if (ErrorCode!=0) throw new Exception("Error Getting Data");

return Content;

}

}

แล้วจึงเอา SomeMessage ไปยัดไว้ใน ConnectionMessage อีกที การทำแบบนี้จะทำให้รับประกันว่าไม่ว่าอนาคตเราจะเขียนตกหล่นยังไง แต่ถ้าเราพยายามจะดึงข้อมูลที่ไม่สมบูรณ์มี Error ออกมาเมื่อไหร่ จะได้ Exception ตามมาทันที แล้วเราจะเอา ConnectionMessage ไปใส่ใน Method ต่างๆ โดยไม่ดึง Content ออกมาก่อนก็ไม่ได้ จึงรับประกันได้เลยว่าถ้าเราซุ่มซ่ามพยายามดึงข้อมูลที่ส่งผ่านกันไม่สำเร็จเมื่อไหร่ มันจะเกิด Exception ทันที ซึ่งจะดีกว่าเกิด Bug เอามากๆ

ปล. แต่รับสารภาพว่าตัวเองก็ไม่ได้เขียนถึงขั้นล็อกไว้ให้ GetContent ยิง Exception ออกมา เพราะขี้เกียจครับ ก็แค่ห่อไว้ใน ConnectionMessage เท่านั้น นิสัยเสียจริงๆ




Create Date : 30 สิงหาคม 2555
Last Update : 30 สิงหาคม 2555 21:28:27 น. 0 comments
Counter : 437 Pageviews.

ชื่อ : * blog นี้ comment ได้เฉพาะสมาชิก
Comment :
  *ส่วน comment ไม่สามารถใช้ javascript และ style sheet
 

Mariel
Location :


[Profile ทั้งหมด]

ฝากข้อความหลังไมค์
Rss Feed
Smember
ผู้ติดตามบล็อก : 1 คน [?]




Friends' blogs
[Add Mariel's blog to your web]
Links
 

 Pantip.com | PantipMarket.com | Pantown.com | © 2004 BlogGang.com allrights reserved.