Index: [Article Count Order] [Thread]

Date:  Sun, 2 Jul 2000 00:47:57 +0900
From:  Kaoru Hosokawa <khosokawa@....com>
Subject:  [XP-jp:00568] Test-first, by Intention Part 2 Was:Re: XP	Installed26 Part1 Test-first, by Intetion
To:  extremeprogramming-jp@....jp (extremeprogramming-jp ML)
Message-Id:  <B584417D.2299%khosokawa@....com>
In-Reply-To:  <200006101349.WAA31357@....nu>
Posted:  Sun, 02 Jul 2000 00:46:59 +0900
X-Mail-Count: 00568

ホソカワです。

コメントちりばめています。よろしくお願いします。

on 2000/06/10 10:50 PM, Ken N. at kenn@....nu wrote:

> Part1と2についてコードをJavaにしてみました。
> どの程度妥当な訳になっているかあまり自信はありませんが、参考になれば。

…

> 
> つづいてPart2のほうです。
> 
> 
> <Smalltalk>
> === Page 193 Code 1
> 
> testEmpty
> |summarizer|
> summarizer:=self emptySummarizer.
> </Smalltalk>
> 
> <Java>
> === Page 193 Code 1
> 
> /*
> Summarizerクラスの実装に入る前に、そのクラスのテストを先に
> 書くことから始めているわけですね。本章の主題でもあります。
> 
> さてと... JUnitを使うことにしましょうか。
> 
> class SummarizerTest extends TestCase {
> ...
> }
> 
> などとしてあるものとします。
> */
> 
> public SummarizerTest testEmpty(){
> Summarizer summarizer = emptySummarizer();
> // 未完です
> return this; // voidでもいいと思います。
> }
> </Java>

この時、

    public Summarizer emptySummarizer() {
        // ...
    }

があるわけですね。

> 
> 
> <Smalltalk>
> === Page 193 Code 2
> 
> testEmpty
> |summarizer|
> summarizer:=self emptySummarizer.
> self should:[summarizer summary isEmpty]
> </Smalltalk>
> 
> <Java>
> === Page 193 Code 1
> 
> /*
> ``should:''キーワードメソッドは、受け取ったブロッククロー
> ジャにvalueメッセージを送り、Trueのインスタンスが返ってこ
> なければエラーとするものだと推測できます。以下のように書け
> ると思います。
> */
> public SummarizerTest testEmpty(){
> Summarizer summarizer = emptySummarizer();
> assert(summarizer.summary().isEmpty());
> return this; // voidでもいいと思います。
> }
> /*
> しかし、両者の違いについては知っておいたほうがいいでしょう。
> 上記Javaコードではassertには評価された後の値、つまり、真ま
> たは偽が渡りますが、前出のSmalltalkコードでは、真偽の獲得は
> should:キーワードメソッドの中で行なわれることになります。
> */
> </Java>

should() は、「このようになるべきである」ということを言っているのですね。と
ころで、Java に assert() ありました?

> 
> 
> <Smalltalk>
> === Page 194 Code 1
> 
> Object subclass:#Summarizer
> instance variables:'first second'
> </Smalltalk>
> 
> <Java>
> === Page 194 Code 1
> 
> /*
> ここで彼らは一旦Summarizerクラスに注意を向けています。とい
> っても、クラスの属性を定義しただけで、すぐにテストの続きに
> 戻っています。
> 
> 属性の型をどうするかというのが問題です。後で出てくる
> OrderedCollection と同じにしておくのが無難そうですが、Java
> で何を使うのが適当かよくわからないので、仮に FooCollection
> とでもしておきます。
> */
> class Summarizer {
> private FooCollection first;
> private FooCollection second;
> }
> </Java>
> 
> 

Vector は、どうでしょうか?

class Summarizer {
    private Vector first;
    private Vector second;
}

> <Smalltalk>
> === Page 194 Code 2
> 
> emptySummarizer
> ^Summarizer
> with:#()
> with:#()
> </Smalltalk>
> 
> <Java>
> === Page 194 Code 2
> 
> /*
> SummarizerTestのなかにemptySummarizer()を定義します。
> privateでいいでしょう。
> 
> 仮に設定したFooCollectionを引数無しのコンストラクタで構築
> すると、空のコレクションができるものと仮定して、次のように
> 書けます。
> */
> private Summarizer emptySummarizer(){
> return new Summarizer(new FooCollection(), new FooCollection());
> }
> </Java>
> 
> 
> <Smalltalk>
> === Page 195 Code 1
> 
> with:firstCollection with:secondCollection
> ^self new
> setFirstCollection:firstCollection
> secondCollection:secondCollection
> </Smalltalk>
> 
> <Smalltalk>
> === Page 195 Code 2
> 
> setFirstCollection:firstCollection secondCollection:secondCollection
> first:=firstCollection
> second:=secondCollection
> </Smalltalk>
> 
> 
> <Java>
> === Page 195 Code 1
> === Page 195 Code 2
> 
> /*
> 前出のSumの場合と同様です。ここまでのSummarizerをまとめて
> みます。
> */
> class Summarizer {
> private FooCollection first;
> private FooCollection second;
> 
> public Summarizer(FooCollection firstCollection, FooCollection
> secondCollection){
> setFirstAndSecondCollection(firstCollection, secondCollection);
> }
> 
> public Summarizer setFirstAndSecondCollection(FooCollection firstCollection,
> FooCollection secondCollection){
> first = firstCollection;
> second = secondCollection;
> return this; // void でもいいでしょう。
> }
> }
> </Java>
> 
> 
> <Smalltalk>
> === Page 195 Code 3
> 
> summary
> self halt
> </Smalltalk>
> 
> <Java>
> === Page 195 Code 3
> 
> /*
> Javaではどうするのがいいのかよくわかりません。デバッガを使
> うために実行の停止をさせたいということですから、最初からデ
> バッガの中で動かすことにして、このメソッドにブレークポイン
> トを設定しておけばいいと思います。
> */
> public void summary(){}
> </Java>

例外を投げることになるのではないでしょうか?

public void summary() {
    throw new RuntimeException();
}

> 
> 
> 
> <Smalltalk>
> === Page 195 Code 4
> 
> summary
> ^first,second
> </Smalltalk>
> 
> <Java>
> === Page 195 Code 4
> 
> /*
> 仮の実装として、ふたつのCollectionを連結して返すと言う処理
> を記述しています。
> 
> うーん、くるしまぎれですが、FooCollectionではconcat()メソッ
> ドで別のインスタンスを連結できるということにしておきます。
> また、concat()はレシーバ自身を返すものとします。
> */
> public FooCollection summary(){ return first.concat(second); }
> 
> /*
> また、
> 
> =   空の collection を書いてそれを返す方がより単
> =   純だが、
> 
> ということでやってみると、以下の通りです。
> */
> public FooCollection summary(){ return new FooCollection(); }
> </Java>
> 
> 

Vector クラスにも concat(Vector) メソッドがありません。Smalltalk 強し!

> <Smalltalk>
> === Page 196 Code 1
> 
> testABC
> "self unsafeRun:#testABC"
> |summarizer|
> summarizer:=self abcSummarizer.
> self should:[summarize summary size=3]
> </Smalltalk>
> 

Smalltalk の質問です。「#testABC」は、なんですか?配列?

> <Java>
> === Page 196 Code 1
> 
> /*
> ここで新たなテストを追加しています。
> 単項メッセージの優先順位が最高ですので、次のように書けます。
> */
> public SummarizerTest testABC(){
> Summarizer summarizer = abcSummarizer();
> assert(summarize.summary().size() == 3);
> return this;
> }
> /*
> FooCollectionのsize()メソッドは、コレクションの要素数を返すも
> のであると仮定しています。
> */
> </Java>
> 
> 
> <Java>
> 
> /*
> ここまでで、各クラスがどうなったかをまとめておきます。
> 
> 勝手に想定したFooCollectionクラスのせいで、わかりにくくなっ
> ている部分がありますね... Javaでの適切なコレクションクラス
> をご存知のかたは、どんどん書き換えてください。
> */
> 
> class Sum {
> private String name;
> private int amount;
> 
> public Sum(String aString, int aNumber){ setNameAndAmount(aString, aNumber); }
> 
> public Sum setNameAndAmount(String aString, int aNumber){
> name = aString;
> amount = aNumber;
> return this;
> }
> public String getName(){ return name; }
> public int getAmount(){ return amount; }
> }
> 
> class SummarizerTest extends TestCase { // JUnitの使用を想定している。
> public SummarizerTest(String name){ super(name); }
> 
> // setUp()とtearDown()は、このケースでは省略できると思います。
> 
> public SummarizerTest testEmpty(){
> Summarizer summarizer = emptySummarizer();
> assert(summarizer.summary().isEmpty());
> return this; // voidでもいいと思います。
> }
> private Summarizer emptySummarizer(){
> return new Summarizer(new FooCollection(), new FooCollection());
> }
> 
> public SummarizerTest testABC(){
> Summarizer summarizer = abcSummarizer();
> assert(summarize.summary().size() == 3);
> return this; // voidでもいいと思います。
> }
> }
> 
> class Summarizer {
> private FooCollection first;
> private FooCollection second;
> 
> public Summarizer(FooCollection firstCollection, FooCollection
> secondCollection){
> setFirstAndSecondCollection(firstCollection, secondCollection);
> }
> 
> public Summarizer setFirstAndSecondCollection(FooCollection firstCollection,
> FooCollection secondCollection){
> first = firstCollection;
> second = secondCollection;
> return this;
> }
> 

このCollectionまわりの宣言など、ちょっと長いですね。原文のSmalltalkも長いで
すよね。本当にこのように書いているのでしょうか?

> public FooCollection summary(){ return first.concat(second); }
> }
> </Java>
> 
> 
> Part3/4で出てくる``do:[...]''や``detect:[...] ifNone:[...]''を
> どう訳すのが適切か、ちょっと考えているところです。
> 
> 

出来上がったら、ポストしてください。

> -.- . -. -.
> Ken Nakagaki (kenn@....nu is NOT for private E-Mail)
> 「人は船ではない。人は会社ではない」-- Gerry Spence

-- 
Kaoru Hosokawa
khosokawa@....com