DoorKeeper
http://devlove.doorkeeper.jp/events/4060
場所は新橋のリクルート メディアテクノロジーラボさんです。
参加者は50人くらいでしょうか。
主催はDevlove&CodeIQさんで、講師は増田さん。そして今回のテーマは以下だそうです。
今回のDevLOVEは、CodeIQさんの協力を得て、オブジェクト指向設計をテーマに開催します。
具体的な問題に対して、オブジェクト指向ではどのように考えるのか、トライしてみましょう。
むむむ、いかにも楽しそう!
というわけで速攻で申し込んだら、いつの間にかTOPになっていた件。。。

ちなみに私、CodeIQ(コードアイキュー)というサイト、今回始めて知りました。
https://codeiq.jp/
「自分の実力を知りたいITエンジニア向けの、実務スキル評価サービス」らしいです。
いろんな問題が公開されてて、それにチャレンジできるようになっており、出題者からフィードバックも受けれる仕組みだそうな。
エンジニアなら、腕試しにちょっと挑戦したくなっちゃいますね!
というわけで私も事前課題にチャレンジしようとしたら、その前日に回答期限が締め切られていた。。。
んで再掲載されないかなぁと思ってツイートしたら、@papanda さんが救済してくださいました!感謝!
@makopi23 問題文へのリンクをdoorkeeperに貼っておきました。ご参考までに ;) devlove.doorkeeper.jp/events/4060
— ichitaniさん (@papanda) 2013年6月10日
というわけで、今回の出題を事前に解いてみてから当日参加しました。
■ちゃんとオブジェクト指向ができるようになるために -解説編-
当日は参加者3~5人でグループを作り、出題内容を各自で考えてみた後、各グループでディスカッションを行いました。
んで、増田さんからオブジェクト指向設計に関するレクチャーと、CodeIQでの解答例の紹介などが行われました。
以下、メモ。
■出題1

あるWebサービスの会員登録の画面で、以下の入力が必要です。 ・氏名 ・メールアドレス ・パスワード ・パスワード(確認用) 入力は、以下のルールを満たす必要があります。 ・氏名は20文字以内 ・メールアドレスは、正しい形式 ・パスワードは、半角英数字で、大文字・小文字・数字の三つが混在 ・パスワードと確認用パスワードが一致する この入力チェックを実現するためのクラスを考えてください。 ※ 一つの問に複数のクラス名を解答してもかまいません。 ※ 同じクラス名を複数の問に重複して回答してかまいません。 |
私の解答と、グループメンバーの解答はこんなカンジ。
私の解答 | グループメンバの解答 | 備考 | |
(1) 入力情報を保持するクラス名 | MemberRegistForm | ①MemberRegist ②Member ③InputData ┣ Name ┣ Password ・・・ | 私の解答は、画面毎に 【画面名+Form】というクラス名とする案。 ③は構造体みたいなデータ構造とする案で、氏名やパスワードも子としてクラスにし、親のInputDataに持たせる階層構造としている。 |
(2) 氏名の20文字以内をチェックするクラス名 | NameFormatChecker | ①NameLengthCheck ②Name | 私の解答は、【チェック対象+Checker】というクラス名にする案。②は、ドメイン駆動設計(DDD)を意識したもの。NameクラスやPasswrdクラスに、データとチェックメソッドの両方を持たせる。 |
(3) パスワードをチェックするクラス名 | PasswordFormatChecker | ①PasswordFormatCheck ②Password | |
(4) パスワードと確認用パスワードの一致をチェックするクラス名 | PasswordEqualityChecker | ・PasswordDoubleCheck ・Password | |
(5) クラス名の数は全部でいくつ? | 5 | (1)~(4) + ※ = 5 | |
※ (1)~(4)の回答に登場しないクラスの名前も | MemberRegistFormChecker | 画面毎にチェッカークラスを用意し、データ項目ごとのチェッカーを呼び出す指針。 |
ウチのグループは大きく2パターンに分かれました。
■パターン1
・画面データ保持用のクラスを1つ作り、各データ項目はフィールドで持たせる。
・各データ項目用にチェッカークラスを作成する。
■パターン2
・画面の各データ項目をそれぞれクラスとする。(氏名ならNameクラス、パスワードならPasswordクラス等)
・各データ項目のクラスに、データフィールドとチェックメソッドの両方を保持させる。
---
私はパターン1で設計しました。
パターン2は、ドメイン駆動設計を意識してますねー。
かくいう私も、パターン2も検討しました。
んでもDDD本、まだ途中までしか読んでないので、俺にはまだ早すぎる!ということで見送った。
![]() | エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践) (2011/04/09) エリック・エヴァンス 商品詳細を見る |
あと(1)の③は、checkメソッドだけ持つInterfaceを1つ用意し、Nameクラスとかは全部このInterfaceを実装(implements)する設計だそうな。
他に出た意見としては、コンストラクタの引数で氏名やメールアドレスが渡されたときに、コンストラクタの時点でチェックを行う、という案がありました。
チェックで不備があったデータは、そもそもインスタンスやフィールドとして存在させない、というポリシーですね。
各グループの発表を聞く限りでも、概ね上記2パターンに分かれたグループが多かったようです。
他には以下のような案が出ました。
■複数種類のユーザの存在を考慮した設計
・「User」というクラスに、フィールドとしてname(氏名)とかpassword(パスワード)を持たせる
・ユーザクラスとしては管理者権限(AdminUserクラス)とか一般権限(CommonUser)とか何種類か考えられるので、「BaseUser」という基底クラスを用意し、継承させる仕組みにする。
■データ保持とチェッカを分離した設計
ユーザ情報を保持するクラスと、チェックを行うクラスに分ける。(パターン1とほぼ同じ)
■ストラテジーパターンを利用した設計
妥当性を評価するポリシークラスを作って、ストラテジーパターンで依存性を注入する。
クラス名(人数) | 増田さんのコメント | |
(1) メインクラス名 | ・User (21) ・Member (13) ・Input (13) ・Account (5) ・Regist (5) ・Signup ・その他 (26) | ・Inputというクラス名だと、何の入力か区別できない ・Registという単語は和製英語。本来は末尾に "er" が必要。 でも通じるなら使ってもいいんじゃないか |
(2) 検証クラス名 | ・xxxValidator (21) ・CheckxXxx (15) ・xxxChecker (9) ・その他 (24) ・なし (17) | 「その他」は、アノテーションでチェックする、という解答もあった。 個人的な感覚だと、「Validator」は技術用語になっているので、「Checker」のほうがお客さんに伝わるかな。 なので「validator」よりは「checker」に軍配をあげたい。 |
(3) データクラス名 | ・なし (26) ・xxxInfo (20) ・xxxForm (13) ・xxxData (7) | なくても通じるなら短めでもいい。 |
■増田さんのフィードバック
■今回の出題
・設計の基本をテーマにしようとした。
・でも、テーマを失敗したかもしれない。。。入力のバリデーションに特化してしまったので。
・もっと一般的なネタがよかったかも。
・今回の問題は「他の人が今後メンテしていくこと考えた設計になっているか」を評価基準にした。
・出題どおりに設計して、「完了しました」と言っているようではダメ。もっと上を目指すべき。
・出題の文面から、「もっとこーゆうのがあるよね」とツッコミを入れられる技術者になるべき。
■皆さんの解答例
今回は、以下のようなカンジに回答が分かれたらしい。
① データを持たせるUserクラスがいて、それをチェックするUserValidatorというクラスが1ついるパターン
② データを持たせるMemberクラスがいて、チェック用のクラスとしてCheckNameとかCheckPasswordとかを個別に用意するパターン
③ Nameクラスとかを個別に作り、Nameのバリデーションまでそこに持たせるパターン
・他にも、以下のような解答例があった。
④ クラス数が6以上の案を回答した人も20名くらいいた。彼らはバリデーションの仕組みを自作していたのが多かった。
⑤ アノテーションを使ったバリデーションを徹底してる回答者もいた。
---
■増田さんのコメント
・何が正しくて、何が間違っている、ということはない。ニーズによって変わる。
・自分がメンテナンス技術者だったら、「どの設計がいいか」という意見はあるはず。
→ 設計の良い/悪いより、他の技術者がメンテしやすいかを考える。
・ソフトウェアを成長させていくときに、どういう設計になっていがほうが他の人が理解しやすいか、3年後の自分が理解できるかを考える。
・創造力の勝負
■増田さんのオブジェクト指向設計
・クラスは小さくしたほうがよいと個人的に思っている
・設計にこだわってみたい、とかの気づきが大事。
・ペアモデリングとかペア設計もガンガンやるべき。
・雑談レベルでいいので、同僚に「俺はこう考えたんだけど、どうよ?」って話してみるのがいい。
・「設計はかくあるべき」というのは無いと思っている。ただ、ある文脈の中で仕事しているので、設計にこだわりもある。
・例えば、「オブジェクトの役割は小さくする」というこだわり。
・後々、メンテナンス性とか保守性とか、変更が入った時の強さを考慮すると、単一責任は常に意識したいと思っている。
・「データ+ロジック (オブジェクトの凝集性)」というのを、保守性を高めていく道としてこだわり続けていくのが良いのでは。
・ちなみに、「~Validator」とか「~Caliculatro」というクラス名は、増田さんのプロジェクトでは却下している。
→ 「~Validator」とかを許容してしまうと、考えずにそうしてしまうことが多くなるので。
・マーチン・ファウラーとケントベックの著書「リファクタリング」の最後の方に、「 大きな分離」という項がある
→ 手続き的な設計からオブジェクト指向らしい設計へ地道にリファクタリングしてきました、と書いてある。
・増田さんは、コテコテのケントベック派。鵜呑みにしている。
→ でも、それが正しい設計だと言うつもりはない。
・こだわってるのは、変更したときにたくさんいじらなくてよい、保守しやすい、ということ。
・どこに何が書いてあるかがすぐわかる設計が良い。
あとスライドには出題2に対する紹介と説明もありました。スライド公開が待たれる。。。
■質疑応答
■Q1.
引っかかるのは「オブジェクト指向らしい設計とは」ということ。
今回の解答例で、「名前」とかをオブジェクトとして捉える、という考え方に引っかかっている。
というのも、現実世界の写像をオブジェクトとして捉えるべき、とこれまで習ってきた。
「名前」ってのは現実世界のオブジェクトではないはず。
なのでこれまでは、「名前」しか扱わない場合でも、「会員」というオブジェクトの属性として「名前」を扱え、と設計してきた。
「名前」でクラスすると、それだけで一人歩きする。
「会員」というオブジェクトの属性に「名前」を持つのがオブジェクト指向設計だと私はそう思っていた。
これについてどう思うか?
■A1.
たしかにオブジェクトは「現実正解の写像」と言っていた時代があった。
でも、それはすごく嫌。
人間の頭の中の概念は、オブジェクトの候補になると考えている。
用語はルールを持っている。ルールの書き場所としてクラスを宣言してしまえという考えに立つ。
ただ、「名前」をクラスにすることががオブジェクト指向である、ということにこだわりはない。
どういう持たせ方をすべきか、にこだわりがある。
例えば今回の出題にあった「パスワード」なら、「パスワード強度」というクラスを抜き出すかもしれない。
「パスワード強度」というのは現実世界にモノとして存在しない。
でも、ルールとかポリシーの変更があるから、クラスとして抜きだしたい。
ビジネスとかルールの制約を書き込むのがクラスだと思っている。
集約の粒度を下げようとはおもっていない
メソッドに分ける感覚でオブジェクトを分けちゃう。
---
■Q2.
データとロジックを1つに纏める、という設計で疑問がある。
複合データチェックはどのクラスに置くべきか?
■A2.
一緒にあったほうが自然なら、一つのクラスに纏める。
データの発生のタイミングとか変更のタイミングが同じものはまとめたい。
タイミングが違うなら違うクラスにしたい。
例えば、「メールアドレス」と「パスワード」の変更のタイミングは違う。
一緒なのは最初の登録のタイミングだけ。なので、クラスは分けたい。
---
■Q3.
クラスとかメソッドの名前を付けるときに、ロジックを作り込む以上に時間がかかる。
名前付けに悩むぐらいなら、一個のクラスに突っ込んでしまえ、とやってしまう。。。
増田さんは名前付けに一貫性を持たせてやってらっしゃるとおもっているが、プロジェクトごとにポリシーを分けたりしているのか?
■A4.
名前は辛いよね。。。
8~9割は、こんなかんじかな、でいけちゃう。でも、残りの1割は悩む。
良いクラス名が思いつかないクラスは、メソッドが増えて肥大化してくるのが実態。
そのクラスはお客様のキーポイントになっているので、「楽しいリファクタリングの時間」として対処する。
幸いお客様と継続でやっているので、「いい名前わかった!」と後でなったらリファクタリングをしている。
---
■Q5.
オブジェクト指向でプログラムを作ると、性能が気になることがある。
そこの折り合いはどうつけてるか?
■A5.
最近思うのは、「良い時代になったなぁ」ということ。CPUもメモリも安くなった。
最近は性能を考えなくても痛い目をみることは少なくなった。
今は、早い段階で実データ規模を投入して実行してみて、ボトルネックを見つけてそこだけ手を入れるようにしている。
カットオーバー直前に性能をみるんじゃなくて、早めに見ることが大事。
ただ、個人的にはそんなにハイトランザクションのアプリにはぶちあたってない。
10年前だと、「このオブジェクト指向設計でやると動かない!」とかあったはず。
でも、Javaの出た直後と今では、Javaの性能は全く違うものになっている。
---
■最後に増田さんから一言
・今回CodeIQに提出された解答を採点してて、すごく勉強になった。
・他の人の意見を聞くことは大事。自分のスキルを上げる機会だと思う。
★感想:
事前に出題に取り組んで、事前に提出して、事前に採点してもらい、解説を聞きに当日勉強会に参加する。
この流れは他の勉強会と違って斬新ですねー。素晴らしい企画だと思います。
自分でまず考える、という過程が入ることによって、理解度も格段に上がるのがデカいです。
他のエンジニアさんの解答例を紹介してもらえるのも良いですねー。
当日はディスカッションで他のエンジニアの考えを直接聞くこともできましたし。
大変勉強になりました。
こーゆうの、これからもやってほしいなぁ。
あと、けっこーDDD的な設計を意識している人が多かった気がします。
これはDDD本を読み進めざるを得ないッ!と思うヒトトキでした。
当日のスライドは後で公開してくださるとのことで、楽しみに待っていよう。
最後に講師の増田さん、papandaさん始めスタッフさん、CodeIQさん、ありがとうございました。