จริงๆจะเขียนมานานและ Solution พร้อม แต่ติดงานที่บริษัทตลอด 55 โดยเรื่องของเรื่อง คือ มีรุ่นน้องวิทย์คอม มศว มาถามเรื่อง FizzBuzz ว่าจะเขียนอย่างไร(จะเขียนในบทความนี้นะครับ) โดยไม่ใช้ if (ผมเขียนในบทความถัดไปครับ)ในภาษา python ผมก็ได้แนะนำไปเกี่ยวกับการใช้ Recusive Call ในการแก้ปัญหา มาคราวนี้ผมขอมาเรียบเรียงใหม่ในบล๊อกเผื่อมีคนอื่นสนใจ โดยผมใช้ภาษา java ในการแก้ปัญหานะครับ
สำหรับเรื่องนี้มี 3 Blog ครับ
FizzBuzz คือ อะไร
FizzBuzz เป็นโจทย์ฝึกสมองเด็ก ที่ใช้ช่วยในการเรียนรู้เรื่องการหาร ซึ่งสามารถไปอ่านกฏเพิ่มเติมได้จากใน WIKI: FIZZBUZZ ครับ แต่บทความนี้ผมขอนำกฏของ FizzBuzz มาประยุกต์กับการเขียนโปรแกรม โดยกฏอยู่ว่ารับข้อมูล Input มา 1 ตัวเลข
- ถ้าหาร 3 ลงตัวให้แสดง Fizz
- ถ้าหาร 5 ลงตัวให้แสดง Buzz
- ถ้าหาร 15 ลงตัวให้แสดง FizzBuzz
- ถ้าไม่ใช้ก็ให้ Print ตัวเลข Input ออกมา
โดยในภาษา Java สามารถแก้ด้วย if ง่ายๆก่อนเลย ทุกคนคงเขียน Code ประมานนี้ (เขียนได้หลายแบบครับ ตอนนี้เอาแบบ Basic ก่อน เผื่อคนที่เพิ่งเริ่มศึกษา Java เข้ามาอ่าน)
package testFizzBuzz; import java.util.Scanner; import javax.swing.JOptionPane; public class SimpleFizzBuzz { public static void main(String[] args) { try { Scanner sc = new Scanner(System.in); System.out.print("Enter a number to test fizzbuzz: "); int input = sc.nextInt(); System.out.println("Result form input number " + input + " is " + testFizzBuzz(input)); } catch (Exception ex) { JOptionPane.showMessageDialog(null, ex.getMessage(), "ERROR", 0); } } private static String testFizzBuzz(int p_Input) { if (p_Input % 15 == 0) { return "FizzBuzz"; } else if (p_Input % 3 == 0) { return "Fizz"; } else if (p_Input % 5 == 0) { return "Buzz"; } else { return String.valueOf(p_Input); } } }
ผลการทดสอบโปรแกรม โดยการทำ UnitTest คร่าวๆ (ใช้คนทำครับ)
---------------ครั้งที่ 1--------------- Enter a number to test fizzbuzz: 3 Result form input number 3 is Fizz ---------------ครั้งที่ 2--------------- Enter a number to test fizzbuzz: 5 Result form input number 5 is Buzz ---------------ครั้งที่ 3--------------- Enter a number to test fizzbuzz: 15 Result form input number 15 is FizzBuzz ---------------ครั้งที่ 4--------------- Enter a number to test fizzbuzz: 23 Result form input number 23 is 23
ลอง Refactor Code ซักรอบก่อน เพื่อให้มันดูเป็น OOP นะครับ แยกการทำงานออกมาเป็น Class ดังนี้ โดยผมจะแยกออกเป็น Class Input กับ Class ที่ตรวจสอบ FizzBuzz ครับ
- Class FizzBuzzTest: เอาไว้ให้ User ป้อน Input
package testFizzBuzzOOP; import java.util.Scanner; import javax.swing.JOptionPane; public class FizzBuzzTest { public static void main(String[] args) { try { Scanner sc = new Scanner(System.in); FizzBuzz fizzBuzz = new FizzBuzz(); System.out.print("Enter a number to test fizzbuzz: "); int input = sc.nextInt(); System.out.println("Result form input number " + input + " is " + fizzBuzz.findFizzBuzz(input)); } catch (Exception ex) { JOptionPane.showMessageDialog(null, ex.getMessage(), "ERROR", 0); } } }
- Class FizzBuzz: เอาไว้ตรวจสอบว่าตัวเลขที่ป้อนเข้ามา ตรงตามเงื่อนไข หรือไม่ครับ
package testFizzBuzzOOP; public class FizzBuzz { public String findFizzBuzz(int p_Input) { if (p_Input % 15 == 0) { return "FizzBuzz"; } else if (p_Input % 3 == 0) { return "Fizz"; } else if (p_Input % 5 == 0) { return "Buzz"; } else { return String.valueOf(p_Input); } } }
ผลการทดสอบโปรแกรม โดยการทำ UnitTest คร่าวๆ (ใช้คนทำครับ)
---------------ครั้งที่ 1--------------- Enter a number to test fizzbuzz: 6 Result form input number 6 is Fizz ---------------ครั้งที่ 2--------------- Enter a number to test fizzbuzz: 10 Result form input number 10 is Buzz ---------------ครั้งที่ 3--------------- Enter a number to test fizzbuzz: 30 Result form input number 30 is FizzBuzz ---------------ครั้งที่ 4--------------- Enter a number to test fizzbuzz: 901 Result form input number 901 is 901
ถัดมาลองใช้ Tools เข้ามาช้วยทำ unittest (เพิ่มความไฮโซนิดนึง เพราะจากการลองแก้ Code มาสองครั้งสิ่งที่ Dev ต้องทำ คือ การมารันโปรแกรม และป้อน Input เข้าไปใหม่ทุกครั้ง ซึ่งมันเสียเวลามากครับ)ตอนนี้เราสร้าง Test Case มาและใช้ Tools ชื่อ JUnit มาช่วยครับ ก่อนอื่นเราลองมาเขียน Test Case โดยใช้ Decision Tree กันก่อนครับ เพื่อให้เห็ฯภาพรวมของการทำงานครับ
จาก Decision Tree ลองมาทำได้ Test Case คร่าวๆได้ประมานนี้นะครับ
กรณีที่เป็นไปได้ | INPUT | OUTPUT |
หาร 3 ลงตัว (IS Fizz) | 3 | Fizz |
6 | Fizz | |
หาร 5 ลงตัว (IS Buzz) | 5 | Buzz |
10 | Buzz | |
หาร 3 และ 5 ลงตัว หรือ หาร 15 ลงตัว (IS FizzBuzz) | 15 | FizzBuzz |
30 | FizzBuzz | |
ต้องคืนค่า Input (ไม่เข้าเงื่อนไขใดๆเลย) | 23 | 23 |
901 | 901 |
แปลง Test Case เหล่านี้ให้กลายเป็น Code เพื่อใช้กับ Junit ดังนี้ครับ
package testFizzBuzzWithUT; import static org.junit.Assert.*; import org.junit.Test; import testFizzBuzzOOP.FizzBuzz; public class FizzBuzzUT { @Test public void modThreeAndFiveIsFizzBuzz() { FizzBuzz fizzBuzz = new FizzBuzz(); assertEquals("FizzBuzz", fizzBuzz.findFizzBuzz(15)); assertEquals("FizzBuzz", fizzBuzz.findFizzBuzz(30)); } @Test public void modThreeIsFizz() { FizzBuzz fizzBuzz = new FizzBuzz(); assertEquals("Fizz", fizzBuzz.findFizzBuzz(3)); assertEquals("Fizz", fizzBuzz.findFizzBuzz(6)); } @Test public void modFiveIsFizz() { FizzBuzz fizzBuzz = new FizzBuzz(); assertEquals("Buzz", fizzBuzz.findFizzBuzz(5)); assertEquals("Buzz", fizzBuzz.findFizzBuzz(10)); } @Test public void notFizzAndBuzz() { FizzBuzz fizzBuzz = new FizzBuzz(); assertEquals("23", fizzBuzz.findFizzBuzz(23)); assertEquals("308", fizzBuzz.findFizzBuzz(308)); } }
ผลการรัน Test นะครับ ผ่านฉลุย ^___^
เดี๋ยวบทความหน้า ผมเขียน FizzBuzz โดยไม่ใช้ IF แล้วทำไมต้องไม่ใช้ IF ผมเขียนอธิบายถึงสาเหตุในบทความถัดไปครับ
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.