TシャツとスパルタンVim 2.0を頂きました。ありがとうございます!![]()
予想だにしなかった内容にガクブルです。
職業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
でどうぞ。
package main
import (
"fmt"
"net"
"net/rpc"
)
type FizzBuzz int
func (fb *FizzBuzz) Serve(n int, r *string) error {
switch {
case n % 15 == 0:
*r = "FizzBuzz"
case n % 3 == 0:
*r = "Fizz"
case n % 5 == 0:
*r = "Buzz"
default:
*r = fmt.Sprintf("%d", n)
}
return nil
}
func main(){
fb := new(FizzBuzz)
rpc.Register(fb)
server, _ := net.Listen("tcp", ":8001")
for {
client, err := server.Accept()
if err != nil {
println(err.Error())
continue
}
rpc.ServeConn(client)
}
}
Register に渡される型のメソッドで、入力引数、戻り値のアドレス の二つを引数に持ち、戻り値に error を持つ物はエクスポートされる。なのでこの場合、n が FizzBuzz の入力、r が戻り値へのアドレスになる。
package main
import (
"net/rpc"
)
func main() {
client, _ := rpc.Dial("tcp", "localhost:8001")
var ret string
for i := 1; i <= 100; i++ {
client.Call("FizzBuzz.Serve", i, &ret)
println(ret)
}
}
GobというGo言語に特化したエンコーダなので、他の言語でも...という訳には行かないが、ちょっとした物を作る時にはかなり便利である。net/rpc/jsonrpc も含まれていて、こちらを使えばポータビリティのある RPC が書ける様になっている。このブログを応援する