Voice in the Gentle Wind

มิถุนายน 6, 2007

จาวากับปัญหา Checked Exception

Filed under: simple thoughts — deans4j @ 10:41 am

JDK 7 โอเพนซอร์สแล้ว และทางซันก็เชิญชวนให้หลายๆ คนมาสังคายนาภาษาและแพลตฟอร์มให้ดีขึ้น บางคนก็เสนอให้เพิ่มนู้นเพิ่มนี่ ดังเช่นที่เคยเล่าไปแล้ว แต่ก็มีบางคนเสนอให้ตัดนู้นตัดนี่ออกเหมือนกัน

หนึ่งในเรื่องที่ถูกบ่นมากที่สุดคือเรื่องปัญหา checked exception ที่จาวานำเสนอแต่เพียงภาษาเดียว กล่าวคือตัวภาษากำหนดไว้ว่า ถ้ามี exception ใดๆ เกิดขึ้นระหว่างโค้ดการทำงาน ตัว compiler จะทำหน้าที่อย่างแข็งขันในการตรวจสอบว่ามีการจัดการหรือยัง ซึ่งทำให้นักพัฒนามีหน้าที่ต้องจัดการกับ exception นั้นๆ ทันที หรือไม่ก็ปล่อยมันออกไปที่ชั้นบนอย่างตั้งใจด้วยการ throw ออกไปข้างนอก

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


คนที่เกลียดมันมากจะหนีไปใช้ RuntimeException กันซะหมด ซึ่งเป็นวิธีการหนีไปใช้ unchecked exception วิธีการหนึ่ง เป็นความสามารถที่เพิ่งมีใน Java 1.4 แต่การใช้มันมากไปในบางทีทำให้ฝ่ายตรงกันข้ามบอกว่า unchecked exception ทำให้ผู้พัฒนาละเลยหรือลืมจัดการกับมันได้ การใช้ checked exception ยังมีข้อดีว่าอย่างน้อยตัวเอกสาร javaDoc จะต้องกำกับว่าเมธอดนั้นๆ จะสามารถเกิด exception อะไรได้บ้างและเกิดเนื่องจากอะไร

ปัญหานี้คงถูกบ่นกันน้อยกว่านี้ ถ้าก่อนหน้าซันรู้จักใช้ RuntimeException อย่างถูกต้อง หลายๆ API จึงยังสืบทอดความผิดพลาดในการออกแบบมาจนถึงทุกวันนี้อย่างหลีกเลี่ยงไม่ได้ ถ้าจำกันได้ว่าในเอนทรีเรื่อง “คุณสมบัติของ DAO ที่ดี” มีข้อนึงในนั้นที่กล่าวไ้ว้ว่า

ตัว interface ต้องไม่แสดงออกถึง compile-time dependency ที่เกิดจากตัว implementation ซึ่งได้แก่

  • คลาสที่เกิดจากตัว persistence framework ที่ใช้ เช่น Session เป็นต้น
  • Exception ที่เกิดจาก persistence framework เช่น IOException หรือ SQLException เป็นต้น

ตัว Interface ต้องสามารถถูกคอมไพลได้โดยปราศจากไลบรารี่ของ persistance framework นั้นๆ ใน classpath

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

คนบางคนบอกว่าเอา checked exception ออกจากภาษาไปเลย บางคนประนีประนอมหน่อยบอกว่าให้คงไว้ แต่ต้องมีทางเลือกให้ผู้ใช้มากกว่านี้ วิธีการต่างๆ ถูกนำเสนอมากมาย บางคนว่า

  • ใช้ annotation กำกับเฉพาะ method ที่ตั้งใจให้เป็น checked exception สิ
  • หรือไม่ก็ใช้วิธีแก้ที่ compiler เอาว่าอย่าคิดมาก ตั้ง flag เปิดปิดได้
  • หรือไม่ก็นำเสนอคลาสใหม่ไปเลยเช่น CheckedException แล้วให้กรณีที่ต้องการให้เป็น checked exception จริงๆ ไปสืบทอดเอา

ส่วนตัวคิดว่าวิธีใช้ compiler flag ดูสะดวกดีแต่น่ากลัวพิลึก อาจนำพาปัญหาอื่นตามมาได้อีกใครจะไปรู้ ยิ่งถ้าต้องแลกเปลี่ยนโค้ดกันจะมีปัญหาหรือเปล่า? วิธีสร้างคลาส CheckedException ก็ดูโอเค แต่จะเป็นการ break API เก่าแหงๆ วิธี annotation ดูแล้วน่าจะ win-win ทั้งสองฝ่าย

ประเด็นเรื่องนี้ไม่ใช่เรื่องใหม่แต่อย่างใด แต่มันถูกปลุกขึ้นมาพูดถึงก็เพราะ Neal Gafter หนึ่งในผู้นำเสนอสเป็ก closure เล่าว่า closure สเป็กจะลดความซับซ้อนลงได้เยอะกว่านี้มากถ้าตัวภาษาตัดความสามารถของ checked exception ออกไปได้ ซึ่งจากการเปิดประเด็นเรื่องนี้แล้วลองใช้ google search ดู พบว่าความเห็นเทไปทางการต่อต้าน checked exception มากกว่า

Advertisements

9 ความเห็น »

  1. งง นิดๆ ครับ กับตรงนี้

    “คนที่เกลียดมันมากจะหนีไปใช้ RuntimeException กันซะหมด ซึ่งเป็นวิธีการหนีไปใช้ unchecked exception วิธีการหนึ่ง เป็นความสามารถที่เพิ่งมีใน Java 1.4”

    แปลว่าอะไรครับ?
    Checked/Unchecked Exception มันน่าจะมีมาตั้งแต่มี Java แล้วนะครับ (หรือผมเข้าใจผิด)

    เชื่อหรือไม่ว่า ตอน Java ออกมาใหม่ๆ (เมื่อสิบกว่าปีก่อน) … การมี checked exception ถูกนำมาโปรโมตเป็นข้อดีของภาษา
    เพราะเป็นการบังคับให้โปรแกรมเมอร์ handle error ที่อาจจะเกิดขึ้นได้ (บังคับด้วย compiler)
    ทำให้ Code นั้น Robust!!
    (โปรแกรมเมอร์ก็เลยหัวหมอ เอา try/catch เปล่าๆ ครอบมันซะ .. แล้วก็ compile ผ่าน สบายบรื่๋อ)

    ประเด็นนี้ สำหรับผม ผมมองว่า ทางแก้ ไม่น่าจะยากครับ
    แต่มันต้องแลกมาด้วย .. “Backward Compatibility”
    คำถาม คือ เราพร้อมจะยอมแลกหรือเปล่า์?

    ความเห็น โดย siroz — มิถุนายน 6, 2007 @ 6:21 pm

  2. คิดเล่น ๆ นะครับ ถ้าแลกด้วย backword compatibility นี่เป็นปัญหาระัดบชาติเลย (เล็กไปเป่าเนี้ยะ ?)

    แต่ว่าถ้าเรามี runtime อีกชุดนึงประกอบมาด้วยสำหรับ run โค้ดเก่า หรือ่วาเป็นชุดที่โปรแกรมที่ recode codeเดิมโดยอัตโนมัติ (โดยใช้ feature หัวหมอ try catch ครอบของเก่าซ่ะงั้น) เพื่อให run กะโปรแกรมเก่า บน JDK 7 จะเป็นไปได้เป่าครับ ? หรือว่าเขาทำกันไปหมดแล้ว ??

    ความเห็น โดย dto — มิถุนายน 6, 2007 @ 8:01 pm

  3. @siroz ผมคงผิดเรื่องกำเนิด RuntimeException (ตรงนี้อ่านเค้ามาอีกที ไม่ได้ตรวจสอบ) พอดีเกิดไม่ทัน 😛

    เรื่อง Robust นี่ยอมรับเลยครับว่าจริง และช่วยได้มาก แล้วก็ verbose มากด้วย

    ถือเป็นเรื่องละเอียดอ่อนเหมือนกัน บางทีก็ชอบ บางทีก็เกลียด แล้วก็กลายเป็นภาษาเดียวที่มีคุณสมบัตินี้ไปเลย

    บางที exception มันก็มากไปจริงๆ อย่างการจะ close connection database ที่เราต้องทำใน finally block ข้างในนั้นเราต้อง try-catch อีกรอบในการเรียกเมธอด close ซึ่งใน catch ก็ทำอะไรไม่ได้นอกจากปล่อยมันไว้อย่างนั้น แต่เรื่องนี้มันเป็นปัญหา API ที่ไปใช้ exception อย่างบ้าระห่ำจนพาลทำให้เกลียด checked exception

    เด๋วมาต่อ

    ความเห็น โดย deans4j — มิถุนายน 6, 2007 @ 10:03 pm

  4. อ้าว เวรกรรม .. กลายเป็นตูแก่ไปซะแล้วเหรอเนี่ย

    ิเรื่อง Backward Compatibility ในกรณีนี้ .. มันเป็นเรื่องการ “หักดิบ” ซะมากกว่าครับ
    เพราะ มันไม่ได้เกี่ยวกับแค่ runtime .. แต่มันต้องรวม compiler ด้วย
    ในกรณีของ checked exception .. compiler เป็นคน enforce เรื่องของ exception declaration และ exception handling
    ซึ่งมัน “ฝัง” มาตั้งแต่ต้นเลยว่า unchecked exception คือ java.lang.RuntimeException และ java.lang.Error (และ subclass ของพวกมัน) เท่านั้น

    ถ้าทำลายกฏตรงนี้ไปเมื่อไหร่ … มีโอกาสสูงมากที่ Java จะไม่เป็น Java อย่างที่เคยเป็นอีกต่อไป
    (อันนี้ ต้องเห็นใจ ลุงๆ ป้าๆ ที่เขียน Java มาเป็นสิบปี .. อยู่ๆ จะให้มาล้างกระดานกันเลย คงยากหน่อย)

    เรื่อง Checked/Unchecked Exception นี่ คุยกันสามวันไม่จบครับ เพราะโดยรวมแล้ว มันเป็นเรื่องปรัชญาของการ design (อารรร์ ได้พูดคำนี้แล้วรู้สึกดีจัง) เสียมากกว่า

    ความเห็น โดย siroz — มิถุนายน 7, 2007 @ 2:05 am

  5. กลับมาแล้ว แต่จำไม่ได้แล้วว่าจะพูดเรื่องอะไร -*-

    คุยไม่จบจริงๆ ผมยังบอกไม่ได้เลยว่าตัวเองรู้สึกยังไง ทั้งชอบและเกลียดมันในเวลาเดียวกัน

    ความเห็น โดย deans4j — มิถุนายน 7, 2007 @ 9:10 am

  6. จะว่าไป … Checked Exception ก็คงจะเหมือนกับผู้หญิง (เข้าเรื่องจนได้)

    อย่างที่เค้าพูดกันไว้ว่า
    Women …
    … We can’t live with them.
    … We can’t live without them.

    ความเห็น โดย siroz — มิถุนายน 7, 2007 @ 4:22 pm

  7. ถูก

    ความเห็น โดย Cap — มิถุนายน 10, 2007 @ 12:35 am

  8. ” กลับมาแล้ว แต่จำไม่ได้แล้วว่าจะพูดเรื่องอะไร -*- ”

    กรำแท้ๆ กำลังสนุกๆเลยเอาอีกๆ กำลังเรียนถึงเรื่องนี้พอดีเลยค่ะเล่าอีกๆเด๋วมาอ่านต่อ

    -______-”

    ความเห็น โดย ShijiemiS — มิถุนายน 21, 2007 @ 7:01 pm

  9. กำลังสนุกเลย ได้ความรู้เพิ่มอีกแล้ว

    ความเห็น โดย sonicneo — กรกฎาคม 6, 2007 @ 9:56 am


RSS feed for comments on this post. TrackBack URI

ใส่ความเห็น

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / เปลี่ยนแปลง )

Twitter picture

You are commenting using your Twitter account. Log Out / เปลี่ยนแปลง )

Facebook photo

You are commenting using your Facebook account. Log Out / เปลี่ยนแปลง )

Google+ photo

You are commenting using your Google+ account. Log Out / เปลี่ยนแปลง )

Connecting to %s

บลอกที่ WordPress.com .

%d bloggers like this: