Date:  Wed, 12 May 2004 12:31:10 +0900
Subject:  【オブジェクト倶楽部: 2004-16 	号】

       ┏━━━━━━━━━━━━━━━━━━━━━━━━━━■
       ┃                         ■┃
      ●┃● ● オ ブ ジ ェ ク ト 倶 楽 部   ■ ┃
       ┃                       ■  ┃
       ┗━━━━━━━━━━━━━━━━━━━━━━■━━━┛
                          No.44 2004/05/12

■ I N D E X
┃
┣【プログラミング】コード=カタで目指せ達人プログラマ [2]
┣【プログラミング】リファクタリング-プログラミングの体質改善 [7] 
┗【アンケート】気になるシステム業界 ホントのところ
 
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━1 s t ■━
■
┗【プログラミング】コード=カタで目指せ達人プログラマ [2]

■ はじめに
この連載では、Dave"達人"Thomasによるコード=カタを筆者による乱暴な要約
でお届けします。「コード=カタって何よ?」と思われた方は連載初回[*1]を
参考にしてください。

----------------------------------------------------------------------
カタ其のニ: カラテチョップ
----------------------------------------------------------------------
■ このカタの概要
二分探索(バイナリチョップ――散文的にはバイナリサーチと呼ばれることも)
はソート済の配列から、ある値の位置を特定します[*2]。アルゴリズムの基本。

このカタでは、後述する仕様にしたがって、自分の選んだ言語と技法でバイナ
リチョップを実装します。翌日には、異なる技法を利用して再び実装します。
その翌日にはまた同じことを行い――全く異なる5つの方法で5回実装するまで、
ひたすらバイナリチョップを続けます。これがこのカタがバイナリチョップで
あるゆえんです。……残念ながらこの後はこうした「カタっぽい」名前は出て
こないようですが。ちょっと寂しいですね。

原文では実装技法の例として、伝統的な繰り返し法、再帰、そして関数型の配
列スライスを渡す方法が挙げられています。なお、「全く異なる5つの技法で
実装することは至難の業だろう」とDaveもCodeKataメーリングリストで発言し
ていました。「5種類のアルゴリズム」ではなく5種類の技法(アプローチ)だと
考えてみれば何通りかの方法を思いつけるのではないでしょうか。

■ このカタの目標
1.それぞれの技法でのコーディングしているときに遭遇したエラーの種類を記
  録しておく。バイナリサーチは「一つ違い(off by one)」エラーとフェンス
  ポスト・エラーをやってしまいがち。日々実装を続けているうちに、こうし
  たエラーの発生頻度が減少するかを確かめます。(つまり、異なる技法でコー
  ディングする際には、他の技法の利用経験から学習しているのでは?)
2.選択した様ざまな技法の相対的な長所について、説明ができますか?
  本番コードとして利用するのにふさわしいものは? 書いていて一番楽しい
  ものは? 動かすのが一番難しいものは? これらの質問に対する回答に対し
  て自問自答しましょう――「なぜ?」と。
3.バイナリチョップの5つの技法をひねり出すのはかなり難しいです。どうやっ
  て4つめと5つめを考え出したのか、どのようなテクニックを利用して自分の
  脳のニューロンを発火させたのかについて、思いを巡らせてみましょう。

■ 仕様
整列済みの整数配列を対象とした、特定の整数の検索を二分探索法で記述して
ください。処理は戻り値として、対象配列の整数インデックスを返します。
配列のなかに検索対象が存在しなければ、-1を返します。以下はシグネチャの
論理的記述です:

   chop(int, array_of_int)  -> int

配列の要素は10万より少ないことを想定して構いません。このカタの目的に鑑
みて、処理時間とメモリのパフォーマンスは問いません――といっても、処理
が終わるのを待っている間に退屈してカタを止められても意味がありません。
コンピュータのメモリはそれなりに確保しておきましょう。

■ テストデータ
以下はDave提供の Test::Unit[*3]のコードです。御自由にどうぞとのこと。
カタで利用する言語にRubyを選ばなかった方はテキトウに検索&置換してくだ
さい:

  def test_chop
    assert_equal(-1, chop(3, []))
    assert_equal(-1, chop(3, [1]))
    assert_equal(0,  chop(1, [1]))

    assert_equal(0,  chop(1, [1, 3, 5]))
    assert_equal(1,  chop(3, [1, 3, 5]))
    assert_equal(2,  chop(5, [1, 3, 5]))
    assert_equal(-1, chop(0, [1, 3, 5]))
    assert_equal(-1, chop(2, [1, 3, 5]))
    assert_equal(-1, chop(4, [1, 3, 5]))
    assert_equal(-1, chop(6, [1, 3, 5]))

    assert_equal(0,  chop(1, [1, 3, 5, 7]))
    assert_equal(1,  chop(3, [1, 3, 5, 7]))
    assert_equal(2,  chop(5, [1, 3, 5, 7]))
    assert_equal(3,  chop(7, [1, 3, 5, 7]))
    assert_equal(-1, chop(0, [1, 3, 5, 7]))
    assert_equal(-1, chop(2, [1, 3, 5, 7]))
    assert_equal(-1, chop(4, [1, 3, 5, 7]))
    assert_equal(-1, chop(6, [1, 3, 5, 7]))
    assert_equal(-1, chop(8, [1, 3, 5, 7]))
  end

■ まとめと次回予告
今回のカタは「カラテチョップ」をお届けしました。このカタはMartin Fowler
から「こんなのカタじゃない。講義の演習じゃねえか」と物言いがついたらし
いですが、このカタで大事なのは「目標」を意識することです。コーディング
を身体感覚として体得し、他者に対して設計判断を言葉として伝える。自らが
行き詰った際の打開策を客観視する。いずれも実務で欠くべからざる基礎的な
技能だと思います。

筆者はRubyで挑戦してみたのですが、2種類で行き詰りました(;´Д`)
3種類以上こなせた方は是非、オブジェクト倶楽部編集部宛に見せびらかして
ください。お待ちしています。

次回のカタは「どれぐらい大きい?どれぐらい早い?」を予定しています。
内容はプログラマの心得るべき「見積」についてです。 (かくたに)

*1: http://objectclub.esm.co.jp/ml-arch/magazine/36.html

*2: http://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%8E%A2%E7%B4%A2

*3: Rubyのユニットテスト用フレームワークです。1.8からは標準ライブラリ
    としてRuby本体に同梱されています。
    http://www.ruby-lang.org/ja/man/index.cgi?cmd=view;name=Test%3A%3AUnit 
_______________________________________________________________________
この記事への評価にご協力をお願いします。
URLをクリックして、「ご協力ありがとうございました」のメッセージがご使用
のブラウザに表示されれば投票完了です。
良かった:
http://objectclub.esm.co.jp/cgi-bin/question.cgi?E004+2+0
普通:
http://objectclub.esm.co.jp/cgi-bin/question.cgi?E004+2+1
イマイチ:
http://objectclub.esm.co.jp/cgi-bin/question.cgi?E004+2+2

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━2 n d ■━
■
┗【プログラミング】リファクタリング-プログラミングの体質改善 [7] 
 
さて、前回は不吉な匂いから『巨大なクラス』を紹介しました。今回は予定通
り『・・・・・・』を紹介するのは、すいません、パスさせてください。前回
の予告をおぼえている方いらっしゃいますか? また、期待していた方、いら
っしゃいましたらすいません。あたまの中がうまくまとまりませんでしたので、
今回は予告とは異なりますが『属性、操作の横恋慕』を紹介したいと思います。

[属性、操作の横恋慕で見られる症状]
・やたらと他のクラスのgetメソッドを呼び出している

この症状が見られるときは、本来別のクラスにあるべきメソッドを実装してい
る可能性があります。『メソッドの移動』を行い、適切なクラスにメソッドを
移動しましょう。逆に、メソッドではなく属性が、あるべきクラスに所有され
ていないこともあります。そのようなときは、『フィールド(属性)の移動』
を行いましょう。

さて、それでは簡単な例を見てみましょう。サービス期間を管理する
ServiceTimeRangeクラスと商品を表すProductクラスがあります。Productクラ
スは与えられたServiceTimeRangeと現在時刻currentから、価格を決定します。
ソースコードは次のようになります。
--< before >----------------------------------------------------------
public class ServiceTimeRange {
  private Date start;
  private Date end;
  public Date getStart() { return start; }
  public Date getEnd() { return end; }
}

public class Product {
  public int getPrice(ServiceTimeRange range, Date current) {
    if (withinServiceTimeRange(range, current)) return DISCOUNT_PRICE;
    else return NORMAL_PRICE;
  }

  private boolean withinServiceTimeRange(
                      ServiceTimeRange range, Date current) {
    if (range.getStart().after(current)
        && range.getEnd().before(current)) return true;
    else return false;
  }
}
----------------------------------------------------------------------
全体を見渡すとメソッドの大きさも小さいですし、読みやすいですね。このソ
ースコードだけを見ていると、なかなか良さそうな印象を受けます。でも、ち
ょっと待ってください。ProductクラスのwithinServiceTimeRangeメソッドを
見てみましょう。何か気付きませんか?

この例では、Productクラスにサービス期間内かどうかを判定するこのメソッ
ドが実装されています。サービス期間内かどうかを判定したいのはProductク
ラスだけなんでしょうか?
次にメソッドの内部を見てみましょう。ServiceTimeRangeクラスのgetメソッ
ドをたくさん(といっても2回ですが)呼び出しています。しかもここでは、
サービス期間を扱う処理しかしていませんね。これってSerivceTimeRangeクラ
スにあったほうがいいんじゃないの?

上記の疑問から考えると、やはりこのメソッドはServiceTimeRangeクラスが所
有するほうが良さそうです。ServiceTimeRangeクラスに移動してしまいましょ
う。
このメソッドは外部のクラスから呼び出されるものなので、可視性はprivate
からpublicに変更します。それと引数の"ServiceTimeRange range"は、もう不
要ですよね。併せて内部もちょこちょこと修正しましょう。あとはメソッド名
をそれらしく変更して・・・と、これで完了です。
それでは、修正後のServiceTimeRangeクラスを見てみましょう。
--< after >-----------------------------------------------------------
public class ServiceTimeRange {
  private Date start;
  private Date end;
  public Date getStart() { return start; }
  public Date getEnd() { return end; }
  
  pubilc boolean includes(Date current) {
    if (start.after(current) && end.before(current)) return true;
    else return false;
  }
}
----------------------------------------------------------------------
良い感じになりましたね。まさに「適材適所」といった感じです。
クラスを分割して、1つのクラスの複雑度を下げることはもちろん重要ですが、
でたらめな形で複雑度が下がっても、やはり理解するのが難しいソースコード
になります。そういう理由で、どのクラスがどの属性・メソッドを所有すべき
か「適材適所」を念頭において考え、クラス定義を変更していくことが重要で
す。
また、今回の例ではメソッド全体が『メソッドの移動』の対象となりましたが、
メソッドの一部分で『横恋慕』の症状が見られるときももちろんあります。そ
のようなときには、『メソッドの抽出』を先に行い、その部分を分離してから
移動しましょう。

今回は『属性、操作の横恋慕』を紹介しました。みなさんの中にはお気付きの
方もいらっしゃるかと思いますが、いつでもどこでもこのルールを適用すると
良いわけではありません。きれいなソースコードでもこのルールから逸脱して
いることがありますよね。そう、例えば「Strategyパターン」のようにロジッ
クを構造から分離しているケースです。こちらは次回に紹介したいと思います。

わかりにくい点や質問などは随時とりあげていきたいと思いますので、気軽に
ご意見をお寄せください。また、記事の評価も今後の執筆の参考になりますの
で、気軽に投票にご参加ください。みなさんからのメール・投票をお待ちして
おります。(梅田) 
_______________________________________________________________________
この記事への評価にご協力をお願いします。
URLをクリックして、「ご協力ありがとうございました」のメッセージがご使用
のブラウザに表示されれば投票完了です。
良かった:
http://objectclub.esm.co.jp/cgi-bin/question.cgi?E002+6+0
普通:
http://objectclub.esm.co.jp/cgi-bin/question.cgi?E002+6+1
イマイチ:
http://objectclub.esm.co.jp/cgi-bin/question.cgi?E002+6+2
 
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━3 r d ■━
■
┗気になるシステム業界 ホントのところ

今週は「プログラマはコミュニケーションが得意?不得意?」のホントのとこ
ろ。最近ではウンザリするほど耳にするこの言葉。コミュニケーションと言っ
ても色々ですが、あなたは人とのコミュニケーションが得意ですか?

  私は達人です。
     http://objectclub.esm.co.jp/cgi-bin/question.cgi?Z001+10+0
  どちらかと言えば得意な方です。
     http://objectclub.esm.co.jp/cgi-bin/question.cgi?Z001+10+1
  ある種のコミュニケーションならうまくやっています。
     http://objectclub.esm.co.jp/cgi-bin/question.cgi?Z001+10+2
  どちらともいえません。
     http://objectclub.esm.co.jp/cgi-bin/question.cgi?Z001+10+3
  どちらかと言えば苦手な方です。
     http://objectclub.esm.co.jp/cgi-bin/question.cgi?Z001+10+4
  誰ともうまくいきません。
     http://objectclub.esm.co.jp/cgi-bin/question.cgi?Z001+10+5
  それは秘密です。
     http://objectclub.esm.co.jp/cgi-bin/question.cgi?Z001+10+6
  ちょっと語らせて!
     editors@ObjectClub.jp まで詳細を!!

アンケート結果はオブジェクト倶楽部HP上にて公開します。お楽しみに。
なお、前号「普及率が高いブラウザ」の結果は公開中。是非ご覧下さい。
⇒http://objectclub.esm.co.jp/ml-arch/magazine/question/index.html
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━--■--●--■
■
┗編集後記

こんにちは、編集人です。
5月。GWも過ぎましたし5月病の時節ですね。でも5月病になる暇がない方
もいらっしゃるのでしょう。先代の編集人のさとみさんは、GWはブラック・
ウィークになると漏らしておりました。せつない…。そんな方も、たまには口
開けて空でも眺めてくださいね。私は決して多忙な身ではないのですが(涙)、
今年は秘密の修行を新しく始めたので五十肩ですが、五月病の気配はありませ
ん。ふはは。
GW中に原稿を書いてきてくれたライターもいて、編集人としては、すこしニ
ッコリしてしまう休み明けでございます。ニコ…。
  
「オブジェクト倶楽部カレンダー」6月の電子データを公開します。6月の挿
絵のテーマは「デザイン・パターン(composite)」です。なお、7月のカレ
ンダーは、6月最初のメルマガ発行日に公開予定です。お楽しみに。
http://objectclub.esm.co.jp/calender/2004/
(さわ)
 
今週の強引な一言
*** Without Practice, No Emergence(道元禅師)***
「先日、永平寺に行ったときに道元禅師の言葉が飾ってあった。『修せざれば
現れず』修行のことをPracticeと言う。行うことをしなければ、そもそも見え
ないことがあるのだ。XPっぽいなー。」(〜平鍋の手記より〜)  

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━--■--●--■
● ご意見、ご感想は         ⇒このメールに返信ください
〇 配信中止、アドレス変更は ⇒http://objectclub.esm.co.jp/mlmagazine_help.html
〇 免責事項、過去の記事は   ⇒http://objectclub.esm.co.jp/mlmagazine.html
■ 発行:オブジェクト倶楽部 ⇒http://www.ObjectClub.jp/
■ 編集代表:平鍋  健児
Copyright (c)2003-2004 オブジェクト倶楽部. All Rights Reserved.
powered by Eiwa System Management, Inc.