読書ログ
インテルの製品開発を支えるSFプロトタイピング (プロフェッショナル&イノベーション)
- 作者: ブライアン・デイビッド・ジョンソン,細谷功,島本範之
- 出版社/メーカー: 亜紀書房
- 発売日: 2013/06/07
- メディア: 単行本
- この商品を含むブログ (6件) を見る
SFに惹かれて購入した。 初期のSFの歴史(小説、映画、コミック)の勉強にもなる。新製品開発の際に、ストーリーテーリングの技法に、 SF のテイストを加えた感じ。 さらっと書いたが、ネジを飛ばした新しいアイデアを練りたいなら、試してみていいんじゃね。
Value Object の学習メモ
私の Value Object の学習メモ
おれ、アナパタから入ったかも。
DDD
エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)
- 作者: エリック・エヴァンス,今関剛,和智右桂,牧野祐子
- 出版社/メーカー: 翔泳社
- 発売日: 2011/04/09
- メディア: 大型本
- 購入: 19人 クリック: 1,360回
- この商品を含むブログ (131件) を見る
私が、 Value Object について、再考するきっかけになったのは,やっぱりこの本。Entity と Value Object の違いといえば、アイデンティティを持つか持たないか、Value Objectはイミュータブルなど。サンプルだと、「顧客」の中に埋もれていた概念「住所」を Value Object として切り出し、よりドメインを明瞭にするという、ごくごく一般的な例が出てくる。
興味を引きつけたのは、8章のブレークスルーの物語。物語を要約すると、ドメインエキスパートと話が噛み合わない日々が続く。が、やがて、対話を通じて「シェアパイ」という重要概念を探り当てる。「そうそう、それ!」 シェアパイの概念を使った実装に代えるため、(現行スケジュールが遅れているにもかかわらず)マネージャーと交渉し了解を得て、実装する。後日談で、やがて、シェアパイの概念が 営業の人たちにも使われていく話(要約すると味気ないなw)。 実世界 -> ドメインモデルの1方向写像ではなく、ドメインモデル->実世界の逆方向写像の話になっていて、読んでいて、ドキドキする。(著者は渦巻き好きなので、ドメインモデルと実世界は循環して捉えていると推測される。)
この物語の重要概念のシェアパイを探りあてる補助線にあるのが、 Value Object。Supple Design も読んでおくと、Value Object とその周辺で役立つパターン(閉じた操作、副作用のない関数)を理解でき、8章がより楽しく読める。
DDDを読んでいると、Value Objectを使って、重要概念を明瞭にすることに、強いこだわりを感じる。
GOOS
実践テスト駆動開発 (Object Oriented SELECTION)
- 作者: Steve Freeman,Nat Pryce,和智右桂,高木正弘
- 出版社/メーカー: 翔泳社
- 発売日: 2012/09/14
- メディア: 大型本
- 購入: 4人 クリック: 262回
- この商品を含むブログ (31件) を見る
p16 に 値とオブジェクトの話が出てくる。また、p63から、値型を導入するテクニックとして、分解、発芽、包括が出てくる。
私の場合だと、 「String型、int型の基本データ型に執着していないか?重要概念を見落としていなか?」は時々考えるようになった。多分「発芽」に相当するもの。 DDDのシェアパイの話は、分解か包括か区別はわからなかった。
3部のサンプルの中では、最初ベタ書きだったコードを Value Objectを導入してコードをスッキリさせるシーンが何度か出てくる。
好きな文章は p16にある。
これはつまり、私たちはシステムをふたつの「世界」に分けたいということだ。 ひとつは関数的に扱われる値、もうひとつはシステムのステートフルな振る舞いを実装したオブジェクトだ
実践テスト駆動開発は、アランケイが構想した、オブジェクト同士のメッセージのやりとり重要を強調していることから、後者のオブジェクトがメインの語り口であるものの、前者の「値(Value Object)」についてもキチンと取り扱っており、時折出てくる。(関数型言語は、前者の世界を強調するだろう。Value Objectよりももっとうまく世界を表現できるはず。)
TDDの素振り
- ローマ数字の足し算や引き算を素振りする。
- ライフゲームを3回ぐらい解いてみる。4回目は immutable only の縛りで実装してみる。
あたりは、Value Object を再考するきっかけ例題としては良いんじゃなかろうか。
追記
Ruby で実装する場合
class Money < Struct.new(:amount, :currency)
と Structを使う手があることを知った。
別の Moneyの もりもりした実装例を覗いてみるのも手。
アプリケーションフレームワークの文法を妄想してた
rspec の文法を見ていると、 class XxxService, class YyyPolicy, class Zzz 。。。などを プロダクションコードから class 消し去りたい衝動が出てくる。
DDD, DCIを意識すると、こんなのが欲しい。
サービス
service Xxx, ' サービスの要約説明': before: .... exec 'サービスの振る舞いの要約説明': .... after: (成功失敗で分けたほうがいいかな。。。)
エンティティ
entity Zzz: (has_manyなどが使える)
ロール
role RoleName, Zzz: behave 'ロールの振る舞いの要約説明':
バリューオブジェクト
value Aaa(...): (.. ValueObject を書きやすくする なにかってあったけ。 Embedded Value, イミュータブル, 閉じた操作, 副作用のないメソッド...etc...)
ポリシー
policy Yyy(...): assert "ポリシーの説明": ... (Hamcrestのような述語が使える)
Cucumberを使って iPhone のテスト
Frankというやつがある。
- http://blog.thepete.net/blog/2012/06/24/writing-your-first-frank-test/
- http://testingwithfrank.com/
- https://github.com/moredip/Frank
一番上のプログが一番役立った。
githubにあった iosアプリを例に 素振りしてみた。
https://github.com/haru01/cheddar-ios
動かし方は Readme を参考に。(cheddarのユーザ登録、https://cheddarapp.com/developer/appsを参考に、CDIDefines.mの修正が必要。 )
記述ポイントは、次のファイル
https://github.com/haru01/cheddar-ios/blob/master/Frank/features/register_modify_delete_todo.feature
# encoding:utf-8 Feature: TODO List Scenario: タスクを追加編集削除できる Given I launch the app Then タスクリストを登録できる Then タスクを登録できる Then タスク名を編集できる Then タスクを削除できる Then タスクリストを削除できる
https://github.com/haru01/cheddar-ios/blob/master/Frank/features/step_definitions/tasks_steps.rb
# encoding:utf-8 World(TaskStepHelper) When /^I type keybord "(.*?)" and enter$/ do |key| type_into_keyboard key end Then /^タスクを登録できる$/ do step %Q|I touch "#{todo_list_name}"| step %Q|I wait to see "#{what_do_you_have_to_do}"| step %Q|I touch "#{what_do_you_have_to_do}"| step %Q|I wait for 1 second| step %Q|I type keybord "#{first_task_name}" and enter| end Then /^タスク名を編集できる$/ do step %Q|I touch "#{lists_button}"| step %Q|I touch "#{todo_list_name}"| step %Q|I touch "#{edit_button}"| step %Q|I touch "#{first_task_name}"| step %Q|I wait for 1 second| step %Q|I type keybord "EF" and enter| end Then /^タスクを削除できる$/ do step %Q|I wait for 1 second| step %Q|I touch "#{lists_button}"| step %Q|I touch "#{todo_list_name}"| step %Q|I touch "#{edit_button}"| step %Q|I touch "Delete"| step %Q|I touch "#{achirve_button}"| step %Q|I touch "#{lists_button}"| end Then /^タスクリストを登録できる$/ do step %Q|I touch "#{lists_button}"| step %Q|I touch "#{plus_button}"| step %Q|I wait for 1 second| step %Q|I type keybord "#{todo_list_name}" and enter| end Then /^タスクリストを削除できる$/ do step %Q|I touch "#{edit_button}"| step %Q|I touch "Delete"| step %Q|I touch "#{achirve_button}"| end
既にあるステップは、下記が 参考になる。
- http://testingwithfrank.com/supplied_steps.html
- https://github.com/moredip/Frank/blob/master/gem/lib/frank-cucumber/core_frank_steps.rb
iOS独特のセレクターでうまく、画面要素を指定するキーを見つけるのがちょっとわかりにくい。
一応、要素をさがすためのinspectorも付いてくるのでそこから探すのだが。。。。
$frank inspect
Objective-Cの練習
#import "Kiwi.h" #import "Underscore.h" #define _ Underscore @interface RomanNumber : NSObject @property (readonly) NSNumber *number; @property (readonly) NSString *romanStr; @end @implementation RomanNumber -(id)initWithNum:(NSNumber *)aNumber { // TODO 引数が 1-3999 以外の場合 self = [super init]; if (self) { _number = aNumber; _romanStr = [self convertRomanStr:_number]; } return self; } -(id)initWithRomanStr:(NSString *)aRomanStr { // TODO 引数がローマ数字でないばあい self = [super init]; if (self) { _romanStr = aRomanStr; _number = [self convertNumber: _romanStr]; } return self; } -(NSString *) toString { return [self convertRomanStr:_number]; } -(NSNumber *) convertNumber:(NSString *)aRomanStr { // 総当たりでマッチするものを探す方法 for(int i=0; i<4000; i++ ) { NSNumber *n = @(i); NSString *other = [self convertRomanStr:@(i)]; if ([other isEqualToString: aRomanStr]) { return n; } } return @(-1); } -(NSString *) convertRomanStr:(NSNumber *)aNumber { NSDictionary *nums = @{ @1: @"I", @4: @"IV", @5: @"V", @9: @"IX", @10: @"X", @40: @"XL", @50: @"L", @90: @"XC", @100: @"C", @400: @"CD", @500: @"D", @900: @"CM", @1000: @"M", }; id romanStr = [nums objectForKey:aNumber]; if (romanStr) { return romanStr; } for (NSNumber *base in [self keysDesc:nums]) { int diff = [aNumber intValue] - [base intValue]; if (diff > 0) { return [NSString stringWithFormat:@"%@%@",[self convertRomanStr:base], [self convertRomanStr:[NSNumber numberWithInt:diff]]]; } } return @""; } -(NSArray *) keysDesc:(NSDictionary *) dictionary { NSMutableArray *keysDesc =[NSMutableArray arrayWithArray:Underscore.keys(dictionary)]; [keysDesc sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { return [obj2 compare:obj1]; }]; return keysDesc; } -(RomanNumber *) plus:(RomanNumber *) other { return [[RomanNumber alloc] initWithNum:@([self.number intValue] + [other.number intValue])]; } - (BOOL)isEqual:(id)other { if (other == self) { return YES; } if (!other || ![other isKindOfClass:[self class]]) { return NO; } if ([[self number] intValue] != [[other number] intValue] ) { return NO; } return YES; } @end SPEC_BEGIN(RomanNumberSpec) describe(@"RomanNumber", ^{ // 数字をローマ数字に変換できること _.dictEach(@{ @1: @"I", @4: @"IV", @5: @"V", @9: @"IX", @10: @"X", @40: @"XL", @50: @"L", @90: @"XC", @100: @"C", @400: @"CD", @500: @"D", @900: @"CM", @1000: @"M", @3: @"III", @6: @"VI", @11: @"XI", @39: @"XXXIX", @44: @"XLIV", @95: @"XCV", @345: @"CCCXLV", @3999: @"MMMCMXCIX", }, ^(NSNumber *number, NSString *expected) { NSString *itStr = [NSString stringWithFormat:@"数字:%@をローマ数字:%@に変換できること", number, expected]; it(itStr, ^{ RomanNumber *roman = [[RomanNumber alloc] initWithNum:number]; [[[roman romanStr] should] equal: expected]; }); }); it(@"ローマ数字の文字列から数値変換ができること", ^{ RomanNumber *romanA = [[RomanNumber alloc] initWithRomanStr:@"CCCXLV"]; [[[romanA number] should] equal: @345]; RomanNumber *romanB = [[RomanNumber alloc] initWithRomanStr:@"MMMCMXCIX"]; [[[romanB number] should] equal: @3999]; }); it(@"ローマ数字の足し算ができること", ^{ RomanNumber *one = [[RomanNumber alloc] initWithRomanStr:@"I"]; RomanNumber *three = [[RomanNumber alloc] initWithRomanStr:@"III"]; RomanNumber *four = [[RomanNumber alloc] initWithRomanStr:@"IV"]; [[[one plus:three] should] equal:four]; [[[[one plus:three] number] should] equal:@(4)]; }); // TODO // - 引き算 // - ローマ数字のソート }); SPEC_END
文法がちょっと覚えにくい。修正版は下記に。
https://github.com/haru01/objective-c_kiwi_testsample
成長ループとその成長を制限するバランスループ
フィールドブック 学習する組織「10の変革課題」―なぜ全社改革は失敗するのか?
- 作者: ピーターセンゲ,Peter M. Senge,柴田昌治,牧野元三,スコラコンサルト
- 出版社/メーカー: 日本経済新聞社
- 発売日: 2004/06
- メディア: 単行本
- 購入: 1人 クリック: 12回
- この商品を含むブログ (13件) を見る
この本、システム原型だと「成長の限界」を軸に描かれている。学習、チェンジマネジメント、改革、改善をしていこうとする時に、よく発生する課題をシステム思考を使って整理し、どんな思い込み(メンタルモデル)に注意すべきか、全体のつながりとしての背景やバランスループ(課題)を理解し解決の糸口となるレバレッジポイントがどこにあるのか、バランスループ(課題)に対処していく典型的なワークショップ案にどのようなものがあるかが解説されている。
読み返したのは、はじめにから、課題1: 時間がない「こんなことをしている時間はない!」, 課題2: 孤立無援「誰も助けてくれない!」, 課題3:意味がない「こんなものは意味がない!」, 課題4: 言行不一致「言っていることとやっていることが違う!」, 課題:5 恐れと不安 「こんなものは○○○だ! 」 課題:6 評価と測定 「効果がない! 」 まで。
繰り返し読んでいたつもりだが、前回までは身近に感じていなかった。今回ようやく自分の身にかなり近い課題だと実感がわいてきた。どの課題も過去に(今も)何度見てきた「あるある」ネタになっている。
「時間がない」は、かならずは聞く言葉なのでヒントがある。押し売りで始まる改革は大抵「意味がない」に打ち当たる。年を食って上の立場、指導する立場になる人であれば、「言行不一致」には注意されたし。恐怖政治、コマンドコントロールからの脱却(メンタルモデルの克服)はなかなか難しいテーマ。「恐れと不安」にヒントがある。また通常新しいことにチャレンジするのであれば「恐れと不安」がつきものだ。サムライの「これは魔女狩りではない」の言葉の裏が見えてくる。 活動の周りへの説明に、評価と測定の課題は必ず付いてきて避けては通れない。まずは「評価」の言葉の意味の理解から。(報告よりも)自分たちの学習に使える楽しい「評価」にしてしていくことが肝要。