システムエンジニア

システム開発のアンチパターン

More than 1 year has passed since last update.


はじめに

私も今月で35才になりプログラマーとしての定年を迎えました。

そこで、これまでの経験でこんな兆候があるとシステム開発がトラブルになるかもというポイントをまとめたいと思います。


前提

なお、私が経験してきたことは以下のようにSIer的な案件が多いです。

立場は、プログラマ、リーダ、PM、コンサル、育成様々です。

また、今はSIerに所属してはいませんが、近しいところにはいます。


  • 規模として10人程度をワンチームとして、場合によって複数チームで構成されるもの

  • 企業向けシステム

  • Java 中心


環境差異の軽視


 概要

色々な理由で開発環境と本番環境が違うケースがある

例えば、開発と本番で次のようなものが異なる。


  • OSが Windows - Linux

  • サーバが 一台 - 分散構成

  • DBが H2 - Oracle

  • ネットワークが、HTTP - HTTPS

  • Spring-bootを使っていて、 スタンドアローン - War

他にも、ミドルウェアのバージョンや設定が違うとか。


 問題

環境差異に基づく様々な不具合が出る。しかも、本番にリリースして初めて気づくことが多い。


  • OSによるパス区切りの違いや、ディレクトリ構成の違い

  • 特定のDBでしか使えない、データ型やSQLを使っている

  • SSL証明書の設定をしていない

  • ミドルウェアのバージョン固有のバグを踏む

  • Spring-boot で war にする場合、コンテキストルートがあることを失念する

などなど


対策

本番と違うけど、多分大丈夫という慢心を捨てる。


  • 環境差異をなくすのが最も良い。docker とか仮想環境とか使って。

  • 無くせない場合はぶっつけ本番は避け、環境差異を確認する作業を早期に行なう。

  • SpringやMavenのプロファイルなど、環境切り替えの仕組みを活用する。

  • DBなどミドルウェアのバージョン、設定は必ずそろえる。

最近、 Spring-boot を開発はスタンドアローンで、本番はWarにするケースが多々あるのだけど、

Spring-boot の github issue や、 stack overflow には、 特定の APサーバーで動かないという報告が結構あるので、注意が必要だ。


スタンダード無視


概要

世の中のフレームワークは、よくある問題に対処するための解決策を提供している。

その解決策を適用する際に、フレームワークが推奨する方法とは異なる方法や、

自力で解決する方法を採ったりすることがある。


問題

標準的な方法と異なるやり方をすることで、いろいろな問題が起きる。

特に、普通とは違うやり方をしているということを、ちゃんと明文化していないと、

後から入ったメンバーが、普通とは異なるやり方をしていることを知らず、

普通の方法で実装して、何か挙動が変わるといったようなことが起き得る。


Spring フレームワークの @Transactional アノテーションはこれを付与したメソッドについてトランザクション制御を行う優れた機能だ。

ただし、デフォルト設定ではロールバックを行うのは、非チェック例外だけであり、任意のチェック例外もロールバック対象とするには、以下のように属性を追加する必要がある。

@Transactional(rollbackFor={HogeException.class, RuntimeException.class})

特定の処理だけ、ロールバックする例外を変えたいのならそれでいい。

ただし、すべての処理で任意の例外をロールバック対象にしたい場合、上記のような属性付きのアノテーションを付与して回るのは結構辛い。

人によっては、属性を付けるのを忘れるだろうし、後でロールバック対象の例外を追加するといった仕様変更が発生した場合の修正コストも相当なものとなる。


 対策


  • フレームワークの流儀に沿った設計を心がけ、デフォルト、標準設定のままで上手く動くようにする

  • デフォルトを変える場合、どこか一箇所の修正だけで、その変更が適用できるようにして、影響を最小限にする


 例

上記の Spring トランザクションの場合、非チェック例外を常に使うのが望ましい。

すべての処理で、チェック例外を対象とするなら、以下の2つの方法を使う。

@Target({ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)
@Transactional(rollbackFor={HogeException.class,RuntimeException.class})
public @interface CustomTransactional {
}


工程のすっ飛ばし


概要

スケジュールが遅れ気味の時、予定されている工程を飛ばすことがある。

特に、ウォータフォールの場合、基本設計の内容で実装が達成できると判断して、内部設計を飛ばすことが多々ある。


問題

設計とは段階的に、 実装をするにあたって不確定な要素を見つけたり、発見できてないタスクを見つけることで、次の工程をスムーズに作業だと個人的に思っている。

手を動かしならが考える作業も並行で行うことになるため、手戻りやコードの重複が発生して、思ったより開発効率が出ない。

また、非機能要件や運用、CIといった、地味だが重要なタスクに気づかないといった問題も出る。


対策

そもそも遅延が出た際に、最初に検討することは、スコープの縮小やスケジュールの延長であり、どうにかして間にあわせることを最初に考えるのは悪手になる。

顧客とも遅延や想定外の事態に対して、QCDのうちどれを優先するかを合意しておくことが望ましく、良いこと悪いことをつまびらかに報告できる信頼耐性ができていると最上。


過剰なドキュメント


概要

SI は納品が伴うため、大量のドキュメントを書きがちだ。

特に、金融機関のような間違いを起こさないことを重視する現場では、フローチャートやソースコートど一対一に対応するようなドキュメントが求められることがある。


問題

純粋に、開発スピードが落ちる。

実装に近い内容を書いてあるドキュメントなどは、ソースを一行直すだけでも、ドキュメントに反映が必要だったりと、保守でも効率が落ちてしまう。


対策

ずっとこのプロセスでやってきたからと試行停止せず、本当に重要なドキュメント、保守すべきドキュメントについて、顧客と再検討してみる。

顧客もひょっとすると、ドキュメントが多すぎて困っているのかもしれない。

個人的な意見だが、詳細設計書と呼ばれるもの(外部の振る舞いと、実装との差異を埋めるもの) については、以下のような手段で大幅に簡略化するべきではないかと考えている。


  • 小さい範囲でプロトタイプを作って、その振り返りを実装方針をまとめたガイドとして展開する

  • 実装を決めるためのメモ程度の扱いとして、最初に作った後はメンテナンス対象としない

  • ユニットテストとテストコードのドキュメントで補完する

  • Wiki などのツールで代替する

要は実装の足がかりとなり、保守では実装を理解しやくする程度の内容であれば、問題ないだろうと思っている。


自動生成依存


概要

世の中には、エクセルや定義ファイルなどからソースコードを自動生成することで、開発効率を改善するという方法がある。


問題

自動生成が悪いわけではないが、自動生成を唯一の解決策として開発すると、

開発効率の低下や、コードの重複を招く。

過去の経験では、自動生成でコードの雛形を作成し、その雛形にコードを足していくという現場を見たことがある(そもそも、自動生成されたコードに手を入れること自体、優れた手段ではないのだが)。

そこで何を間違ったか知らないが、自動生成されたソース以外は作成してはならないというルールが制定された。

共通処理を記載する場所が無くなってしまったため、そこらじゅうにコピペが蔓延する結果となった。


対策

自動生成が適する場所でだけ、自動生成を使う。



社内フレームワーク


概要

(特にバッチに多いのだが) OSSではなく、秘伝のタレのような社内フレームワークを使って開発をすることがある。


問題

開発から5年以上経過している社内フレームワークは、大体の場合、開発者がいなくなってメンテされていなかったり、マニュアルやガイドなどが整備されていなかったりする。

また、設計に問題があり機能追加や改善が難しかったりすることも多い。

いまだに、Java6で動いていたりとかね。


対策

せっかく作った社内フレームワークだからもったいないかもしれないが、新規案件では、OSS で代替できないか検討する。

バッチ系のOSSは近年、 Spring Batch や Spring Integration, TALEND など充実している。


枯れた技術


概要

SI 業界は、どちらかといえば安定志向だ。

上の社内フレームワーク同様、前例があることが重視される。


問題

世の中の流れに取り残される。

下手をすると、顧客の情報システム部門の方が、クラウドやDevOpsなど、技術動向に敏感だったりする。

他に、技術が好きなエンジニアにとっては、モチベーションが下がるなどの問題がある。


対策

まず、所属している会社のマインドが技術志向ではなく、かつ自分が技術志向なら、異動するかとっとと去る。

また、上記とは別に、顧客がシステム部門に十分に投資をしていなくて、技術者を確保できず、安定したものを求めることがある。

その場合、システム部門の技術育成や導入のような施策を打って、顧客の技術レベルを向上できないか考えてみる。


ノーレビュー


概要

忙しいから、あの人は信頼できるから、面倒だから、、、

様々な理由で人の作った成果物をレビューしないことがある。


問題

これは過去の私の経験に基づくものだが、一度腕のあるメンバーの成果物について、この人なら大丈夫だろうとノーチェックで本番リリースをしたことがあります。

その結果、バグを含んだソースを本番にリリースしてしまいました。


対策

どんなに忙しかろうと、信頼できる相手であろうと、レビューは必須。

そして、自分が作ったものも第三者にレビューしてもらう。

開発プロセスにちゃんと組み込もう。


まとめ

最後に、SIやSE はどうなっていくべきか個人的な思いを書いておきます。

上でもちょっと触れましたが、顧客とどう関わっていくかが大事なんじゃないかと思っています。

従来型のロングスパンでのシステム開発を求める顧客も当然います。

一方で、システムの運用コストを下げるためや、情報戦略のために、技術刷新やスピードを求める顧客も増えたように思います。

どちらの顧客にも今までやってきた方法で対処しようとするとうまく行かないと思います。

顧客の実現したいことに寄り添うこと、意見を言うことが必要なんじゃないかと思います。

そのために、どうすればよいか、私は次のように考えます。


  • 必要十分なドキュメント

  • 小さく動くものを作る

  • 人海戦術に頼らないやり方

単純に言うと、無駄なことはしないようにしよう、アジャイル的な手法を取り入れよう、顧客にとって必要なことを重視しよう、そんな感じです。

ごめんなさい、十分な時間が取れなくなってしまって、整理できていません。

あとで見直すかもしれません。