เรื่องของ Exception ตอน 3

Anti pattern Exception ต่อ

ผมเขียนเกี่ยวกับ Exception ไว้ 3 ตอน คุณสามารถกด Link ด้านล่างเพื่ออ่านที่เกี่ยวกับ Exception ตอนต่างๆได้เลย

ว่าจะเขียน Blog ทุกสัปดาห์ไปๆมาๆก็ไม่ได้เขียนเนื่องจากงานเยอะแต่จริงๆคือขี้เกียจเขียน จนมีเพื่อนบอกว่า เฮ้ยเขียนทิ้งไว้ไมไม่กลับมาเขียนต่อ วันนี้เลยมาเขียนต่อให้จบดีกว่า ตอนนี้อยู่หัวข้อเดิมเรื่อง Anti pattern Exception

  • Relying on getCause()

อันนี้น่าจะเจอบ่อยใน JAVA แต่ภาษาอื่นก็ทำคล้ายๆแบบนี้ได้อาการมันประมาณว่าเราดัก Exception จากนั้นดึงเอาสาเหตุของ Exception ออกมาอีกทีหน้าตา Code มันจะประมาณนี้

1
2
3
4
5
6
7
8
9
10
11

try {
idolProfile cherprang = IdolService.getProfile("BNK48","Cherprang");
printToScreen(cherprang);
} catch( CustomException ex) {
if (ex.getCause() instanceof FileNotFoundException ) {
doClearResource();
} else {
throw ex;
}
}

ตอนแรกอ่านมันก็โอเคนะแค่ไปดึงเขาสาเหตุที่เด้ง exception ออกมาตรวจ อีกทีว่ามันคืออะไรแล้วเอาไป Check ใน if แล้วมันจะเป็นอะไรไป แต่พอมาอ่านที่เขาอธิบายมันแล้วก็คิดตามก็เข้าใจ คืออย่างแรกเข้าใจก่อนว่า Code ที่ผมเขียนอธิบายนี้เป็นส่วนเรียกใช้งาน idolService ซึ่งเป็น Code ที่คนอื่นเขียน หรือ อาจจะเป็นผมเขียน โดยผมไปอ่าน Manual และ Source code ของเขาอย่างละเอียดเลยว่ามันจะ Throw อะไรออกมาแล้วผมก็ได้ Code ประมาณนี้ คราวนี้เวลาผ่านไป idolService เกิดการแก้ไข Source code ในส่วน Implementation จากการที่เขาเก็บข้อมูลเป็น File เขาย้ายไปเก็บข้อมูลที Server เวลาดึงข้อมูลเขายิงไป Server เวลาได้ Error ก็จะเปลี่ยนจาก FileNotFoundException เป็นอย่างอื่น คราวนี้ฝันร้ายก็มาเยือนเพราะไม่มีใครรู้ว่ามันมีผลกระทบมาถึง Code ส่วนนี้ด้วย จริงๆรู้แน่ตอนทำ Full loop แต่เขามองว่าแก้ Service เกี่ยวไรกับส่วนแสดงผล ในเมื่อรักษา Interface ทุกอย่างครบ นั่นแหละครับปัญหาทีี่ทำให้การทำอย่างงี้กลายเป็น Anti pattern

  • Destructive Wrapping

ข้อนี้เลวร้ายมากมันคือการทำลาย stack trace ของ Exception ซึ่งการทำไม่ยากเลยทำด้วยวิธีนี้

1
2
3
4
5
6
7

try {
idolProfile cherprang = idolService.getProfile("BNK48","Cherprang");
printToScreen(cherprang);
} catch( CustomException ex) {
throw new idolException("Problem with net idol service" + ex.getMessage());
}

ตอนแรกอ่านก็ไม่เห็นไม่เป็นอะไรเลยนี่พอมาอ่านดีๆ อ้าว stack trace ตอนเราสั่ง print stack มันหายไปเลยมาหยุดตรงนี้พร้อม message ซึ่งบางทีมันอาจไม่ใช่ต้นกำเนิดของสาเหตุด้วย ประมาณดูหนังเจ้าพ่อที่ตำรวจตามจับแก๊งของเจ้าพ่ออยากจะสาวไปหาตัวเจ้าพ่อ กำลังไล่ตามหลักฐานจากโจรคนนึงไล่ไปหาเจ้าพ่อแต่สุดท้ายเจ้าพ่อสั่งฆ่าตัดตอนตอนก่อนถึงตัวเอง ทุกอย่างก็เลยเป็นปริศนาต่อไปเจ้าพ่อก็ยังคงลอยนวล

  • Log and Return Null

อันนี้เลวร้ายพอๆกับข้างบนและผมก็เคยทำด้วยเพราะคิดว่าไม่เป็นไร ตัวอย่าง Code มันจะประมาณนี้

1
2
3
4
5
6
7
8
9
10
11
12
13

public class IdolService {
public IdolProfile getProfile(String group, String name) throws CustomException {
try {
InputStream input = FileUtils.openInputStream(new File("idol.dat"));
return streamToProfile(input, group,name);
} catch (FileNotFoundException ex) {
return null;
} catch (IOException ex) {
throw ex;
}
}
}

ถามว่าทำไมเขียนอย่างนี้คือผมไปอ่านไฟล์ที่ชื่อ “idol.dat” ซึ่งผมการันตีเลยว่าไฟล์นี้มีแน่นอนแล้วผมก็ทิ้ง code นี้ไว้อย่างนี้ จนวันนึง มีคนมาแก้ไขข้อมูลในเครื่อง server ตามรอบการดูแลของเขา เขาเขียน script บางอย่างเกี่ยวกับการ backup แล้วมันดันเขียนผิดไปล้ายไฟล์ “idol.dat” ของผมไปที่อื่น แต่ service ของผมยังทำงานปกติเหมือนไม่มีอะไรเกิดขึ้นทั้งๆที่เกิดปัญหาอยู่ ลูกค้าโทรมาหาผมพร้อมบอกว่า เฮ้ยทำไม Search หาข้อมูลน้องคนนี้ไม่เจอเลย เกิดอะไรขึ้น ตอนนั้นผมคงไปหาข้อมูลใน Log พร้อมกับงงๆว่าทุกอย่างทำงานปกติดีนี่ไม่มี Error ไม่มีอะไรเลย คงต้องใช้เวลานานระดับหนึ่งเลยกว่าผมจะรู้ว่ามันเกิดจาก Source code ตรงนี้ ดังนั้นอย่าทำแบบนี้นะครับอันตรายมากๆ

ก็จบไปแล้วนะครับกับเรื่อง Exception จริงๆมีอีกหลายอย่างแต่ผมไม่เข้าใจมันอย่างแท้จริง หรือยังไม่เคยโดนกับตัวเลยไม่อยากจะเขียนเพราะจะทำให้เกิดความเข้าใจผิด ส่วนใจสนใจอ่านต่อไปอ่านได้ตาม ref ที่ผมแนบไว้ข้างล่าง

ปล. ผมไม่ได้เป็นแฟนคลับ idol วงไหนนะครับพอดีเห็นเพื่อนๆผมหลายคนชอบแล้วน้องเขาก็ดูน่ารักดีเลยเอามาเป็นมุกเวลามาอ่านบทความนี้จะได้ไม่เซ็งหรือเครียดจนเกินไป

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

Ref :
https://community.oracle.com/docs/DOC-983543#catchingException
https://arxiv.org/pdf/1704.00778.pdf