オブジェクト指向を学ぶ姉妹 4章(1)
はじめに
妹「うーん……」
姉『どうしたの?妹ちゃん』
妹「4章まで読んだんだけどね~お姉ちゃんにどう教えようかな~って」
姉『そんなに難しいの?この[インターフェース]って』
妹「ううん~インターフェース自体はそんなに難しくないよ~」
姉『えっじゃあよくない?』
妹「んとね、この本の2章あたり最初読んだとき、メッセージが重要って書いてなかった?」
姉『あーあったねぇ。ひとまずはそれは置いておいてクラスを主体に教えるって』
妹「この4章を通じて、メッセージとは何か、なぜ重要かが書かれてるんだけど……」
姉『わかりづらかった?』
妹「めっちゃわかりやすかった!」
姉『えっじゃあよくない?』
妹「ただ例を出しながら順を追って教えてくれてて、それをまるまる書くと劣化コピーだしな~って」
姉『うーん、じゃあひとまず、インターフェースについて教えてよ!』
妹「そうだね~メッセージについてはまた後で考えるね」
姉『うん!』
インターフェースを理解する
妹「えーとまずね、インターフェースって2つ意味があるんだよね~」
姉『そうなんだ』
妹「1つめはこれから学ぶ、クラス内にあるインターフェース」
姉『ふんふん』
妹「2つめは5章で学ぶ、ダックタイプと呼ばれるクラス外のインターフェース」
姉『おっけー、いったん2つ目は忘れるねぇ』
妹「話が早すぎる」
姉『でもさークラス内のインターフェースって何?変数とメソッドしかなくない?』
妹「お姉ちゃんさ、javascriptとかで [private] とか [public] とか見たことない?」
姉『あー変数名とかメソッドの前につけるやつ?』
妹「あれの意味わかる?」
姉『なんか、たしか、公開範囲を決めるんだっけ?』
妹「おお~~~!あってる!お姉ちゃん天才!」
姉『とりあえずpublicってつけておけばいいんだよね?』
妹「あほちん!!!」
姉『落差激しい』
妹「まずね、 [public] ってつけられたメソッドや変数を [パブリックインターフェース] って呼ぶの」
姉『おー。じゃあ [private] は [プライベートインターフェース] ?』
妹「正解!Pythonだと、変数名とかの前に[ __ ] をつけると [private] になるよ~」
class Sample: def __init__(self, value1, value2): self.value1 = value1 # パブリックインターフェース self.__value2 = value2 # プライベートインターフェース if __name__ == "__main__": sample = Sample("パブリック", "プライベート") print(sample.value1) print(sample.__value2)
パブリック Traceback (most recent call last): File "c:/Develop/ObjectOrientedDesign/Python/SisterAttack.py", line 9, in <module> print(sample.value2) AttributeError: 'Sample' object has no attribute 'value2'
妹「こんな感じ!」
インターフェースを定義する
姉『 [private] にすると外から使えなくなっちゃうんでしょ?なんでそんなことするの?』
妹「例えばなんだけど、3章でこんな感じのコードを書いたじゃん?」
class Panch: def __init__(self, weight, grip, speed): self.weight = weight self.grip = grip self.speed = speed def calcAttackDamage(self): return self.weight * self.grip * self.speed class Person: def __init__(self, name): self.name = name @property def weapon(self): return Panch(45, 32, 370) def sayAttackDamage(self): return self.name + "の攻撃力は" + str(self.weapon.calcAttackDamage()) + "だよ~" if __name__ == "__main__": imouto = Person("妹") print(imouto.sayAttackDamage())
妹の攻撃力は532800だよ~
妹「PersonクラスでPunchを使うけど、外に出せないからせめてって責任を分離したやつ」
姉『あーフリーザ様だったやつだね』
妹「たとえばここに続けて、Groveクラスをこんな風に書きました」
class Panch: # 前略 def calcAttackDamage(self): return self.weight * self.grip * self.speed class Person: # 前略 @property def weapon(self): return Panch(45, 32, 370) # 後略 class Grove: def __init__(self, ounce): self.ounce = ounce self.person = Person() def calcGroveDamage(self): return (1 / self.ounce) * self.person.weapon.calcAttackDamage() if __name__ == "__main__": # 前略 grove = Grove(24) print(grove.calcGroveDamage())
22200.0
妹「これみてどう思う?」
姉『GroveがPersonに依存してるけど、Personって変更激しそうだからよくない!』
妹「うんうん、3章がよく身についてるね~。他には?」
姉『んー……。感覚的にはGroveがPersonを経由してPunchにアクセスしてるのが気持ち悪い……』
妹「!!!その感覚すごい大事だよ!おねえちゃん!」
姉『でもGrove側でPersonと同じようにPunchを呼び出すのもDRY原則に反しちゃうしなぁ』
妹「いい感じに単一責任の考えが身についててわたしちょっと泣きそう」
姉『どうしたらいいの?』
妹「これの答えを出すのは今は置いておいて、そもそもの話するね~」
姉『うん』
妹「まず、ほんとはPersonクラス内でPunchクラスを参照したくないの」
妹「でもオブジェクト注入ができないから仕方なくクラス内に書いてます」
妹「ただ想いとしては別のところに書きたい。修正したい箇所なの」
妹「そんなことは露知らず、GroveはPersonからPunchを利用してしまった。」
姉『あー』
妹「こうなるともう、PersonからPunchの参照を取り出すのが難しくなってこない?」
姉『なんとなくわかった』
妹「そう。だから今回の場合、Person内のweaponの記述は、[private]で書くべきなの」
姉『外から使えなくすることは、余計な依存を増やさないって利点があるんだねぇ』
妹「そうそう。プログラムの世界では、知らない・使えないこともひとつの価値なんだよ~」
パブリック、プライベートの分け方について
姉『ひとまずおっけー!変更されやすいものはプライベートインターフェースにするね!』
妹「あ、それ以外にもパブリック、プライベートを分ける目安があるから教えちゃうね」
姉『あ、知りたい知りたい』
妹「まずはパブリックインターフェースについてだね~」
パブリックインターフェース
- クラスの主要な責任を明らかにする
- 外部から実行されることが想定される
- 気まぐれに変更されない
- 他者がそこに依存しても安全
- テストで完全に文書化されている
姉『パブリックインターフェースはあんまり変更しちゃダメなんだねぇ』
妹「自由に使われた後に変更しちゃうと壊滅するのは今まで見てきた通り」
姉『うんうん』
妹「2章で単一責任の考え方に、責任の説明が一言でできることってあったよね?」
姉『言ってたかも?』
妹「基本的にその責任が、クラスのパブリックメソッドになってるはずなの」
姉『なるほどねぇ』
妹「そうやってインターフェースを整理すれば、自然と綺麗な依存関係ができあがるよ!」
姉『はーい』
妹「次はプライベートインターフェースだね~」
プライベートインターフェース
- 実装の詳細に関わる
- 他のオブジェクトから送られてくることは想定されていない
- どんな理由でも変更され得る
- 他者がそこに依存するのは危険
- テストでは言及さえされないこともある
妹「ちなみにプライベートインターフェースも、外からアクセスできちゃうことは覚えておいてね」
姉『えっじゃあ意味ないじゃん』
妹「普通に書くとアクセスできないから、意味ないことはないよ~」
姉『でも書き方変えたらアクセスできちゃうんでしょ?』
妹「非推奨だし、書いた人にとってはアクセスさせたくないって想いが伝わるでしょ?」
姉『なんでアクセスできちゃうの?』
妹「仕様は変わるからだね~。今必要なくても後々外で使う必要ができることもあるでしょ~」
姉『あー。なるほどねぇ』
妹「クラス内のインターフェースについてはこんな感じかなぁ」
デメテルの法則
妹「それからさっきね、お姉ちゃんすごくいいこと気づいてたよ!」
姉『ほえ?』
妹「感覚的にはGroveがPersonを経由してPunchにアクセスしてるのが気持ち悪い」
姉『あーうん、最初のコードに対する感想?』
妹「そう!それね、デメテルの法則そのもの!」
姉『名前からパッと内容がわからない法則とかやめてほしいなぁ』
妹「デメテルの法則を要約すると、 [直接の友達とだけ話すこと] 」
姉『デメテルさんは根暗』
妹「さっきのはPersonを介してPunchと話してたでしょ?そういうのやめてねってこと」
姉『友達の友達は敵理論ってことだね!』
妹「ま~その認識でもいいのかな~?」
姉『デメテルさんとはいい酒が呑めそう』
妹「デメテル、人じゃなくて豊穣の女神だからね?」
姉『女神が根暗!そそるー!』
ここまでのまとめ
妹「ひとまずクラス内のインターフェースについては説明おしまい!」
姉『んー……』
妹「なにか引っ掛かるところあった?」
姉『結局、GroveクラスがPunchクラスを使う方法がわからなかったなーって』
妹「それの正解を導くには、まずメッセージについて知る必要があるの~」
姉『あー、最初に何か言ってたね』
妹「メッセージについての説明方法も思いついたから、ちょっとまとめるね~」
姉『うん!妹ちゃんいつもありがとねぇ』
オブジェクト指向を学ぶ姉妹 3章
3章 依存関係を整理する
はじめに
姉『ねぇねぇ妹ちゃん』
妹「な~に?おねえちゃん」
姉『もう勉強飽きてきたからじそろそろ実践いきたいなぁ』
妹「こらぁ!!!」
姉『ようするに責任を小さくして作ればいいんでしょ?もう楽しょーだよ!』
妹「んとね、小さく作るとね、ひとつひとつは保守しやすくて幸せなの」
姉『うん、いけるいける』
妹「ただ使い方も意識して作っていかないと、すぐに失敗しちゃうよ?」
姉『えぇ---』
妹「すぐわかるから、もうちょっと付き合ってよ~」
姉『しょうがいないなぁ』
依存関係を理解する
妹「あのね、わたしがお姉ちゃんを攻撃するとするじゃん?」
姉『やめて』
妹「攻撃力を測るプログラムを書くね」
class Panch: def __init__(self, weight, grip, speed): self.weight = weight self.grip = grip self.speed = speed def calcAttackDamage(self): return self.weight * self.grip * self.speed class Person: def __init__(self, name): self.name = name def sayProfile(self): return "わたしは" + self.name + "だよ~" def sayAttackDamage(self): return "わたしの攻撃力は" + str(Panch(45, 32, 370).calcAttackDamage()) + "だよ~" if __name__ == "__main__": imouto = Person("妹") print(imouto.sayProfile()) print(imouto.sayAttackDamage())
わたしは妹だよ~ わたしの攻撃力は532800だよ~
妹「仮にこんな感じだとして、どう思う?」
姉『フリーザ様って呼ぶね』
妹「やめて」
姉『んーーー責任を分散してるし、問題ないんじゃない?』
妹「んとね、分散してるように書かれてるけど、実際は2つのクラスが密接に結合しちゃってるの」
姉『えええーーー』
妹「たとえば~」
- 「Panch」が存在することを、クラス「Person」は知っている
- 「Panch」に「colcAttackDamage」が存在することを「Person」は知っている
- 「Panch」の引数に「weight」「grip」「speed」が必要であることを「Person」は知っている
- 「Panch」の引数が「weight」「grip」「speed」の順であることを「Person」は知っている
妹「って感じで、PersonはPanchのことを知りすぎちゃってるの。」
姉『ふんふん。それだと何か悪いの?』
妹「例えばPanchのクラス名とか変数変えたら、Personまで修正が必要になっちゃう」
姉『んー、でもそれってしかたなくない?』
妹「ある程度は仕方ないんだけど、上のは不必要な依存ばっかなんだ~」
姉『依存関係を理解すれば、そういう修正が必要なくせるってこと?』
妹「うん!ある程度は減らせるよ~!」
姉『だいたいわかった!じゃあその回避方法教えてー!』
疎結合なコードを書く
妹「上で4つの結合ポイントを話したから、その結合ポイントを順を追って潰していくね~」
姉『じゃあ最初はこれかな?』
- 「Panch」が存在することを、クラス「Person」は知っている
姉『正直クラス名変えたら、VSCodeが勝手に修正してくれるから別に問題ないんだけどねぇ』
妹「喝っ!」
姉『喝っ!された』
妹「クラス名が変わったときだけじゃなくて、他にも上のには致命的な所があるんだよ!」
姉『えぇぇー後出しー!』
妹「例えば私が日本刀を装備したとするじゃん?」
姉『殺意のかたまり』
妹「sayAttackDamageを使って日本刀の攻撃力を出力したいのに、Panchクラスが占有しててできないの」
姉『あーたしかに。これだとパンチ力しか出力できないね』
妹「そのために、sayAttackDamageにあるPanchクラスを外に出してあげる必要があるんだ~」
姉『そうなると、どんな感じ?』
妹「ひとまずこんな感じかな~」
class Panch: def __init__(self, weight, grip, speed): self.weight = weight self.grip = grip self.speed = speed def calcAttackDamage(self): return self.weight * self.grip * self.speed class Person: def __init__(self, name, weapon): self.name = name self.weapon = weapon def sayProfile(self): return "わたしは" + self.name + "だよ~" def sayAttackDamage(self): return "わたしの攻撃力は" + str(self.weapon.calcAttackDamage()) + "だよ~" if __name__ == "__main__": imouto = Person("妹", Panch(45, 32, 370)) print(imouto.sayProfile()) print(imouto.sayAttackDamage())
姉『Personインスタンスを作成時にweaponを要求して、そこにPanchを渡してるんだね』
妹「これなら日本刀クラスができたときに、同じようにweaponに渡せるからね~」
姉『おっけー!だいぶ理解した』
妹「うん!ちなみにこのテクニックは依存オブジェクトの注入って言うんだよ~」
依存を隔離する
姉『でもなー、こういうの覚えても、結局実践で使えなかったりするんだよねぇ』
妹「わかる~~~!!!既存のコードいじるの難しいよね~」
姉『でしょでしょ。引数いじると相当修正必要になったりするし』
妹「でも放置してよくなくなることなんてないから、リファクタリングはしたいよねぇ」
姉『言うは井上やすしぃ』
妹「上のような変更はできなくても、インスタンス作成を分離したりとかからちょっとずつ!」
姉『段階を追うような修正があるの?』
妹「そう!例えば上の例で、引数をいじれなくても、こんな感じに!」
class Panch: def __init__(self, weight, grip, speed): self.weight = weight self.grip = grip self.speed = speed def calcAttackDamage(self): return self.weight * self.grip * self.speed class Person: def __init__(self, name): self.name = name #追加 @property def weapon(self): return Panch(45, 32, 370) def sayProfile(self): return "わたしは" + self.name + "だよ~" def sayAttackDamage(self): return "わたしの攻撃力は" + str(self.weapon.calcAttackDamage()) + "だよ~" if __name__ == "__main__": imouto = Person("妹") print(imouto.sayProfile()) print(imouto.sayAttackDamage())
妹「こんな感じでクラス内で分離すれば、sayAttackDamegeが綺麗になる!」
姉『でも結局Personの中でPanchを定義しちゃってるね』
妹「うん!そのうえで、さっきのに比べて依存が明らかで修正しやすいでしょ?」
姉『うーん、なるほど?』
妹「小さいプログラムだから実感しづらいけど、大きくなればわかるんだから!」
姉『はーい』
引数の順番への依存を取り除く
妹「次はこれを解決していくよー」
- 「Panch」の引数に「weight」「grip」「speed」が必要であることを「Person」は知っている
- 「Panch」の引数が「weight」「grip」「speed」の順であることを「Person」は知っている
姉『これもう仕方なくない?』
妹「ううん。まず順番のほうなんだけど、ハッシュ(連想配列)を使えば簡単に回避できるの」
姉『ハッシュポテト!好き!』
妹「Pythonで書くとこんな感じかなぁ」
姉『ガン無視!』
class Person: def __init__(self, args): self.name = args["name"] self.weight = args["weight"] self.grip = args["grip"] self.speed = args["speed"] if __name__ == "__main__": args = { "name": "妹", "speed": 370, "weight": 48, "grip": 32 } imouto = Person(args)
妹「だいぶ簡略化したけど、こうすれば引数の順番気にしなくていいでしょ?」
姉『おーすごい』
妹「さらに引数のデフォルト値を設定することで、引数の数も知らなくてよくなる!」
class Person: def __init__(self, args): self.name = args.get("name", "デフォルトさん") self.weight = args.get("weight", 100) self.grip = args.get("grip", 100) self.speed = args.get("speed", 100) if __name__ == "__main__": args = { "name": "妹", "speed": 370 } imouto = Person(args) print(imouto.name) print(imouto.weight) print(imouto.grip) print(imouto.speed)
妹 100 100 370
妹「こんな感じ!」
姉『なるほどねー!すごい!』
妹「えへへ~」
姉『でもいちいち毎回こんなの書くの面倒だなぁ』
妹「そだね~。費用対効果考えて使うべきところで使うべきだよ~!」
依存方向の管理
姉『づがでだぁ』
妹「あともうちょっとだから頑張って!」
姉『もう、ほんと、簡潔にお願い……』
妹「おっけ~!依存方向って概念について簡単にまとめるね」
姉『ありがたやぁ』
妹「今までの例だと、PersonがPanchを呼んでたよね。人はパンチをする!って感じで」
姉『うんうん』
妹「でもこの方向って逆にもできるの。パンチをするのは人だ!って感じに」
姉『ふんふん?』
妹「じゃあ実際に実装するとき、どっちで書けばいいと思う?」
姉『最初の、人はパンチをする!じゃない?』
妹「それが正解かどうかを測る基準として、以下の概念があるの」
- 変更の起きやすさ:変更がより起きにくいものに依存するべき
- 具象と抽象:より抽象化されたものに依存するべき
- 大量に依存されたクラスを避ける:言葉通り
妹「ザクっというとこんなこんな感じ」
姉『やったー簡潔!』
妹「変更が起きやすいのに依存の数が多いクラスがあったら破滅の元だよ!」
姉『はーい!』
3章まとめ
妹「今日はこんなところかな~。どう?おねえちゃん」
姉『責任を小さく作ったら、使うときも結合度を小さくするように作る!』
妹「完璧~~~!天才~~~!」
姉『えへへー、じゃあもうそろそろ実践?』
妹「まだ今進捗1/3くらいかな~」
姉『お姉ちゃん寝るねぇ』
妹「待ってよ~!一緒にがんばろ~!」
姉『妹ちゃんのやる気がなかったらとっくに折れてるなぁ』
妹「えへへ~絶対今後の糧になるからファイトだよ~!」
姉『はーい』
オブジェクト指向を学ぶ姉妹 2章
単一責任のクラスを設計する
妹「オブジェクト指向で重要なものはメッセージってことを主張してたね~」
姉『どうしてもクラスに目がいくけど、肝はそこじゃないんだねぇ』
妹「最初の肝は、シンプルであれと主張すること、だったね!」
姉『具体的には?』
妹「いますぐに求められる動作を行ない、あとにも簡単に変更できるようにモデル化すること!」
姉『言うは秋元康くん』
妹「それをできるようにテクニックを学んでいくんだよ~」
TRUE
姉『設計とは、アプリケーションの可変性を保つために技巧を凝らすことだって』
妹「完璧を目指すための行為ではないって書いてあるね~」
姉『言い方変えてるだけでほんと同じこと何度も言ってるね』
妹「コードは次の性質が伴うべきって~」
- 見通しが良い(Transparent)
- 変更するコードにおいても、そのコードに依存する別の場所のコードも変更がもたらす影響が明白である
- 合理的(Reasonable)
- どんな変更であっても、かかるコストは変更がもたらす利益にふさわしい
- 利用性が高い(Usable)
- 新しい環境、予期していなかった環境でも再利用できる
- 模範的(Exemplary)
- コードに変更を加える人が、上記の品質を自然と保つようなコードになっている
妹「見通しが良く、合理的で、利用性が高く、模範的。略してTRUE」
姉『急にアイドルっぽい命名!』
妹「絶対に男性4人組グループ!」
単一責任かを見極める
姉『どお?妹子ちゃん。写経できた?』
妹「うん~Dartで書けたよ!お姉ちゃんは書けた?」
姉『Pythonで書いたよ!』
妹「クラスが単一責任かどうかを見極めるコツが2つ書いてあったね~」
姉『1つめはクラスを擬人化して問いただすだったね!超得意!』
妹「擬人化とは書いてないけど実質同じ意味だね~」
姉『妹クラスに、妹ちゃんの好きなもの教えて!で通じるのはいいけど、』
姉『お姉ちゃんの好きなもの教えて!が通じるのは何かおかしいってことだねぇ』
妹「それだと私がおねえちゃんの好物まで管理しちゃってるもんね~」
姉『私はウェルカムだよ!』
妹「2つめは1文でクラスを説明してみることだったね~」
姉『上の例だと、妹クラスは妹を管理する?』
妹「うーん、それだと広すぎない?複数責任負ってそう」
姉『妹クラスは妹の好きなものを管理する!』
妹「だとするとクラス名と内容が一致してないね~」
姉『妹の好きなものクラス……?』
妹「その場合まず好きなものクラスを作って、妹クラスが継承するのかな~」
姉『なるほどなー!こうやって設計を見直していくんだねぇ』
妹「こういった責任の度合のことを、凝縮度って言うんだって~」
アクセサメソッド
姉『アクセサメソッドって初めて聞いた』
妹「GetterとかSetterって聞くと、あ~あれね~ってなるね」
姉『おまじないとしか思ってなかったー。結局どんな意味あるの?』
妹「メソッドで包むことで、どこからでもアクセスできるデータじゃなくなるみたい」
姉『それって不便になるってこと?』
妹「勝手に変更されたり変な使い方される恐れがなくなるってことだよ~!」
姉『まだピンとこないなぁ』
妹「あと1ヵ所で振る舞いを定義するから、大きな変更があっても吸収しやすいの」
姉『わかりづらいいい!』
妹「鬼データを無惨様メソッドで包むことで、無惨様をいじればすべての鬼が修正されるの」
姉『わかりやすい!!!』
妹「rubyだとattr_readerを使うことで簡単にラッパーメソッドが作れるから、必ず使おうだって~」
姉『じゃあPythonでもやったほうがいいのかなー。修正してくる!』
妹「それがね~どーもPythonでは推奨されたやりかたじゃないみたいなの。」
姉『えぇぇぇ』
妹「Pythonでは言語仕様上、完全に隠匿することができないとかなんとか。」
姉『Dartは?』
妹「Dartも不必要なgetter/setterを作らないんだってー。ここらへん理由も調べとくね」
姉『言語によって方針がだいぶちがうんだねぇ』
妹「それが面白いところだよね~」
姉『最強の言語が天下統一果たすのを願うばかりだよぅ』
~続く~
オブジェクト指向を学ぶ姉妹 1章
はじめに
姉『最初は何から勉強してくー?』
妹「オブジェクト指向がいい!!!」
姉『おーちなみになんで?』
妹「んとね~、最近いろんな参考書買って読み始めてるんだけど」
姉『うんうん』
妹「当たり前にクラスとか出てくるの」
姉『出てくるねー』
妹「わかるわかる~って自分に嘘つきながら読んでると泣きそうになる」
姉『もはや知らないって言うの勇気いるもんねー』
妹「これ知らないと他の参考書読めないと思うから、先に勉強したいな~って」
姉『おけおけ、どうやって勉強するかんじー?』
妹「まずは参考書を写経してこ~~~!!!」
姉『おっけー!』
参考書・開発環境について
妹「まず参考書と開発環境を整理するね~」
参考書
OS
- Windows10
使用言語
姉『Dartって何???』
妹「そのうち私たちが習熟する必要のある言語だね~」
姉『この参考書Ruby使ってるけど、最初は背伸びせずにRubyがよくないかなー』
妹「うん、だからRubyで写経したあとにDartで写経するよ!!!」
姉『(はじめハードル上げまくって挫折するタイプだなぁ)』
オブジェクト指向について
妹「さてここで問題です」
姉『デデン!!』
妹「オブジェクト指向設計を一言で表すと???」
姉『かっこいい!』
妹「1点」
姉『1点はくれるんだねー』
妹「かっこいいもん」
姉『じゃあ妹子ちゃん、オブジェクト指向設計を一言で表すと?』
妹「依存関係を管理する設計手法……かなぁ」
姉『それっぽい!』
妹「えへへ~!本に書いてあった!」
姉『じゃあ私も読んでくねぇ』
1章 オブジェクト指向設計
姉『第1章まで読みおわったから、ここまでの感想言ってこっか』
Solid原則
妹「出てきたね~SOLID原則」
姉『メタルギア原則とも言うよね』
妹「言わない」
姉『SOLID原則ってなんだっけ』
妹「えっとね~」
- 単一責任(Single Responsibility)
- オープン・クローズド(Open-Closed)
- リスコフの置換(Liskov Substitution)
- インターフェース分離(Interface Segregation)
- 依存性逆転(Dependency Inversion)
妹「の頭文字を取った原則のことだね!」
姉『リスコフさんがインターフェースを分離して』
姉『オープン・クローズドするチカンにより単一責任を負ったけど』
姉『被害者がリスコフさんなしでは生きられない依存性逆転がおきた話かなぁ』
妹「とんだテクニシャンだねリスコフさん」
姉『意味はこの本を通して教えてくれるみたいだから何点取れるか楽しみー』
妹「0点以外の可能性を信じるお姉ちゃんの胆力~~~!」
GoF デザインパターン
妹「この本では解説されないけど、23パターンあるらしいね~」
姉『なにその絶妙な擬人化したくなる数』
妹「強力だけど、間違った問題に適用しがちだから要注意だって~」
姉『pixiv デザインパターン』
妹「オブジェクト指向覚えたら一通り知っておきたいね!」
姉『2件ーーー!同志ーーー!』
アジャイルソフトウェア開発宣言
妹「オブジェクト指向設計はあくまで、変更を用意にするための設計手法なんだね~」
姉『クラス使えばオブジェクト指向プログラミングってわけじゃなさそうだねぇ』
妹「で、繰り返しのフィードバッグが不可欠だからアジャイル開発と相性いいみたい」
姉『アジャイル開発の方法かー。知らないといけないこと沢山だねぇ』
妹「ひとまずはアジャイルソフトウェア開発宣言の12原則を読みこんでおこ~」
姉『pixiv アジャイルソフトウェア開発宣言』
妹「12原則の中二感に抗えなかったか~」
姉『0件ーーー!!!ねらい目ーーー!!!』
オブジェクト指向設計について
妹「繰り返し主張されていることが、適切な設計こそ大事ってことかな~」
姉『簡易な成果物に柔軟性もたせすぎて意味ないもんねぇ』
手続き型プログラミングとオブジェクト指向プログラミングとの比較
姉『手続き型言語は型を自分で作れなくて、オブジェクト指向言語は型を作れる!』
妹「正確には違うみたい!オブジェクト指向言語では型って概念がないの!」
姉『えっ、でもint型とかstring型とかあるくない?』
妹「全部オブジェクトなの!それらはintオブジェクトだしstringオブジェクト!」
姉『混乱するー!型からオブジェクトって名前が変わっただけ?』
妹「オブジェクトは全部編集可能だから、intオブジェクトも定義から変えれるの」
姉『int宣言してるのに文字しか扱えなくすることも可能ってこと?』
妹「そうそう」
姉『へへっintちゃん……俺色に染めてやるよ!』
妹「string君が雄々しい」
その他覚えておきたい言葉
- BDUF(Big Design Up Front):
- 開発前の大規模な詳細設計(文脈で意味は変わりそう)
まとめ
妹「だいぶ脱線したけど、1章はこんな感じかな~」
姉『薄い本が厚くなる内容だったね』
妹「正直結構取りこぼしてるね~」
姉『へーきへーき、1.5のまとめがこれ以上なくまとめてくれてるから!』
妹「私たちの存在意義!」
動き出す姉妹
はじめに
妹「おね~ちゃ~ん!!!」
姉『どったの妹子ちゃん』
妹「私たちやばいかもしんない!!!」
姉『ほうれん草好きだもんねー』
妹「それはポパイ」
姉『何がやばいのー?』
妹「技術力が低すぎるの~~~!!!」
姉『そーなのー?でもお仕事で困ってないよー?』
妹「現場の技術水準自体が低すぎるの!!!」
姉『うーん。ガンダムで例えてもらっていい?』
妹「逆シャアの時代にザクⅡ作り続けてる感じ」
姉『やばっ!!!転職してくる!!!』
妹「今のままじゃどこも拾ってくれないよ……」
姉『どうしたらいい!?!?』
妹「一緒に技術力磨いていこ~!」
現状整理
姉『といってもまず何したらいいかなぁ?』
妹「まずはねー今の私たちの状況を整理してみない?」
姉『そうしよっかー。思いつくだけ挙げてみるね』
姉『っていう女子高生姉妹だね☆』
妹「ぴちぴちのJKだね☆」
姉『ちなみに妹子ちゃんはどのあたりに危機感を抱いているの?』
問題点
IE 8.0
妹「主要ブラウザがIE 8.0なの辛すぎる~~~!!!」
姉『でもChoromeに移行を始めてるみたいだよ?』
妹「私たちがChorome用に開発するのだいぶ先だもん!!!」
姉『それもそうだねー。IE 8.0だと何が悪いんだっけ?』
妹「CSS3とHTML5が使えないの!!!」
姉『あー確かにネットで出てくる情報ほとんど使えないねー』
妹「それにJavaScriptもES6どころかES5にすら対応してない!!!」
姉『var宣言の撲滅以前の問題だね~』
妹「JavaScriptのフレームワークとかもほぼ使えないし……」
姉『結局、過去の資材を参考に書いてくしかないのは辛いよねー』
バージョン管理なし
妹「Gitも使ってな~~~い!!!」
姉『直でファイルを更新してるもんねー』
妹「修正した箇所にコメントで履歴を残すの嫌~~~!!!」
姉『同じ資材を修正する案件2つできなかったりねー』
妹「試しに一部でGit導入しようとしたけど、直で触られて壊れて諦めたり」
姉『皆に教えて一斉に切り替えられればいいけど、気力いるもんねー』
技術力が低い
妹「そもそもエンジニアの向上心がなさすぎるの~~~!!!」
姉『でもそれ私たちにも言えちゃうよねー』
妹「そうなの~~~!!!ちょっと前までこの環境が普通だと思ってたもん!」
姉『ASPファイル内にHTMLもJavaScriptもVBScriptも全部書いてたりねー』
妹「一回勉強会出てみて、自分たちの状況の劣悪さを知っちゃった……」
姉『知らなければそのまま幸せに働けてたのにねー』
妹「そんな怖いこと言わないで!!!」
これからのこと
姉『話聞いてて、だいぶ実感沸いてきたよー』
妹「それならよかった~~~」
姉『色々勉強しなきゃなーって思ったけど、何から手をつけようかなー。』
妹「まずは汎用的に使える基礎知識を身につけよ!」
妹「ひとまず上の基礎知識を身につけたいなって!」
姉『買ったはいいけど途中までしか読めてない本たちだね』
妹「9月末までに一通りこなせるようにがんばろ~~~!!!」
姉『がんばろーーー!』
まとめ
を9月末までに身につける!がんばろーーー!