FizzBuzz Problem

FizzBuzz เป็นโจทย์ฝึกสมองเด็ก ที่ใช้ช่วยในการเรียนรู้เรื่องการหาร ซึ่งสามารถไปอ่านกฏเพิ่มเติมได้จากใน WIKI: FIZZBUZZ ครับ แต่บทความนี้ผมขอนำกฏของ FizzBuzz มาประยุกต์กับการเขียนโปรแกรม

จริงๆจะเขียนมานานและ Solution พร้อม แต่ติดงานที่บริษัทตลอด 55 โดยเรื่องของเรื่อง คือ มีรุ่นน้องวิทย์คอม มศว มาถามเรื่อง FizzBuzz ว่าจะเขียนอย่างไร(จะเขียนในบทความนี้นะครับ) โดยไม่ใช้ if  (ผมเขียนในบทความถัดไปครับ)ในภาษา python ผมก็ได้แนะนำไปเกี่ยวกับการใช้ Recusive Call ในการแก้ปัญหา มาคราวนี้ผมขอมาเรียบเรียงใหม่ในบล๊อกเผื่อมีคนอื่นสนใจ โดยผมใช้ภาษา java ในการแก้ปัญหานะครับ

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 Fizz Buzz Table
Decision Fizz Buzz Table

จาก Decision Tree ลองมาทำได้ Test Case คร่าวๆได้ประมานนี้นะครับ

กรณีที่เป็นไปได้INPUTOUTPUT
หาร 3 ลงตัว (IS Fizz)3Fizz
6Fizz
หาร 5 ลงตัว (IS Buzz)5Buzz
10Buzz
หาร 3 และ 5 ลงตัว หรือ หาร 15 ลงตัว (IS FizzBuzz)15FizzBuzz
30FizzBuzz
ต้องคืนค่า Input (ไม่เข้าเงื่อนไขใดๆเลย)2323
901901

แปลง 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.