最近、プロダクトを作って納品して終わりではなく、同じプロダクトを継続して開発していくことが多いと思います。
私もその一人です。
SIerとして開発していたときと比較して、継続して開発するようになってから意識するようになったことがいくつかあるのでメモがてら記事として公開しておこうと思います。
※記事は私の経験を基に記載しています。私がSIerだったのは執筆時点で10年弱前なのでSIer側の状況も変わっていると思います。
SIer時代の開発との関わり方
SIer時代は1つの開発プロジェクトのジョインして開発してリリース、また別のプロジェクトへ参加するという感じで様々なプロジェクトを渡り歩いていました。
プロジェクトごとに利用言語やライブラリ、インフラは決まっていることが多く、ジョインしたプロジェクトに必要なスキルをジョイン時にキャッチアップするスタイルでした。
自分でライブラリやインフラを選定することはほぼなかったので、幅広い技術をキャッチアップするのではなくプロジェクトに必要な技術をピンポイントでキャッチアップするスタイルでした。
また、成果物はお客様に納品するものであり、バグなどをすべて潰し、仕様通りに動作する物に作り上げるということが重要でした。
継続開発するようになってからの関わり方
継続開発するようになってからは、以前のようにリリースして終わりのような明確な区切りはなく、ずっと同じプロダクトを開発していくことになります。
同じプロダクトを継続的に稼働させるためには、機能開発だけしているだけではダメで、使っている言語やライブラリ、インフラなどを定期的にアップデートしていく必要があります。
アップデートを怠ると、セキュリティーアップデートされない脆弱性を含んだライブラリを使い続けることになったり、便利な新機能が使えず開発工数が増える/もしくは実現ができなかったり、エンジニアの開発体験が低下してしまい離職や採用に苦戦するなど様々な問題が発生します。
また、成果物は自社プロダクトであり、バグを潰し品質を上げることも必要ですが、あえて検知しているバグを許容するなど、継続稼働させていく中でバグとの付き合い方が変わりました。
プログラミング言語、フレームワークやライブラリのバージョン情報
SIer時代はプロジェクト開始時のバージョンからアップデートすることはほぼなかったのですが、継続開発をしている場合、バージョンアップは避けて通ることはできません。
私が業務で使っているプログラミング言語のRubyやフレームワークのRailsも1年に1回ほどメジャーバージョンがアップデートされます。
バージョンアップしなくても使い続けることはできるのですが、古いバージョンはセキュリティーアップデートがされないためアプリケーションが脆弱になったり、便利な新しい機能が使えず開発効率が落ちることがあります。
このようにバージョンアップは避けて通れないので、自分の主担当のプログラム言語や主要ライブラリのバージョン情報はキャッチアップするようにしています。
プロダクトコードとテストコードはセット
SIer時代からjunitなど自動テストの仕組みはあったのですが、業務で使うことはほとんど使うことはありませんでした。
開発物は手動テストを一通りして、テストが終わった部分には基本的に触らないので、自動テストの恩恵がほとんどなかったためです。
継続開発していく場合、既存コードに手を入れることが多く、コードを触らなかったとしてライブラリ等のバージョンアップで既存コードの再テストが必要になります。
そのときに、自動テストの有無で開発効率が大幅に変わります。
自動テストについて語ると長くなるので、興味がある方は以前に書いた別記事を参照してください。
新しい技術に対する探究心
利用しているプログラミング言語やフレームワークのバージョン情報をキャッチアップしようということは書きましたが、それだけではなく関連技術のキャッチアップもするようにしています。
関連技術もキャッチアップする理由は、利用している技術が別のものにリプレイスされる場合があるためです。
例えば、Javascriptを使う際、一昔前であればJQueryを使うことが主流でしたが、今はReactやVueを使うことが多く、今から新規開発するプロダクトでJQueryを入れることはほぼないと思います。
ただ、このような判断は利用しているJQueryだけをキャッチアップしていて周辺技術であるReactやVueをキャッチアップでしていなければできません。
インフラもSIer時代はApacheやTomcatを使っていましたが、今でもその構成でシステム開発する人はほぼいないと思います。
このように技術は日々進化しており、利用している技術がいつの日かリプレイスされる可能性があります。
そのため、利用している技術だけではなく関連技術もキャッチアップするようになりました。
過去の開発の深堀りはしない
継続開発していると既存コードを見てなぜこの実装になっているのか不明な箇所が出てくることがあります。
こういう場合、SIer時代は議事録や仕様書などを掘り起こしてその仕様になった証拠を発掘します。
誰の責任でこの実装になったのか明らかにするためです。
継続開発している場合、このような調査は時間が無駄になるだけでなく、理由がわかったとしてもほとんど意味がないことが多いです。
継続的に開発している場合、そのプロダクトは稼働中だと思うので現在のコードが正と考えるのがベストです。
そして、不明な挙動をしている箇所は、過去の仕様を掘り起こすのではなく現時点でどういう仕様がベストかを話しあって前に進めるようにするようになりました。
たまにしか発生しないバグの扱い
システムにはバグはつきものです。
SIer時代は検知したバグは必ず直して納品する必要があったのですが、継続開発しているプロダクトでは違います。
月に1回など低頻度でしか踏まれない、かつセキュリティリスク等がないバグの場合は修正にかかる工数を見積もり工数次第では後回しにするという判断もありえます。
ほとんどのユーザーが踏まないバグを直しても99%の利用者には恩恵がありません。それよりもっと有意義に開発工数を使ったほうが良いと考えるようになりました。
ただ、これを言うと優先度の低いバグは直されることがない事になってしまいますが、サクッと治せる程度のバグだったらなにかのついでに直しちゃいましょう。
継続開発している場合、基本は機能開発で工数を取られてしまい、明示的に優先度の低いバグを直したり、リファクタリングするような工数を取ることは難しいので、優先度の低いバグをスキマ時間にサクッと修正したり、なにかのついでにリファクタリングができるスキルも継続開発する上で重要だと思います。
(こういう考え方を「ボーイスカウトルール」と言います。気になる方はググってみてください。)
本番にない/またはレアなパターンの考慮
システムが取りうるデータパターンはすべて想定しておくべきではありますが、本番データに存在しないパターンやレアなパターンは場合によっては無視しても良いと思います。
例えばデータの移行ツールを作る場合、システムが取りうるすべてのパターンを実装するのではなく、実際に本番データに存在しているパターンのみ網羅すれば十分です。
あと、よくあるのがデプロイの瞬間に利用者に特定の操作をされたらエラーが発生する場合です。
簡単に避けられるなら対応しておくべきだとは思いますが、例えばその特定の行動をされる確率がほぼない場合や画面リロードなどで回避できる場合は工数をかけてまで対応する必要はないと考えるようになりました。
データ不整合について
データ不整合はプログラムやデータベースの制約等で発生しないように実装すると思いますが、長期に渡って運用しているとどこかで不整合なデータが混入することがあります。
例えば、プログラムのバグであったり、Webシステムの場合は同時アクセスやリトライ等で不整合データが登録されてしまうことがあります。
このような場合、SIer時代はすべての穴を塞ぐことだけを考えていましたが、継続開発するようになってからは、不整合データが発生したときに検知したり、補正できる仕組みも考えるようになりました。
ただ、補正する仕組みを作った場合でも、不整合データだ発生するということはどこかに穴があるのは間違いないので原因を探して潰すことは必要です。