2012/08/09


gist に置いておくのも勿体ないかなと思ったので、こちらにも。
職業PGにわかるFizzBuzz - 日々常々

なんかFizzBuzzが書けないPGがどーとか定期的に話題になってるけど、私に言わせれば説明の仕方が悪い。

http://d.hatena.ne.jp/irof/20120808/p1
この設計書を参考に業務プログラマっぽくコードを書いてみた。
業務プログラマがFizzBuzz書いたらどうなるか ( ref: http://d.hatena.ne.jp/irof/20120808/p1 ) — Gist
https://gist.github.com/3292173
結構、設計書通りに作ったつもり。ループじゃなく、標準入力から読み込み、標準出力する部分も仕様通りです。
ただこの標準入出力を使っている事が裏目に出て、試験では標準入出力を一時的に差し替える必要があった。
試験コードだけ載せておく。
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringReader;

import net.kaoriya.mattn.joke.FizzBuzz;

/**
 * FizzBuzzテストクラス.
 */
public class FizzBuzzTest {
    /** 標準入力退避用. */
    private InputStream in;

    /** 標準出力退避用. */
    private PrintStream out;

    /**
     * テスト開始前処理.
     *
     * <p>標準入力および標準出力を退避する</p>
     */
    @Before
    public void setUp() {
        in = System.in;
        out = System.out;
    }

    /**
     * テスト開始後処理.
     *
     * <p>標準入力および標準出力を復帰する</p>
     */
    @After
    public void tearDown() {
        System.setIn(in);
        System.setOut(out);
    }

    /**
     * テスト実行.
     *
     * <ul>
     * <li>標準出力を差し替える</li>
     * <li>標準入力を引数nを数値化した入力に差し替える</li>
     * <li>FizzBuzzクラスを生成する</li>
     * <li>FizzBuzz変換処理を実行する</li>
     * <li>標準出力された文字列と引数sで検証する</li>
     * </ul>
     *
     * @param n FizzBuzz変換処理に与える数値
     * @param s 期待する結果
     * @throws IOException 標準入出力処理に失敗した場合に発生
     */
    private void doFizzBuzz(int n, String s) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(baos);
        System.setOut(new PrintStream(bos));
        byte[] input = ("" + n + "\n").getBytes();
        System.setIn(new ByteArrayInputStream(input));

        FizzBuzz fb = new FizzBuzz();
        fb.runFizzBuzzConvert();

        System.out.flush();
        StringReader sr = new StringReader(baos.toString());
        String result = new BufferedReader(sr).readLine();
        assertEquals(s, result);
    }

    /**
     * FizzBuzz変換処理テスト.
     *
     * @throws IOException 標準入出力処理に失敗した場合に発生
     */
    @Test
    @SuppressWarnings
    public void testFizzBuzz() throws IOException {
        // CHECKSTYLE:OFF
        doFizzBuzz(1"1");
        doFizzBuzz(2"2");
        doFizzBuzz(3"Fizz");
        doFizzBuzz(4"4");
        doFizzBuzz(5"Buzz");
        doFizzBuzz(6"Fizz");
        doFizzBuzz(7"7");
        doFizzBuzz(8"8");
        doFizzBuzz(9"Fizz");
        doFizzBuzz(10"Buzz");
        doFizzBuzz(11"11");
        doFizzBuzz(12"Fizz");
        doFizzBuzz(13"13");
        doFizzBuzz(14"14");
        doFizzBuzz(15"FizzBuzz");
        doFizzBuzz(16"16");
        // CHECKSTYLE:ON
    }
}
一応、プロジェクトフォルダになっているので # git clone git://gist.github.com/3292173.git として貰ったら開発出来る様にしてある。gradle を使っているので # gradle build でビルド # gradle test でテスト。javadoc は # gradle javadoc でどうぞ。
ネタなのでツッコミなしでお願いします。ましてやバグチケット切るなど問題外です。
Posted at by



2011/03/06


public class foo {
    final static String bar = "a" + "b";

    public foo() { }

    public String bar(String baz) {
        return "a" + "b" + baz + "c" + "d";
    }
}
コンパイルしてデコンパイル # javac -version
javac 1.6.0_24
# javac foo.java
# jad foo.class
// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   foo.java


public class foo
{

    public foo()
    {
    }

    public String bar(String s)
    {
        return (new StringBuilder()).append("ab").append(s).append("c").append("d").toString();
    }

    static final String bar = "ab";
}
+ をStringBuilder に置き換えてくれたまでは良かった。a と b は最適化されて一つの ab になったけど c と d はそのままだ。
この最適化が有効なのは、業務のソースなんかでたまに見かける String sql = "SELECT "
           + "  * "
           + " FROM "
           + "  USER_MST"
           + " WHERE "
           + "  BAR = ?";

PreparedStatement stmt = con.prepareStatement(sql);
stmt.setString(1"baz");
こんなソースの場合だと思うんだけど、テーブル名なんかを変数に持ってて String sql = "SELECT "
    + " * "
    + " FROM "
    + " " + tableName
    + " WHERE "
    + "     BAR = ?";
こんな事しちゃうと、変数以降の最適化が StringBuilder での最適化に止まってしまう。まぁよく見るよね。こういうコード。
String s1 = (new StringBuilder()).append("SELECT *  FROM ").append(s).append(" WHERE ").append(" BAR = ?").toString();
PreparedStatement preparedstatement = connection.prepareStatement(s1);
preparedstatement.setString(1, "baz");
しばらく「最近のJavaはconstなStringを結合して最適化する」っていうのはやめておこうと思った。
Posted at by



2009/10/08


Javaで...
class test{public static void main(String[]a){for(int n=1;n<101;n++)System.out.println(n%15>0?n%3>0?n%5>0?""+n:"Buzz":"Fizz":"FizzBuzz");}}
むー139バイトで46位。遠いなー。

じゃぁRubyで...
puts (1..100).map{|i|i%15==0%1?:FizzBuzz:i%3==0?:Fizz:i%5==0?:Buzz:i}
むむー。72バイトで65位。遠いよー。

なっ...ならばLuaで!!!汗...
for v=1,100 do print(v%15>0 and(v%3>0 and(v%5>0 and v or"Buzz")or"Fizz")or"FizzBuzz")end
88バイトで11位。ムキーーーーッ!

寝る!
Posted at by