RandomThoughts

RandomThoughts

【書籍】CodeComplete

Contents:
  1. Code Complete遍歴
  2. 暇つぶしに読み直そう企画
    1. 1章、Welcome to Software Construction 2025-04-07 (月)
    2. 2章、メタファーの話 2025-04-09 (水)
    3. 3章、Upstream Prerequisite(上流工程) 2025-04-10 (木)
    4. 3章続き 2025-04-20 (日)
  3. 終わらない開発とtoCの、より適切なメタファーを考える
    1. 学校とか行政組織とかを作り上げる
    2. 化学実験の試験官の中の物質の調査
    3. 戦争
    4. スーパーで食材の買い物
    5. 雪だるまを作る
  4. レイヤーとDDDと上流工程
  5. 自然言語の要求や仕様を顧客が読むという事はあまり無い理由を考える

技術的なメモ

amazon: CodeComplete

日本語版でいいと思うが英語版がセールだったので英語版を買った。 コードコンストラクションについてこれほど良く書かれている本も無いよなぁ、とは思うけれど、ハンドブックであるがゆえにフォーマル寄りに偏っている傾向はあると思う。

Code Complete遍歴

初版を何度も読み直したコードコンプリートだが、さすがに手元に残っていない(何回か買った記憶があるが…)。 二版は無職の頃二回くらい図書館で読んだが、手元に無かった。

その後セールの時にKindleの英語版を買ってたまに参照している。

暇つぶしに読み直そう企画

カクヨムでできの悪いテンプレを大量に読んだ結果、これは不毛すぎるのではないか、という気分になり、代わりにCode Completeを読む事にする。 今回は目的は別段無いので、一日一章ずつ読んでいこうかな、と思っている。

1章、Welcome to Software Construction 2025-04-07 (月)

ソフトウェアコンストラクションとはなんぞや(コーディングとかデバッグとかその辺の奴のこと)、それ以外にはどんなものがあるのか(要求分析とか保守とか)、なんでソフトウェアコンストラクションが重要と思うか(他のプロセスは省略されるがコンストラクションは必ず実行される、プロジェクトに占める割合が多い)といった話がされている。

現代的な視点だとフォーマルなやり方があってインフォーマルなプロジェクトがある、 という見方はちょっと偏りを感じる部分もある。 例えば一発当てるのが目的のサービス開発みたいなので、 何をやるのかと開発はそんなに分かれた話では無いし、それはインフォーマルというのともまた違ったもののように思う。

ただフォーマルな手法をハンドブックとしてまとめる事には多くのプロジェクトにとって意義があるとは思うが。

2章、メタファーの話 2025-04-09 (水)

コードコンプリートを読んでいて、最初はぴんと来ない事もだいたいはあとでその重要性を理解し、使いこなせるようになった時にその良く書かれた内容に感動する、 という事を繰り返していたが、いまだにその体験が無いのがこの2章のメタファーの話。

ソフトウェア開発というのを理解するのにメタファーは重要で、いろんなメタファーを紹介して、建築のメタファーと工具箱のメタファーが良いという話をしていて、そのソフトウェア開発との対比からいろいろな示唆を引き出している。 また、メタファーはアルゴリズム的では無くヒューリスティック的だ、という話もしている。

Further Readingには、以下の2つが上げられていた。

前者を読んでみようかな。bookwalkerには無かった。

3章、Upstream Prerequisite(上流工程) 2025-04-10 (木)

上流工程がなぜあった方がいいのか、とか、そのメリットを説く。

とりあえずBoss-Readiness Testまで読んだ。続きは明日かな。

今読むとやはりプロジェクトの形態が決めたものを作るという前提がある気がする。 何かのソフトウェアを10年くらい作り続ける、みたいな形態にそぐわない気がするんだが、その辺はどうなのかなぁ。

何を作るのを決めてからcodingをする、みたいな話は、 何を作るのかを決めるためにcodingを使う道を閉ざしてしまっている気がする。 何を作るべきか、コードを書いていると分かる事も結構あるからなぁ。

ただ誤ったものを上手く作っても仕方がないのは間違いない。 そして正しいものを作るべきでもある。 ただどうやったら正しいものを知る事が出来るかは良くわからないよなぁ。 客がいて要望を聞く、みたいなのは、toCではあんまりいい手段では無いよな。

フェーズを分けて調査するのではなく、もっと日常的にその問題について調査をしたり考えたり調べたりしているべきだよな。 なんかリリースしたものの反応とかを見てちょとずつ自分の中に何かが溜まっていって、それでどうすべき、 みたいなのが決まっていくのがtoC的だと思う。

3章続き 2025-04-20 (日)

ちょっと間が空いたがちょくちょく読んではいた。3章は進みが悪いな。 今はProblem DefinitionやRequirementsのあたりを読んでいる。 Capers とJonesはたびたび参照されていて、昔読んだな〜と少し懐かしくなるとともに、 やはり顧客が居てその顧客のためにソフトウェアを作る、というモデルは古いのでは無いかな、という気はする。

今読むのであれば、やはりそうした前提が少し古い事を考慮に入れた上で、 そうした前提のもとではどういう事が分かっているかを情報として仕入れる、という姿勢がいい気はする。 この辺の基本は、適用出来ないケースが増えたとはいえ、やはり知っていた方がいい。

終わらない開発とtoCの、より適切なメタファーを考える

昨今の開発は、終わらないでずっと続くものも多い。サービス開発とかはずっと続いていく。

どうもその現状に対し、3章の話は建築に引きずられていてあまり適切になっていない気がしたので、より適切なメタファーを考えてみる。

学校とか行政組織とかを作り上げる

もっと組織を作るのに近いと思うんだよな。軍隊とか行政組織とか村とか学校とか円満な家庭とか。 良い学校を作る、というのは、何かをやって終わり、というものじゃない。 学校の中で何か問題が起きたらそれを改善していくような仕組みとか、 そうしたものを自動的になおしていくような文化を育むとか、 そういう事がソフトウェア開発と近い気がする。

何かおかしな機能を作ってしまっているとか、ユーザーの熱が逃げていっているとか、 なんかそういう間違ったシグナルみたいなのを捉えては道を修正していくような、不断のアクティビティが現代的なソフトウェア開発の主流…というと言い過ぎかもしれないがそれなりの範囲を占めるようになったものであり、自分が最近やっている仕事でもある。

上手く行ってない時というのは、何かおかしな事を実装したりしていながら、やっている人たちはそれがおかしいと思っていない、とか、 そういう状態になったりする。 そういうのが現代的な失敗で、それは要求が間違っているというのは表面的で、なんか開発組織の歪みのようなものが本質のように思う。 そういうのは、コーディングの前のフェーズで分析して解決出来る類の事では無いんじゃないか。 もっと開発組織を直さないといけない気がする。

ソフトウェア開発は、ゴールが無い、営みのようなものがメタファーとしては良いよな。

化学実験の試験官の中の物質の調査

特定の客のために作る想定よりも、toC的な、もっと対象が良くわからないもやもやした何かに対してつくる前提で考え直した方が、自分の現状には合う気がする。 そうしないとtoCでもユーザーアンケートだとか市場調査だとかで特定の客につくるのと同じようなものになるかのような、 間違った印象を持ちやすくなる気がする。

市場というのは、もっと化学の実験みたいな感じで、試験管の中の良くわからないものにいろいろと混ぜたり熱したりして反応を見て、 そこから中を理解していくような何かだと思う。 そしてこの反応を見ていく何かというのがソフトウェアの変更とかだと思うんだよな。 どういう変更をしてどういう反応があるかをあらかじめ知るというのは本末転倒で、 変更の反応を見て理解を深めていく必要がある。

その時にどういう変更をすべきか?というのは、要求を分析する、というのとはちょっと違うと思うんだよな。 どういう反応を期待するか、どういう事を調べたいのか、 その負の影響はどのくらいに抑えたいのか、 というような事は注意深く決めたい気もするが、 そうはいっても試してみないと結局わからないのだから限界もあるし、 プランニングよりいろいろ試して知識を蓄積していく方がいい場合もある。

戦争

競合があって勝者がすべてを取り敗者は何も得られない、というような開発では、スポーツや戦争などの争いごとの方が近いかもしれない。 スポーツはルールがあってやれる事が決まっているという点で、ソフトウェア開発的では無い気がする。 戦争の方が近いようにも思う。

ただ戦争は戦争の事を良く知らないのでメタファーとしてどうなんだ?という気もする。ソフトウェア開発の方がむしろ良く知っているからなぁ。

勝つ事が目的であって決めたものを作るのが目的でない事は良くあると思う。 建築とかのメタファーではそういう重要なケースが漏れてしまっていると思う。

スーパーで食材の買い物

現代的なソフトウェア開発には、例えば既存のオープンソースのプロダクトに参加する、みたいなものがある。 これは参加している期間何かを開発し続けるが、 別に期日までに何かを完成して納品したりする訳では無い。 その期間参加している事が目的であって、目的が終わればそこから引き上げる、というたぐいの問題に思う。

こういうプロジェクトのメタファーとしては、終わるものでは無く注ぎ足していってずっと続くものが良い。

という事で、日々の食材の買い物とかはどうだろう? 今冷蔵庫には何かがある。そこに何かを足して料理を作る。 冷蔵庫の中は空っぽになる事はあまりなく、いつも少し予備は残るのが望ましい。 残ったものは別の用途に使いやすいのが良いが、何に使うかは良く分からない。

買い物に行くのは足りないものがあるからだろう。それは今あるものと次に作る料理のためである。 一方で何を作るかはまだ決めてないがとりあえず買っておきたい、というものもあるだろう。 冷蔵庫の中を、以下のような複数の性質を満たすような状態に持っていきたい。

  1. とりあえず次に作るつもりものものの材料を満たす
  2. まだ何を作るか決めていないが、いろいろなものに応用できるものを常備する
  3. いざという時にとりあえず食べられるような、すぐに食べられるものをある程度用意しておく

こうした冷蔵庫の状態というのは、継続的なものであって、 いろいろな食材とかを試して自分にあったものを選んだり、 飽きてきたら違うものにしたり、栄養的に食べたいものを追加したり、 と試行錯誤をしつつ育てていく何かという気がする。

これは継続的なソフトウェア開発に近い性質のものでは無いか。

雪だるまを作る

3章のイテレーティブな開発の話で少し違和感があるのは、 最終的に同じものを作る時にイテレーティブに作るかウォーターフォール的に作るか、という比較で話を組み立てている所。

現代的な大きなソフトウェアというのは、コードベースに対してちょっとの変更を継続的に加えていって大きくなっていくもので、 ゼロから大きななにかを作る、というのはあまり大規模プロジェクトの実態を捉えてない気がする。

個々の変更はそんなに大きくない(事がほとんど)。けれどコードベースは大きい。 こういう時に、上流工程の必要性などを考えるのは、この本のメタファーではうまく行かないんじゃないか。

大規模プロジェクトは、雪だるまの雪玉を作るのに似ている気がする。 雪玉は大きいが、一回回転させて増える量はそんなに大きくない。 これを繰り返して大きなものを作る。

雪玉の表層一つのために問題定義して要求を書いて仕様を書いて機能仕様を書いてテスト仕様を書いて実装をしてテストをして〜とやっていくのは、 明らかに過剰にフォーマルだと思う。

そもそもに作った雪玉が間違っていたら大惨事な訳だが、普通は上手くいったものを大きくしていくので、 最初に作るものをちゃんと定義するとかそういう話では無い気がする。

そして最初に上手く行くのをどう作るか、というのは、分析どうこうというよりは、誰も良く分かってないのでは無いか。 これはベンチャーとかが各自全く別の方法で挑んでいって、良さそうなのが出来たらみんな真似したり買収したりといった感じで始まる気がする。

典型的なプロジェクトというのは雪玉の表層何周か、というものなんだよな。 これは期間は短く3ヶ月〜半年くらいで終わる事が多い。 だからそれに必要な計画というのはそんなに多くはない。 雪だるまを作っている期間は長期なんだが、それは計画されて進んでいるものでは無いんだよな。

ある一定の大きさまでたどり着くのに何年掛かるか、みたいなのは皆興味は持っていない。 その雪だるまに少しなにかを足して自分たちの目的が達成出来ると思う人が目的分だけ雪玉を転がし、 それの総体として大きな雪玉が出来ていく。

レイヤーとDDDと上流工程

3章の上流工程を読んでいて思った事。

問題定義があって要求があって仕様があって機能仕様があって実装、みたいな世界観というのは、 いわゆるレイヤーアーキテクチャの上の方を自然言語にしよう、という考えに近い。

各レイヤーそれぞれに何らかの方法でのテストがあってそれで正しさを確認して、要求が正しければ仕様が正しい、仕様が正しければ機能仕様が正しい、機能仕様が正しければ実装が正しい、 という、「AならばB」を積み重ねてソフトウェアを作ろうという事だ。そして基本的にはより上流の方が生産性が高く、間違いの修正が容易である、という前提がある。

一方でFSharpなどのType First DevelopmentやDDDのユビキタス言語などでも、似たような話はある。 上流から下流、という向きはあまり強調されていないが、 ステークホルダーとプログラムとは違うなにかで対話をして詰めていく、 というのが有効であるという話である。

自然言語のRequirementsをちゃんと書いてメンテする、というのは、現代ではもはや少数派になったと思うし時代遅れに感じられるが、 一方でソフトウェアをレイヤーにして書く、というのは割と良く用いられるデザインであり、現代でも良く見る。 DSLを作ったりユビキタス言語を作ったりというのはRequirementsや仕様を自然言語で書くのとかなり近い思想ではある。

一方で、非機能要求だとかそういったものがちゃんとそれらで書かれる事は無い。 そういう点で自然言語でのそれらの概念を完全にコード化出来た訳では無い。 Gilbの本などで書かれているような、ちゃんとした機能仕様などを書くメリットは、本来はそれなりにある気もするけれど、 現代としてはロストテクノロジーだよな、とは思う。

CIにはパフォーマンスの監視がついてそれらがある程度盛り込まれてもいるか。 ただそういうのは先に要求が来るというよりは、出来たものを改善していく時に具体的に目標が決まっていくパターンの方が多い気がする。

かつてのプラクティスは、コード化出来るものは頑張って取り込まれ、コード化出来なかったものは捨てられた、という事にも思う。 ただ時代とともにだんだんとかつて捨てたものを拾ってきて取り込むようになってきている気もするので、 現在捨てられているものも近い将来には何らかの形でコード化されて取り込むトレンドが来るかもしれないな。

そういう点では現在捨てられているものを調べてみるのはやる価値があるかもしれない(今は自分はやる気は無いが)

自然言語の要求や仕様を顧客が読むという事はあまり無い理由を考える

最後にちゃんとした仕様などを書いて作業をしたのは、MS時代なのでもう15年以上前となる。 逆にここ15年行った仕事では、そういうものは一切無かった。

作り始める前にパワポで説明する、というのはある。それでプロジェクトを立ち上げたり予算を取ってきたり、というのはある。 けれど、文書で書かれた要求や仕様を顧客が見て同意して次に進んで〜、という事は無かった。

今の仕事で要求や仕様を書いても、まず間違いなく顧客は読まないし、プロジェクトの同僚も読まない。 一つ前の仕事を思い浮かべても、やはり読まない。

自分が最近やったのはだいたいは以下の2パターンだ。

  • 社内のなにかのチームの手伝い
  • toC

社内のなにかのチームの手伝いの場合、仕事を依頼する側もある程度はプログラマであるし、またそのコードをある程度は読める。 やりたい事を頼むのはそれまで開発を続けてきたコードベースになにかを追加したり、なにかを実験したり、といったもので、 それ自体はそこまで大規模なものでは無い(コードベース自体はそれなりの規模なものもあるが)。

そういう点で、顧客はむしろ自分よりコードベースを良く理解しているのだよな。自分が作る所は理解していなくても。 そして顧客はプログラマなんだよな。

考えてみるとこのパターンはかなり多い気がする。

顧客はたいてい忙しいのでやりたい事をアウトソースしたいので、なるべく顧客の時間を使わないのが重要なプライオリティで、 自然言語の要求とかを書く、というのは明らかにやる時間を掛けたくない。 それよりは私が作るものが失敗する方が良い気もする。 それは払っているお金からすると無駄かもしれないが、金で解決出来るなら良いという話にも思える。

自分は要求や仕様を文書で合意する代わりに、コードベースを読んで顧客の意図を推測し、それを簡単な打ち合わせですり合わせて作業をする。 顧客がやってほしい事を文書で書くのは顧客にとって望ましくない。 そして私が書いた自然言語の文書を読むのもやりたい事では無い。 なにか試してみたい事を試した結果とか、そのうちやりたいと思っていたが手がついていない事とかを、私が代わりにやって結果だけ知ったり成果物だけほしい。

顧客の時間を増やすのが目的で雇われているので、顧客の時間を消費するものを増やすのは望ましくないんだよなぁ。