全力で怠けたい

怠けるために全力を尽くしたいブログ。

Java で -server オプションを付けたら4割近くも速くなったメモ

Java で -server オプションを付けたら4割近くも速くなったときのメモ。

動機

ログファイル中の XML をパースして XPath で抜き出す調査用のツールを使っていたのですが、本番機 / ステージング機と開発機で実行速度に大きな差がありました。本番機・ステージング機・開発機はハードウェアのスペックからしてまったく違うとはいえ、同じログファイルに対して実行したときの TAT が2倍以上違うとかもザラにあり、少し調べてみました。

環境

  • 本番機・ステージング機: 64bit Windows
  • 開発機: 32bit Windows

開発機では Client VM が使われていた

開発機の OS が 32bit Windows のため、デフォルトで Client VM が使われていたのが原因でした。java コマンドに -server オプションを指定して Server VM で実行するようにしたところ、TAT が4割近くも短くなりました。ちょっとしたツールだしあまり変わらないだろうと思っていたのですが、全く変わるものなんですね。

大雑把な計測結果をメモしておきます。

# Client VM で実行
PS >1..10 | foreach { Measure-Command { java -client Hoge  }} | measure -Average TotalMilliseconds

Count    : 10
Average  : 32756.72687
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

# Server VM で実行
PS >1..10 | foreach { Measure-Command { java -server Hoge  }} | measure -Average TotalMilliseconds

Count    : 10
Average  : 24059.97238
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

ユースケースを元にキャッシュ化

Server VM を使うことで相当に速くなったのですが、使っていたツールの使われ方には以下のような偏りがあったので、

  • XML を抜き出すための XPath の大部分は毎回同じ
  • 毎回変わるのはごく一部だけ
  • 同じログファイルに対して「ごく一部」を変えながら何回も実行する

XML のパースと XPath での抜き出しは初回のみ行い、以後はそのキャッシュに対して「ごく一部」を適用するようにしてみました。

# 事前にパースしてキャッシュしておき、それを使うようにする
PS >1..10 | foreach { Measure-Command { java -client -Dcache=enable Hoge }} | measure -Average TotalMilliseconds

Count    : 10
Average  : 2667.87865
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

圧倒的に速いですね。桁が1つ減りました。ちなみに、キャッシュからの検索には PowerShell の Get-Content と Where-Object を使っているのですが、grep コマンドに置き換えたらミリ秒で終わるようになりました。本番機・ステージング機で grep コマンドが使えないのが残念ですが、Get-Content と Where-Object を使う版でも2, 3秒で終わるのでまあいいかな、というところです。

まとめ

  • ほとんどの場合、Server VM を使っておけば OK *1
  • 32bit Windows なくなってほしい

*1:GUI でも Server VM を使いたいことのほうが多そう

チームメンバーにリファクタリングを紹介する勉強会を開催した

チームメンバーにリファクタリングを紹介する勉強会を開催しました。

動機

  • ふりかえりで、最近コードがちょっとよくなってるよね、という話題がでた
  • 仕様変更やバグ修正のたびにコードが汚くなって困っている…という声もでた
  • コードをよくする方法があるならちょっとやってみたい、という声につながった
  • リファクタリングのさわりを紹介 + ハンズオンなんてどう?

ってことで、勉強会を開催することになりました。

勉強会の進め方

スライド中の様子

  • 負のスパイラルでは結構深刻な表情
  • コードが病むスピードのグラフでは「そうだよね〜 (真顔)」
  • マイケル・フェザーズのレガシーコード論が一番食いつきが強かった
  • ボーイスカウトルールでは「そうなんだよな〜」「そうだったらな〜」

ハンズオンの様子

  • ペアでリファクタリング体験
  • メソッド名の変更やメソッドの抽出といったごくシンプルなものを手順込みでいくつか
  • 同じくごくシンプルなものを手順なしで自分たちで考えてやってみる *1
  • ボーナスステージとして、実際のプロダクトコードをレベルダウンしたものも *2

まとめ

まだまだ立ち上がったばかりの活動ですが、少しずつ自分たちの手で触れていくのが大事だと思っています。
ふりかえりが出発点なので、まずは毎回のふりかえりで、今回のイテレーションでのリファクタリングを1〜3分くらいでフィードバックするようにしています。すでにイテレーションでのフィードバックがありましたが、ごくシンプルなものでもみんなの食いつきがとてもいいです。

本音

リファクタリングが特別でもなんでもない、チームにとって空気のようになるのが目標です (キリッ

*1:パターンは手順込みでやったものと同じ

*2:結果は言うまでもない

Excel 入出庫台帳の思い出と付き合い方

システムエンジニア Advent Calendar 2016 - Qiita 2日目の記事です。

SI 業界人なら構成管理の現場で一度くらいは遭遇したことがあるかもしれない Excel 入出庫台帳との思い出と付き合い方について書きます。

書くこと

  • Excel 入出庫台帳とは
  • 付き合いの歴史
  • オススメの付き合い方
  • まとめ

Excel 入出庫台帳とは

f:id:ebc_2in2crc:20161128234551j:plain
こういうやつです。
この Excel に、これから編集するファイルのパス・バージョン・編集種別 (追加・修正・削除) といった管理情報を記入します。それを申請書として構成管理担当者に提出すると、記入したとおりのパス・バージョンのファイルが送られてきます *1
これは「構成管理物を担当者に払い出す」ので「出庫 (申請書)」と呼ばれます。反対に、担当者が作成・修正したファイルを構成管理に戻す (入れる) ときは「入庫 (申請書)」と呼ばれます。しかし、入庫も出庫も単に「入出庫台帳」と呼ばれることも多いです。

Git しか使ったことがない人にはまったく意味不明だと思いますが、使っていた人もほとんどが「なんでこんなの使うんだ?」という代物です。
そんな Excel 入出庫台帳について、あるプロジェクトで付き合った思い出と付き合い方を書きます。

付き合い前 - 最初期

構成管理のためにバージョン管理システム (以下 VCS) を利用することが多いと思いますが、最初期は VCS を使っていませんでした。

どうやっていたかというと、共有ディレクトリに置かれたファイルを担当者が直接修正 + 日付ディレクトリで運用していました。また、共有ディレクトリのファイルを直接編集するのではなく、ローカルにコピーして編集したあとにディレクトリ全体を戻す、といったことも行われていました。


当然のように、いろいろな問題が頻発しました。

  • 修正したファイルが他の担当者に上書きされる
  • 削除したファイルが復活する


自分がジョインしたのはちょうどそんな頃でしたが、VCS を使わないのはあまりにも無謀です。そこで、すぐに VCS の導入を提案しました。

付き合い前 - 前夜

チームとしても「このままではまずい!」という危機感を持っていて、すぐに VCS を導入することになりました。自分は Git か Mercurial を推したのですが、最終的には標準ソフトウェアという理由で CVS が導入されました。なお、この時点ではまだ Excel 入出庫台帳による管理は行われていませんでした。

運用の実際

この頃から頻繁にステージング環境にデプロイするようになり、以下のような手順でデプロイしていました。


一直線に進むだけの開発においては CVS + ブランチなし運用でもなんとかやっていけていました。一応。

ふりかえって気が付いたこと

当時は Git や Mercurial ではなく CVS を採用する理由が分かりませんでした。しかし、

  • 自分以外のメンバーは Git, Mercurial の経験がなかった
  • 一方、CVS の経験はあった
  • デスマーチ一歩手前で学習コストが払いづらい
  • 不慣れな Git, Mercurial を使った場合の事故が怖い
  • 自分はジョインしたばかりだった = 実績がない = 信頼がない


これだけネガティブな環境的要因が揃っているなかで、実績も知名度もないメンバーの意見を積極的に採用するほうが難しいでしょう。
「信頼を得るのに弁舌でなく実績をもってすべき」とか言われても不思議ではないと思います。

付き合い初期 - すべて人力

プロジェクト全体で構成管理プロセスの品質向上が図られることになり、Excel 入出庫台帳 (以下、台帳) が導入されました。また、この頃からプロジェクトが完全にデスマーチ化しました。

運用の実際

台帳を導入したもののファイル自体は CVS で管理されているので、台帳が入出庫フローに直接組み込まれることはありませんでした。その代わり、ファイルを追加したり修正した場合はその実態に合うように台帳に記入し、デプロイの際には台帳の記録履歴からファイルを集めてビルド・デプロイすることになりました。

困ったこと

台帳を導入してすぐに問題が発生しました。問題は大小様々でしたが、一番大きな問題はコンパイルができない *2 ことでした。原因は様々ですが、大雑把にリストすると、

  • 台帳に記入されたパスが間違っていて update できない
  • 台帳に記入されたパスが間違っていて別のファイルが update された
  • 台帳に記入されたリビジョンが存在しない
  • 台帳の記入順に update するとリビジョンが巻き戻る。これが正しいのか?
  • 台帳はコミットごとに別ファイルとして作られる *3
  • そもそも台帳への記入漏れがあった


こういった原因のためにコンパイルできなかったり、コンパイルできても論理的な矛盾 (バグ) があるなどに悩まされました。「昔はブランチをマージする前に禊 (みそぎ) をしたものだ」なんて聞いたことがありますが、この頃はマージどころか単にビルドするだけで何時間もかかるのが当たり前で、通常業務への影響は到底無視できるものではありませんでした。

ビルドは持ち回りでやっていたのですが、1度でもやった人は2度とやりたがらず、自分も1度やってみてすぐに改善を決めました。

付き合い中期 - リファクタリング

台帳による管理を続ける理由はまったくありませんが、台帳は品質向上プロセスの一環として導入されたため、取りやめるためには政治的な壁が高く立ちはだかっていました。そこで、入出庫フローそのものは変更せず、作業の実体だけを変えることにしました。つまり、プロセスのリファクタリングです。

ビルド持ち回り2巡目からはほぼ自分1人がビルドしていたので、チームリーダーの合意だけもらってリファクタリングを進めました。

リファクタリングで変わったこと

  • ビルドにかかる時間が20分になった
  • 誰でもビルドをしてくれるようになった
  • 台帳に記入する時間を開発に充てられるようになった
  • 「台帳いらないよね」気運が高まった

やったこと

台帳への記入と台帳からファイルを集めるのを自動化しました。具体的には、

  • CVS クライアントを導入
  • commit のログから自動で台帳に記入するラップコマンドを作成 *4
  • 一連の台帳の記入内容からファイルを集めるスクリプトを自動生成
  • 記入内容をチェックして誤りや矛盾がある場合にはレポート生成 *5
  • 定間隔で記入内容をチェック


行った変更はすべて台帳に記入・台帳の記入内容からファイルを集めてビルド…という入出庫フローはそのままですが、作業の実体としてはまったく別物になりました。定間隔でのチェックは Windows のタスクスケジューラを使ったのですが、誤りを早期発見できるようになったおかげで無駄な調査時間を一掃することができました *6 *7

どうやったか

できるだけ段階的な自動化を心掛けました。というのは、

  • 単純に変化を嫌う人もいる
  • 変化よりは苦労のほうがマシとさえ言う人もいる
  • CLI しか用意しなかったが、CLI に苦手意識を持つ人もいる


こういったありがちなことを避けるためです。
また、自動化後の運用フローも1人ずつ段階的に導入してもらいました。というのは、

  • 一気にチーム全体にお願いすると "上意下達" と受け取る人もいる
  • 反発したり、言われたから仕方なくやる、になってしまいがち
  • 事実上、いきなり全員をフォローするのは無理ゲー
  • 相談という形で1人ずつお願いすると自分事と捉えてくれる
  • 先行して導入した人が後続する人のメンターになってくれる


目的は構成管理にかかる時間の最小化と余計な作業を減らすことで、自動化された手順を使ってもらうのは手段にすぎないので。

とはいっても、このあたりはプロジェクトや組織の文化次第でいくらでも変わるので、いけるなら一気に導入したと思います。

付き合い末期 - 別れ

自動化を導入してから数ヶ月後、家庭内別居状態だった台帳と別れるときがやってきました。

きっかけ

プロダクトが無事にリリースし、それと同時に複数バージョンのメンテナンスが必要になりました。台帳と家庭内別居したあたりから構成管理周りのことは最初に相談してもらえるようになっていたのですが、この時は「好きにやっていいよ」と言ってもらえたので好きにやることにしました。

やったこと

  • VCSCVS から Mercurial + TortoiseHg に移行 *8
  • Mercurial 社内勉強会開催
  • ブランチ戦略を策定
  • その他、構成管理にかかわるもろもろ
  • マネージャーに台帳不要論を納得してもらう
  • そして、台帳と完全に縁を切った


いろいろやりましたが、キモは台帳が不要であることをマネージャーに納得してもらうことでした。

マネージャーは台帳そのものが必須だと考えているわけではありません。マネージャーにとって台帳はあくまで手段でしかなく、目的は構成管理プロセスから生み出されるプロダクトの品質が担保されることです。しかし、「台帳という手段があるからこそ目的が達成される」「台帳という手段がなくなったら目的が達成できなくなる」とも考えています。

そこで、台帳が無くても新しい構成管理のやり方 (= 手段) で目的を達成できることを、チームリーダーと2人でマネージャーに説明しました。自分一人では納得してもらえないか、あるいは相当に時間がかかりそうでしたが、チームリーダーが粘り強く説得してくれたおかげでかなり早期に GO サインがでました。この一件にとどまりませんが、チームリーダーに対するマネージャーの信頼の高さに救われました。信頼は大事です。つくづく思います。

その後

台帳と別れたあとはユニットテストを充実させたり、CI を導入したり、DSL で機能テストを書けるようにしたり、と変化の速度はあがりましたが、台帳とは関係ない話なので以下略。

オススメの付き合い方

誰がなんといおうと付き合わない、間違いなくこれが最善策です。

それでも付き合わなければならなくなったとしたら、家庭内別居状態→離婚のコンボを狙う、これが次善策でしょうか。

実効性がないプロセスは政治的・文化的な理由から存在するのがほとんどなので、最初から拒否するのは難しいことも珍しくありません。そこで絶対に拒否!と頑張るのもいいのですが、非常に疲れますし最終的に受け入れざるを得なくなることも多いです。ある程度まで頑張っても駄目なら、悪化した状況、つまりリスクが発現するのを前提に考えてみるのも1つのやり方だと思います。

まとめ

ながくなってしまいましたが、Excel 入出庫台帳の思い出と付き合い方でした。
最後に、Excel 入出庫台帳に限らないのですが、プロジェクトのルールや文化を変えていくにあたって心がけていることを書きます。

  • 知名度がなければ実績で信頼を得る
  • 変化は少しずつ
  • 変化は自分から
  • 自分自身を変えるのも簡単ではない
  • 自分が他人を変えるのはほぼ不可能
  • しかし、他人が自身を変えることはできる
  • 仲間をつくる・増やす
  • メリットを体験してもらう
  • トップダウンボトムアップに絶対はない
  • 技術的正論が通らない (= リスク) ことは当たり前にある、を前提に考える
  • 建前を変えられないときは実体から変えていく
  • そのときがきたら建前も変える
  • 変化は手段であって目的ではない
  • しかし、変化がない≒リスクである


いろいろ書きましたが、変化を楽しみながら仕事ができる、そんなシステムエンジニアでいたいと思います。

*1:メールだったり共有ディレクトリだったり様々

*2:Java で開発していた

*3:台帳というより入庫申請書な使われ方

*4:ついでにタグも打つようにした

*5:手動での記入を続ける人もいたため

*6:Jenkins を使いたかったが以下略

*7:昔あった "テーブル定義書.xls からマクロで DDL を生成" みたいなノリで微妙ですが…

*8:ネット、特に Twitter で非常に非常に助けていただきました。Twitter 素晴らしい!

IntelliJ IDEA + Lombok + Gradle の環境構築メモ

IntelliJ IDEA で Lombok を使う環境を作り直した時のメモ。

やったこと

  • SDKMAN! のインストール
  • Gradle のインストール
  • build.gradle に依存関係を記述
  • Lombok Plugin のインストール
  • Annotation Processors の設定

SDKMAN! のインストール

homebrew で Gradle を管理していたのを SDKMAN! (旧 GVM) で管理するように変更。

公式サイト に書いてあるコマンドを打つだけで完了。

$ curl -s https://get.sdkman.io | bash

# 省略

$ source "$HOME/.sdkman/bin/sdkman-init.sh"

SDKMAN! をインストールすると .zshrc (or .bashrc) に SDKMAN! 用の設定が追加される。

#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
export SDKMAN_DIR="/Users/shrimp/.sdkman"
[[ -s "/Users/shrimp/.sdkman/bin/sdkman-init.sh" ]] && source "/Users/shrimp/.sdkman/bin/sdkman-init.sh"

Gradle のインストール

こちらも公式サイトに書いてあるコマンドを打つだけで完了。
途中で Gradle 3.2 をデフォルトにしてもいいか聞いてくるので、デフォルトにするなら y を入力する。

$ sdk install gradle 3.2

Downloading: gradle 3.2

In progress...

######################################################################## 100.0%

Installing: gradle 3.2
Done installing!

Do you want gradle 3.2 to be set as default? (Y/n): y

Setting gradle 3.2 as default.

build.gradle に依存関係を記述

build.gradle に以下を記述。

apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    compileOnly "org.projectlombok:lombok:1.16.10"
}

Lombok Plugin のインストール

f:id:ebc_2in2crc:20161119171335p:plain

Preferences - Plugins から「Lombok Plugin」をインストールする。

f:id:ebc_2in2crc:20161119164341p:plain

インストールを反映するために IntelliJ を再起動するか聞いてくるので「Restart」を選択して再起動する。

Annotation Processors の設定

f:id:ebc_2in2crc:20161119164327p:plain

Preferences - Build, Execution, Deployment - Compiler - Annotation Processors から「Enable annotation processing」にチェックする。

以上。

システム間接続のはまりパターン

中〜大規模開発のシステム間接続でハマったときのメモ。

連携方法は様々だが 徹底解説! ITアーキテクトとは何か?(4):システム間連携のアーキテクチャ、4つの基本パターンと正しい適用のポイント (1/2) - @IT で解説されているアプリケーション連携が多い。

LAN アナライザーを使えばすぐ分かりそうなものが大半だが、禁止されている現場が多いのかもしれない。

接続できません!どうなってるんですか!?

ステルス接続

こちらのログには出力なし。LAN アナライザーでもパケットを拾えない。

原因は…

  • 相手の設定が間違っていてテスト環境を向いていた
  • ネットワーク経路で止められていた (ルータ、プロキシーなど)
  • 相手のマシンがテスト環境のマシンだった

404 not found

URL が間違っている。

原因は相手の設定ミスなのだが「こちらはすぐに直せないのでそちらでなんとかしてください!」…ここでなんとかするのも仕事である。

応答がありません!

"接続できない" から一歩前進。

原因は…

  • こちらからはちゃんと応答しているのだが、受信した相手プロセス (スレッド) がなぜか死ぬ
  • 上記同様だが、相手プロセスが無限ループで無応答に見える

エラーが返ってくるんですが!どうなってるんですか!?

原因のほとんどは「エラーを返すのが正しい」パターン。

  • プロトコル違反: たいがいがアプリケーションプロトコル違反
  • プロトコル違反ではないが、HTTP ヘッダに "Connection: Close" を指定しておいて 同じ TCP 接続で再度 POST してくるなんていうのも
  • 相手の設定が間違っていてテスト環境を向いていた (これもよくある)

データが送られてこないんですが!

原因は…

  • こちらからはちゃんと送っているのだが、受信した相手プロセス (スレッド) がなぜか死ぬ
  • 上記同様だが、相手プロセスが無限ループで無応答に見える
  • 上記同様だが、相手の処理が遅すぎてタイムアウト

変わり種: そちらのデータを受信すると CPU 100% になるんですが!

ビジー無限ループ (送ったデータは正しかった)

学んだこと

システム開発ではすべてを疑え *1

*1:まず自分の書いたプログラムを疑うのは大前提

Mercurial 作業領域の状態をいい感じに表示する PowerShell プロンプト

C:\Users\shrimp [hg: default +]
PS>

# Mercurial リポジトリにいると "[hg: <ブランチ名>]" のように表示してくれる
# 作業領域にコミットしていない変更がある場合は ブランチ名の後ろに "+" も表示

こんな感じに表示してくれる。

function Prompt {
  $HgBranch = hg branch 2> $null
  if ($HgBranch -ne $null) {
    if ((hg st 2> $null | where { $_ -match '^[MAR!] ' } | measure).Count -gt 0) {
      $HgBranch = "$hgBranch +"
    }
    $HgBranch = "[hg: $hgBranch]"
  }

  Write-Host -NoNewLine -ForegroundColor DarkGray "$(pwd)"
  Write-Host -ForegroundColor Yellow " $HgBranch"
}

こんな感じの Prompt 関数を $env:userprofile の Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 に保存しておくと PowerShell の起動時に勝手に読み込んでくれるので楽。

プロンプトの表示タイミングでしか変更をチェックしないのがちょっと残念だけどまずまず便利に使ってる。

"形を作っただけでは機能しない。仕組みは作れるが、目的は共有されない" ソフトウェア開発の現場も同じ

縁あって福島第一原子力発電所の事故についての 政府事故調査報告書 を読んだ。

非常にボリュームがあるので流し読みしただけだが、最後の総括と提言には非常に考えさせられたのでメモ。

(1)あり得ることは起こる。あり得ないと思うことも起こる。
(2)見たくないものは見えない。見たいものが見える。
(3)可能な限りの想定と十分な準備をする。
(4)形を作っただけでは機能しない。仕組みは作れるが、目的は共有されない。
(5)全ては変わるのであり、変化に柔軟に対応する。
(6)危険の存在を認め、危険に正対して議論できる文化を作る。
(7)自分の目で見て自分の頭で考え、判断・行動することが重要であることを認識し、そのような能力を涵養することが重要である。

形を作っただけでは機能しない

特に考えさせられ・共感したのが "(4)形を作っただけでは機能しない。仕組みは作れるが、目的は共有されない。" だ。短いので全文を引用する。

(4)形を作っただけでは機能しない。仕組みは作れるが、目的は共有されない。
事業者も規制関係機関も地方自治体も、それぞれの組織が形式的には原発事故に対
応する仕組みを作っていた。しかし、いざ事故が起こるとその対応には不備が散見さ
れた。それは組織の構成員がその仕組みが何を目的とし、社会から何を預託されてい
るかについて十分自覚していなかったためと考えられる。各構成員が何をしなければ
いけないかを自分の問題として自覚している状態を作らなければ、仕組みを作っても
全体としては機能しない。目的が共有されないからである。緊急時のために構築され
SPEEDI のシステムが避難に活用されなかったのは正にこの例である。
構成員全員が目的を共有するには、それぞれが社会から何を預託され、自分が全体
の中でどこにいるのか、また自分の働きが全体にどのような影響を与えるかを常に考
えているような状態を作らなければならない。その状態を更に維持するためには教育
と訓練が必要である。社会がそれぞれの構成員に預託している事柄をきっちり自覚で
きるような社会運営をしなければならない。

特にこのあたり。

  1. 事故に対応する仕組みを作っていたが、実際の事故時には不備が散見された
  2. 自分の問題として自覚していなければ、仕組みを作っても機能しない
  3. 自分が全体の中でどこにいるのか、自分の働きが全体にどう影響するのか
  4. その状態を維持するためには教育と訓練が必要

これはソフトウェア開発や保守の現場で常に議論され、考えさせられることとまったく同じだ。人気のビルドツールを使ったからといってビルドが上手くいくとは限らないし、最新の言語を使ったからといってシステムの質が向上するとも限らない。もっと大きな枠で見ても、ウォーターフォールで開発したからといってプロジェクトが失敗するとは限らないし、アジャイルで開発したからといってプロジェクトが成功するとも限らない。なぜなら、ツールやプラクティスといったものは箱モノではないからだ。だから、導入しただけでその価値を得られることなどそうそうない *1

まとめ

使えば使うほど・習熟すればするほど "お得になる"、それがツールやプラクティスだと思う。もちろん、ここでの習熟には使うべきではないところの見極めなども含まれるのはいうまでもない *2

むろん、原子力発電所で過酷事故が発生したときのような影響範囲の巨大さはそうそうあるものではないと思う。よって、前述の提言が自分の関わるシステムやプロジェクトにそのまま適用できるものではない。しかし、こういったことを常に意識し・目指す姿勢を持つ / 持たないとでは、出来あがるプロセスや組織、そしてシステムもまるで違うものになる。ソフトウェア開発に何年も携わってきたが、あながち外れてはいないんじゃないだろうか。

*1:個人的にはうま味という言葉がしっくりくる

*2:たかだか300行のプログラムに GOF デザインパターンを10個も適用したらと考えたらゾッとする