コンピュータやソフトウェアのあれこれ@道民(&元道民)
Archive for 12月, 2011
達人プログラマー読書会@札幌-2011.11.28 に参加しました
12月 5th
11月28日(月)に行われた、達人プログラマー読書会@札幌に参加しました。
テストの話やプロジェクトの話など、今も大切だとされていることが10年前に書かれていたことに驚きました。
34. テストしやすいコード
- テストによりコンポーネントの信頼性を高めることができる
- コードの実装を開始する前にテストを作成することでインターフェースのテストをしている
- テストは手近なところになければ使われない
- テストは繰り返し実行されなければいけない
- テストは技術というよりも文化
この短い章の中に、ユニットテスト・テストの自動化・CI・TDDなどの重要性がすべて書かれていました。
これらのことが重要である、とこの頃から言われていることにまず驚きました。すごい本だ。
「場当たり的にデバッグでテストを済ませない」であるとか「プロジェクトにテスト文化を植え付ける」であるとか、今、まだできていないことがたくさんあります。
テストの書き方にもまだまだ悩みます。
「テストは文化」とは、まさにそうだなと思います。
今のプロジェクトにはテスト文化を広めてくれる指導者がいます。おかげでさぼらずにテストを書く、テストから書くという習慣(思考の変化)ができてきました。
これからも精進したいと思います。
35. 邪悪な魔法使い(ウィザード)
新人〜2,3年目の自分に読ませたかった章。
何となくソースコードが書けるようになってきた頃に陥りがちなこと、それは
「フレームワークが何となく使えてればコードが書けている気になる」です。
でも、それだと自分が何を書いているか(どんなバグを埋め込んでいるか)ちっともわかってないのですよね。
- 作り出されたコードの意味が本当に理解できていなければ、自分自身をだましていることになる
- 生成されたコードが理解できないようなウィザードを使うということは、自身のアプリケーションのコントロールを放棄することに等しい
昨今は開発を加速化するため、便利にするために作られた素晴らしいフレームワークやウィザード形式のコード生成ツールなどがたくさんあります。
それらのコードをすべて理解しなければ使うな、ということではなく、
- 何が起こっているか(少なくてもどんなソースがどこにできているか)を理解しておくこと
- いざとなったらきちんとソースを解析できること
- 自分がそのソースコードに手を加える際に適当になんとなくコードを書かないこと
これらを意識しておくだけでも「自動生成コードに振り回されない」プログラマになれると思います。
36. 要求の落とし穴
ここから第7章「プロジェクトを始める前に」に入ります。
お客様の要求を捉える、掘り起こすという、ちょうどアジャイルサムライ読書会でも行っているテーマでした。
どちらも同じことを言っていました。
- 要求が表面上に現れていることはほとんどない
- 最終的な目標はお客様のビジネス上の問題を解決すること
- 要求の掘り起こしは、ユーザーとの親密な関係を築いていく始まりの時
- 要求とは設計ではなくニーズそのもののこと
一つニュアンスがアジャイルサムライ(アジャイル開発)と異なるなと感じたところは
「お客さんは何もわかっていないから開発者がすべてのお客様のニーズをうまいこと引き出す必要がある」
という立場が達人プログラマの方が強めに書かれているなというところでした。
アジャイルサムライでは「お客様がプロジェクトチームの一員となる」ことの重要性が説かれています。
「ユーザーと親密にならなければよいものは作れない」という考え、目指すところは同じですが、アプローチの方法が若干違うなぁと思いました。
名前大事
この章の後半に書かれている「プロジェクト用語集」は本当に大切で、しかし、往々にしてプロジェクト途中で空中分解してしまうもの、です。
プロジェクトの終わりの方には全然更新されてない「(参照してはいけない)用語集」がサーバーに残っていたり・・・。
wikiを使うのも一つの方法かもしれないし、SVN管理することで自分のアクセスしやすい場所においておくこともできるのかな、と思いました。
そして、なにより、開発者間、開発者とユーザー間で「名前大事」という感覚そのものを共有することが大切なのだな、と感じています。
みんなに知らせる
wikiの重要性。2年前だったら言っていなかったと思うこの言葉。「wiki大事。」
使ってみなければわからないとはまさにこのことだよなー、とこの1年ちょっとで実感しております。
だいぶ、本の終わりが見えてきました。
最後まで頑張ります。
[TDD] TDDを学ぶべき10の理由 #TddAdventJp
12月 5th
[perl][hachiojipm][machidapm]Hachioji.pm in Machida に行ってきました。
12月 4th
飲んで騒いで楽しかったです。以上!
人数多かったので使わずに済ませましたが、スライドは用意してたんでリンク貼っときます。緩募は本当に募集してます(笑。
普段あまり見かけないような方と会えて楽しかったです。幹事の @ytnobody さんと運営の @uzulla さん、どうもありがとうございました!
(12/4 追記: 緩募した甲斐がありました(笑)→手元のPODを簡単・綺麗に見るひとつの方法)
[レポート]今日は 第5回 スタートHaskell の日です
12月 3rd
生憎の雨ですが、大森ベルポートのニフティさんに来てます。途中退室の予定ですが、居る間に聞いた内容をメモ。
第10章:クラスとインスタンスの宣言 / @ruicc さん
- OOからHaskellの型・型クラスの理解をする
- 型クラスと型インスタンスがOOのクラスである
- 型クラスはメソッド、型はフィールド
- 状態 = 大いなるバグの母
- 直積構造(タプルみたいなもの)、直和構造(orみたいなもの)、再帰構造(リスト、木)
- data IntOrSome a = MkInt Int | MkA a
- IntOrSome : 型構成子
- MkInt, Mka : 値構成子
- type IntOrStr = IntOrSome String
- 値構成子がない
- 直積構造 → OOではフィールド、Haskellでは型構成子
- 直和 → OOはステートパターンや状態をフラグで管理。Haskellでは | で直接表現
- 再帰構造 → OOは自分の型をフィールドにもつ(コンポジット、ビジターパターン)。Haskell は書き下せる
- OOだと意図が
- Haskellではprivateがない
- Haskellは状態がないので、そもそも要らない
- パフォーマンスを改善する場合にはモジュール単位で隠す(where, module単位)
- OOでは列挙型が欲しくなる → 直和型がないから
- 継承とはなんだったのか
- メソッドの、型の継承+実装の継承
- 型の継承 → フィールド非依存
- 実装の継承 → フィールド依存
- Haskellの型クラス同士の継承はフィールド非依存、型はフィールド依存
- OOはオーバーライドが複数回行われる。Haskellは一回
- 型クラスは多重継承が可能
- C++やPythonでも多重継承できる?
- うまくはできない。マクロやコードジェネレータで差が出る
- 型クラスはScala のTraitと似てる → Scalarzにそんなのがある
- class Eq a where (==), (/=) :: a -> a -> Bool
- 型クラスEq, 型パラメータa、 型クラスのメソッド==, /=
- instance Eq MyType where x == y = ...
- 型クラス Eq、インスタンスにする型 MyType
- クラスの継承 class (Eq a) => Ord a where ...
- => で指定
- 特定のクラスのインスタンス化が簡単になるようにしている
- deriving (Eq, Ord, Show, Read, ...)
- 仕組みはwww.haskell.org でググって
- 型クラスは2種類
- instance Eq (Maybe Int)
- instance Monad Maybe → 型パラメータを1つとる型の宣言
- モナドなどに関するヒント
- Monad, Functor, Applicative
- 要素はコンテナと中身しかない。
- 質疑応答
- 「Q. 10.6のevalとexecって?」
- 「A. 評価順を明確にするために2つの関数に分けている」
- 「Q. 型クラスはOOのクラスでなく、総称関数のインタフェースってことでいい? 実装を与えるのがインスタンス?」
- 「A. はい。クラスって名前は忘れた方がいい。同じ名前の関数を持つグループ。」
- 「Q. C#とJavaのインタフェースと同じ?」
- 「A. はい。ただしHaskellはデフォルト実装を持てる」
- Haskellでは、既存のインスタンスを自分のクラスにしたりできる
切符番号選び(11章) / @dekosuke さん
- Twitterの数字遊び
- 4つの数字が出て、10にする
- 演算が決まってない。ルールがあいまいで面白い
- 切符番号選び
- 四則演算のみ、好きな数字を選んでよい、0になっては駄目
- data Op = Add | Sub | Mul | Div → 四則演算
- valid, apply : 正当かどうか。演算結果はどうか
- 分けなくてもMaybe でいいんじゃん?
- data Expr = Val Int | App Op Expr Expr
- eval : 式を評価。List型だが実質Maybe
- subs : 冪集合を求める
- perms : 並び替え
- choices : perms + subs
- solution : Exprが答えになっているか調べる (未使用)
- solutions : 全ての回答を探す
- combine : 二つの演算に四則演算を総当たりで適用したリスト
- ops : 四則演算のリスト
- exprs : 与えた数値を使った式を全て返す
- このプログラムは遅い(4分かかる)
- validでない式を落としてない (最後にevalしているため)
- 高速化
- type Result = (Expr, Int)
- combine' : Result へ四則演算を総当たりする
- results : 数値を使った式を全て作って評価
- solutions' : 速い版。数十秒。
- さらに工夫
- 可換な演算は片方でよい、x×1 は自明なので略す
- 組み合わせ爆発の時は、小さな工夫も指数的に効く
モナモナ言わないモナド入門 / @kazu_yamamoto さん
- モナドは名前が悪い。抽象的だからわかりにくい
- 物理学の統一理論、大統一理論と同じ
- 状態系(IO, State)、失敗系(List, Maybe)の共通点を見つけ、コンテナを見つける
- ParserとIOの共通点を探す
- データ定義が似ている
- ラップする関数がある
- 合成する関数がある
- 抽象化オタクなら抽象化したくなるはず → class Stateful m where swrap, sbind
- 抽象化すると何が嬉しい? → do記法
- Stateful の中身は関数なので、走らせなければならない
- 関数を取り出し、runParserやrunIOする
- IOは公開されてないため、runIOできない → ランタイムが実行
- Maybe → 複数回関数適用すると、場合分けが指数関数的に増える
- 失敗をいい感じで合成する関数 → mbind
- data List a = Nil | Cons a (List a)
- MaybeとListを抽象化 → class Failable m where fwrap, fbind
- searchによって抽象化の恩恵を受ける例
- Philip Wadler → StatefulとFailableを統一、Programmable
- Failable でもdo が使える
- 力の弱いものを使う(再帰よりmap)
- コンテナの力の階層 強) >>= 、<*>、<$> (弱
- チューリング完全
- 構造化定理 : 逐次、分岐、反復
- Mappable (<$> (fmap))
- <*> (ap)
- 心眼で<$>と<*>を消すと、(+) (Just 1) (Just 2) に見える
- <*>はdoを書き換えられるので、逐次。再帰しているので反復もできる
-->>= が分岐を表現する
- なぜモナド? → モナドはチューリング完全だから
- モナドの嬉しさ
- do、差し替え可能な文脈、差し替え可能な実装、モナド変換子
- IOモナドとかMaybeモナドとか、「モナド」とつけて呼ぶのは犯罪
- IOもMaybeも特別なものでない
- 糖衣構文 do がモナドを特殊にしている
- 本来はFunctor → Applicative → Monad だけど、そうなってない
- 内包表記は、doの別表記
- scalar のfor も同じ
- 1990年にでき、1997年にモナド内包表記へ一般化されたが、1999年に戻された
- モナド内包表記 のエラーメッセージがわかりにくかった(糖衣構文のため)
- また戻った(SQLも表現できるっぽい)
- 表記
- Parser はApplicative
- IO はdo
- Maybe は>>=
- List は内包表記
- 質疑応答
- Q. Functor, Applicative, Monad の力の強弱
- A. FunctorとApplicativeは似たようなもの。Monadは分岐
- Q. typeは合うけど、monadが限定されるということはあるのか
- A. forM_ とかはIO を期待している
- Applicativeの良さ
- data KV = KV String Int でパーサを書くとき、持ち上げができる
ここで退室しました。関係者のみなさん、おつかれさまでした!