เทคนิคหนึ่งเกี่ยวกับการใช้ if….else

blog วันนี้เกิดขึ้นจากความอัดอั้นตันใจนิดหน่อย คือเรื่องมันมีอยู่ว่าผมดันไปมีความเห็นไม่ตรงกับหัวหน้านิดหน่อยในเรื่องของการเขียนโค๊ด โดยโค๊ดตัวที่มีปัญหาก็คือ

if codeinlist(input-a, "AB,CD") and 
codeinlist(input-b, "01,02,03,04,05")
then
output = input-a + input-b
else
output = input-a

โค๊ดข้างบนไม่ใช่โค๊ดจริง เพราะเดี๋ยวผมโดนฟ้องจะซวยเอา โจทย์คือ ไอ้  AB05 เป็น output ที่ไม่ถูกต้อง แต่  CD05 ใช้ได้นะ

วิธีที่ผมเสนอไปก็คือ งี้ …

if input-a = "CD" and input-b = "05"
then
output = "CD05"
else if codeinlist(input-a, "AB,CD") and
codeinlist(input-b, "01,02,03,04")
then
output = input-a + input-b
else
output = input-a

โดนด่าเปิงเลยครับ 555 คือพี่เขามองว่าผม hard code น่ะ พี่เขาว่างี้ดีกว่า

if (codeinlist(input-a, "AB,CD") and 
codeinlist(input-b, "01,02,03,04"))
or (input-a = "CD" and input-b = "05"
then
output = input-a + input-b
else
output = input-a

คือจริง ๆ ทั้งสองอย่างมีข้อดีต่างกัน อันของผมจะอ่านง่ายกว่าเพราะว่าผมแยกเคสกรณี input-b  เป็น 05 ออกมาเป็นอีกเคสนึง ส่วนอันล่างเองโค๊ดจะไม่ซ้ำซ้อนและดูไม่เหมือน hard code  แต่ว่าเป็นเงื่อนไขแบบ 2 ระดับ 2 เงื่อนไขซึ่งจะอ่านยากขึ้นนิดนึง

แต่ถ้าถามว่าแบบไหนดีที่สุด ผมเชื่อว่า แบบนี้ครับ

if (input-a = "AB" and
codeinlist(input-b, "01,02,03,04"))
or (input-a = "CD" and
codeinlist(input-b, "01,02,03,04,05"))
then
output = input-a + input-b
else
output = input-a

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

if (input-a = "AB" and
codeinlist(input-b, "01,02,03,04"))
then
output = input-a + input-b
else if input-a = "CD" and
codeinlist(input-b, "01,02,03,04,05")
then
output = input-a + input-b
else
output = input-a

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

เผื่อนึกภาพไม่ออก

if ((inputA == "AB" &&
codeinlist(inputB, "01,02,03,04")) ||
(inputA == "CD" &&
codeinlist(input-b, "01,02,03,04,05")))
{
output = inputA + inputB;
}
else
{
output = inputA;
}

คำถาม … ผมใส่วงเล็บครบมั้ยครับ ?

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

ผมก็จะสรุปเป็นเทคนิคส่วนตัวที่ผมใช้นะครับ คือ ถ้าเกิดว่า ในประโยคเงื่อนไขของ  if statement นั้นเป็นประโยคย่อย ๆ หลาย ๆ อันที่เชื่อมกันด้วย หรือ (or) ผมจะแยกมันออกมาเป็นหลาย ๆ if แทนโดยที่ข้างในแต่ละประโยคก็เหมือนกัน และถ้ามันซับซ้อนมาก ๆ ก็รีแฟคเตอร์มันออกมาเป็นฟังก์ชั่นด้วย

เช่น สมมติว่าแต่ละ  statement มันซับซ้อนประมาณนึงนะครับ

if ((statement_A) || (statement_B) || (statement_C)){
doSomething();
}

ผมก็จะทำแบบนี้แทน

if (statement_A) doSomething();
else if(statement_B) doSomething();
else if(statement_C) doSomething();

เนี่ย ซ้ำกันไปเลย

ประโยคที่เชื่อมด้วย or  เนี่ย หลาย ๆ ครั้งอาจจะถูกแยกเพราะว่าพอใช้ ๆ ไปเงื่อนไขมันเปลี่ยน ถ้าเราแยกซะตั้งแต่แรกไปเลยก็อาจจะทำให้ไม่ต้องมานั่งแยกภายหลังด้วยครับ

ส่วนประโยคเงื่อนไขที่เชื่อมด้วย และ  (and) ผมจะใช้ if ซ้อนใน if หลาย ๆ ชั้นลงไปเรื่อย ๆ แทนครับ เช่น

if ((statement_A) && (statement_B) && (statement_C)){
doSomething();
}

ผมก็จะทำแบบนี้แทน

if (statement_A) {
if(statement_B) {
if(statement_C){
doSomething();
}
}
}

ทั้งสองวิธีตั้งอยู่บนพื้นที่ฐานที่ว่า ประโยคเงื่อนไขไม่ได้ยาวมาก ไอ้ประเภทมี 7-8 เงื่อนไข 4-5 ระดับเนี่ยใช้ไม่ได้นะครับ เขียนแบบนี้เละตายเลย ถ้าเป็นกรณีนี้แนะนำให้ refactor ตัวประโยคเงื่อนไขออกเป็นอีกฟังก์ชั่นนึงแทนไปเลยดีกว่าครับ

ที่สำคัญอีกอย่างก็คือมันก็มี trade-off  ครับ โค๊ดอาจจะดูง่ายขึ้น พลาดยากขึ้น แต่ว่าอาจจะมีข้อเสียอื่น ๆ อย่างการซ้ำซ้อน หรือมี branch เยอะ ก็ต้องชั่งน้ำหนักให้ดีก่อนตัดสินใจว่าจะใช้วิธีไหนนะครับ

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *

This site uses Akismet to reduce spam. Learn how your comment data is processed.