開発チームにアーキテクトがいないなと感じてしまうような、残念なコードスメルの例

まったく個人的なモチベーションの問題から、前回の最終更新から2年以上が経過してしまい、多くの読者のみなさんにはご心配をおかけいたしました。「プログラミングに関して調べたことや日々感じたことをメモとして残していきたいと思います。」というもともとの原点に立ち返って、あまり気負わずに、また今後も時々更新していけたらと思います。今までこのブログの主なテーマとして、JavaEEやSpringといったような、いわゆる業務開発で使われるような技術を中心としてきたわけですが、最近Springを使ったJavaの開発に(アーキテクトではなく)プログラマーとしてちょっと参加する機会があったので、その時気づいたこと、感じたことを書いてみたいと思います。

さて、皆さんはアーキテクチャやアーキテクトという言葉に対してはどのようなものをイメージするでしょうか。システムのセキュリティを確保するための方式であったり、大量のデータを短時間に処理する並列化の仕組みであったり、また、効率的な業務フローの構築だったり、ソフトウェアアーキテクチャという言葉はコンテキストによって実に様々な対象を意味します。実際には、ソフトウェアアーキテクトといってもさまざまな仕事があり、また、それぞれの分野において膨大な知識が必要なため、最近ではお医者さんのように専門の得意分野に特化せざるを得ないということもあるかもしれません。基本的には、アーキテクトはプロジェクトの成功を左右するような基本的な設計方針、技術の選択といったことに関わってきます。

ここでは特に、クラスやパッケージ、設定ファイルの分割といった開発作業に深くかかわってくる、プログラミングの基本指針のことを単にアーキテクチャと呼ぶことにします。自分の経験からも、このプログラミングに関わるアーキテクチャプログラマーの開発生産性や、後々のコードの再利用性、保守性といった点に深くかかわってくる開発の最重要ポイントの一つであり、他のアーキテクチャ指針とともにプロジェクト成功のためには軽視できないものであると考えています。この意味において有効なアーキテクチャを構築するにあたっては、アーキテクトがアプリケーション開発チームのメンバーとして仕事をするか、少なくとも、深く関与するということが大切だと思います。アーキテクト自身もアプリケーション開発者のコードを少なくともレビューできる体制になっているべきだし、「現場のプログラマーの気持ちがわかる」状態が望ましいと思います。さらに、こういったプログラミングアーキテクチャは事前にあらかじめ決められるものではなく、繰り返しのリファクタリングを通して、繰り返し洗練していくというアジャイルなプロセスが必須であると思います。以前から私が「下流アーキテクト」という言葉を何回か使ってきましたが、少なくとも有効なプログラミングモデルを構築するにあたって、アーキテクトは重役椅子に座ってパワーポイントの資料を編集しているだけではなくて、実際に開発チームを率いるプログラマーでもあるべきなのです。(アーキテクトもプログラミングするべきか? - 達人プログラマーを目指して

残念ながら、多くのプロジェクトにおいては、開発チームの中にこうしたアーキテクトがいないのでないかと感じることがあります。実際に、そういった事実は実際にソースコードを読んでいるといくつかの特徴から明らかになります。ここでは、アーキテクト不在を感じるソースコードの不吉な臭い(スメル)の例について、いくつか書いてみたいと思います。

間違った過剰なコンポーネント(プロジェクト)分割

初心者のソフトウェアアーキテクトでも、最初に考えるであろうことは、何とかして全体のコードを分割しなくてはならないということでしょう。モノリシック(一枚岩)なアーキテクチャがダメという考えがあるためか、とにかく、コードをいくつのコンポーネントに分割したくなります。全体のソースコードが多くのコンポーネントに分割されていれば、それだけでいい仕事をした気分になってしまうというところもあるかもしれません。*1
しかしながら、コンポーネントの分割には一定のコストが伴うということを忘れていはいけません。単にチェックアウトしてIDEの中で扱わなくてはいけないプロジェクトが多ければそれだけ面倒が増えますし、全体的なビルド時間も分割が増えるにしたがって急速に長くなる傾向があるため、CIの効率的な実行に支障が出ます。XP的な要件を満たすもっともシンプルな設計を目指すのであれば、どうして分割が必要なのかというメリットを考慮したうえで、分割は必要最低限にするべきだと思います。適切なコンポーネントの分割は簡単そうでいて、実は非常に難しいところがあると思いますし、実際、要件に合った最適な分割は何回かのイテレーションを経てようやく到達できるということも珍しくありません。一方、チームにアーキテクトが不在だと、以下のような形式的な分割の基準をあらかじめルールとして設定してしまい、結果として開発生産性を大きく下げるということになりがちです。

  • 画面ごとに分割する
  • 機能ごとに分割する
  • インターフェース、アノテーション、クラス、設定といったソースの種類ごとに分割する*2

こうした形式的な基準に従って分割した場合、一つの開発チームに割り当てられたプロジェクトの数が何百個になることさえあります。実際問題として、プロジェクトの数以上に問題なのは、こうした形式的な分割方法によって得られるのは多くの場合、密結合で凝集性の低いアーキテクチャであるということです。要するに、一見きれいにコンポーネントが分割されているようにみえるが、実際は関連した機能があちこちに分散し、実質はモノリシックなシステムと変わらない、結局は何も分割したことになってはいないという状態です。例として、Springのbean定義をxmlで記述しているとして*3xmlのbean定義ファイルと実際のbeanの実装クラスを別々のプロジェクトに分割して管理するというルールを考えてみてください。当然beanの定義と実際のクラスは密接に依存し合っているので、通常は同時に更新する必要がありますし、別々のプロジェクトとしてビルドすることで常に不整合が発生することを避けられません。プログラマーの気持ちがわかっているアーキテクトであれば、最初からこんなルールにはしないし、むしろアノテーションを使ったりJavaソースを使ってbeanの設定とクラス定義を近くに配置するということを考えると思いますが、そうでないと、設定ファイルは別々のプロジェクトで管理するものという常識で考えてしまいます。

私としてはeclipseプロジェクトのようなビルドの単位となるコンポーネントの分割は最低限にすることをお勧めします。もちろん、分割するメリットとして、

  • 別々にビルド・デプロイできる(SOA的にコンポーネントごとに別々のチームで運用する場合など)*4
  • 依存関係を強制できる(データ層からプレゼン層のクラスを間違って参照できないなど)
  • ビューなど頻繁に変更される領域とドメインロジックなど安定した領域を分ける

といったようなことがありますが、比較的小規模なプロジェクトであれば、

くらいの分割からスタートするので十分なのではないかと思いますし、むしろ最初から過剰に分割された構造で進めるより、実際上ははるかに生産性が高いと思います。

フレームワークによって強制されたパラレル継承

これは、ずっと以前に侵略的なフレームワーク - 達人プログラマーを目指してで書いたことの繰り返しになりますが、フレームワークの規約によって一つの機能ごとに様々なクラスや設定を作成しなくてはならないルールになっている場合がよくあります。たとえば、

  • MusicTrackDao
  • MusicTrackModel
  • MusicTrackService
  • MusicTrackView
  • MusicTrackViewModel
  • musicTrack.jsp
  • JSPタグ
  • 個々のbean定義
  • 個々の単体テストクラス

といったように、同じ名前で始まる大量のソースが存在していれば、パラレル継承のスメルを発しているといって間違いありません。*5

なお、関連してこのようなケースでは、レイヤーごとに値の入れ物として別々のクラスを定義することが強制されている場合も多いのですが、実際に多くの場合

musicTrackViewModel.setTitle(musicTrackModel.getTitle());
musicTrackViewModel.setTrackData(musicTrackModel.getTrackData());
...

のように、記述するコードの大半が単なる値の転記となることもあります。
これも、実際にプロジェクトにアーキテクトが参加していれば、そんなナンセンスな設計ルールにはしないはずなのですが、事前にアプリケーション開発チームとは別の標準フレームワークチームがルールを決めた場合など、このアンチパターンによく出会います。コンポーネント分割の場合と同様にたくさんのクラスを作成させることで、メンテナンス可能なアーキテクチャを作っているんだという気分になるという人もいるかもしれませんが、実際のところは、これも密結合・低凝集なアーキテクチャの原因となり、生産性を大きく低下させる元となります。大量の無駄なクラスを作成しなくてはならないために、初期の開発に時間がかかるという点に加えて、さらなる問題は「変更の分散」といったコードスメルの原因となることにありますね。つまり、後々のメンテナンスであちこちのファイルを同時に編集しなくてはならないということです。

もちろん、本当に継承が適切ならば継承を使えばよいのですが、JUnitやSpringMVCの昔のバージョンと今の最新バージョンを比較してみるとわかるように、最近のフレームワークでは共通のベースクラスを避ける傾向があると思います。*6

共通コードのプルアップがされていない

何らかのMVCフレームワークでアプリケーションを作っているとして、以下のようなコードがあったとします。いったい、何が問題なのでしょうか。

/**
 * 共通ベースコントローラー
 */
public abstract class AbstractController {
    protected abstract void execute(RequestContext context);
...
}

/**
 * 返品ポリシーのリンクを描画するためのコントローラー
 */
public class ReturnPolicyController extends AbstractController {

    public static final String RETURN_POLICY_MODEL_ID;

    @Inject
    private ModelRegistory modelRegistry;

    protected void execute(RequestContext context) {
        ReturnPolcyViewModel viewModel = modelRegistory.findModel(ReturnPolcyViewModel.class,  RETURN_POLICY_MODEL_ID);
        if (viewModel == null) {
           throw new InvalidConfigrationException("No model found for " + RETURN_POLICY_MODEL_ID);
        }
 
        viewModel.setURL(URLConverter.convertURL(context, model.getURL()));
        .....           
 
        context.setViewModel(viewModel); 
    }
}

/**
 * 音楽のトラック情報を描画するためのコントローラー
 */
public class MusicTracksController extends AbstractController {

    public static final String MUSIC_TRACKS_MODEL_ID;

    @Inject
    private ModelRegistory modelRegistry;

    @Inject
    private MusicTracksDataSource musicTracksDataSource;

    protected void execute(RequestContext context) {
        MusicTracksViewModel viewModel = modelRegistory.findModel(MusicTrakcsViewModel.class,  MUSIC_TRACKS_MODEL_ID);
        if (viewModel == null) {
           throw new InvalidConfigrationException("No model found for " + MUSIC_TRACKS_MODEL_ID);
        }
 
        .....           

        context.setViewModel(viewModel); 
    }
}

...似たようなサブクラスが何百と存在

普通の感覚であれば、各サブクラスのコードの類似性に気づくと思います。共通のロジックを親クラスに移動(プルアップ)するなどして、重複を減らすべきでしょう。しかし、ここではイメージなので実際のロジックを省略していますが、実際に各画面ごとのロジックが記述されている場合、この類似性に気づかずに大量の似たようなクラスを作成してしまうことがあります。こうしたコードの類似性は実際にいくつかのサブクラスを作成してみないと気づかないことが多く、フレームワークチームから与えられたベースクラスは多くの場合重複コードの削減のためにあまり役立ちません。アーキテクトが開発にかかわっているのであれば、こうした重複を発見する都度リファクタリングによって取り除く努力をすべきだと思います。

手続き型のコード

これはこのブログでも何度か取り上げてきたことですが、Javaなどのオブジェクト指向の言語を使っているにも関わらず、ほとんど活用できていないというケースが結構あると思います。実際、そういったプロジェクトで作成されたコードをみると、

  • データとgetter、setterだけのクラス
  • すべてstaticメソッドからなるXXXUtilクラス*7、あるいは巨大なサービスクラス
  • ポリモーフィズム多態性)が使えておらず、Enumや型によって似たようなswitch文の構造が繰り返し現れる

といったような手続き型の言語で設計したのと大差のない構造になってしまっています。これは、要件やチームのスキルによっては必ずしもアンチパターンとまでは言えないかもしれませんが、やはり、プログラミング言語のあるべき設計を使いこなせるアーキテクトがチームに存在していないのが原因の一つなのではないかと思います。

ところどころに散在する実験コードの痕跡

コードのアーキテクチャのスメルは、なにもスキルの低いプログラマーのみで構成されたチームで起こるとは限りません。非常にモチベーションがあって、やる気のあるプログラマーであれば、自然なこととして、いろいろと自分の新しいアイデアをどんどん試したくなります。それは、技術者としてはすばらしいことなのですが、業務アプリケーション開発のプロジェクトの顧客の要件を最短で満たすという制約された条件の中では、ある程度節度をもって計画的にやらないと問題となることがあります。実際、うまくいかなかったアイデアなどは未練を捨てて早期にクリーンアップするべきだと思いますが、実際上は時間の制約からか、あるいはプログラマーが入れ替わったからか、ところどころに過去の遺産がデッドコードとして残されることがあります。そういったデッドコードが存在していると、障害の解析が困難になったり、後々機能追加が大変になったりメンテナンスの上で苦労することになります。
そういった問題を防ぐためには、やはりアーキテクト的な視点からコードの状態を監視し、常に余分な複雑性が取り残されないようにする努力やプロセスが必要だと思います。

最後に、最近気づいたことを

最後に、最近になって気づいた自分の間違えについて書いておかなくてはなりませんね。以前であればこうした設計上の問題は日本のSI業界の構造が問題なのであるという話をしていたかもしれません(^_^;)が、ここで書いたような話は多少フィクションが入っているとはいえ、実際私がSI業界以外の今の会社で体験したことに基づいていると告白しなくてはなりません。言語の特性から、Javaで開発していると、こういった設計上の問題が起きやすいということがある可能性もありますが、こういった話はSIer以外でも、どこの国の開発チームでもあるのだなということですね。

こうした設計に陥る原因として考えられるのは、SI業界の構造というより、むしろ、アーキテクトがアプリケーション開発チームと一緒に仕事していないという問題にあるのではないかと思います。そして、実際多くの場合、「フレームワークチーム」「共通チーム」というのがアプリケーション開発チームとは切り離されて存在しており、フレームワークを開発プロジェクトが開始する前に作成して提供するというようなモデルの場合に起こりがちなのではと思います。さらに、非常によくあるパターンとして、あるバージョンのフレームワークを使ってアプリケーションの開発が進められている時点では、フレームワークは既にアクティブに開発されておらず、フレームワークの改善に興味がないということがあります。既にフレームワークチームは「次世代フレームワーク」の開発に目が移っていて、古いフレームワークはよほどのバグがない限り手を付けないというようなケースが多いかもしれません。

自分としては、なるべくオープンソースフレームワークを活用するなどして、自社フレームワークの部分を最小限にし、アーキテクトはアプリケーションのアーキテクチャの改善にもっと目を向けるべきなのではないかと思うのですが、さまざまな政治的、ビジネス的理由からそれができないのが問題でないかと思いますね。

*1:なお、ここではコンポーネントとはJavaパッケージのような論理的な名前空間の分割ではなくて、eclipsemavenのプロジェクトに相当するようなビルド・デプロイの分割単位のことを指すものとします。

*2:場合によってはインテーフェースやアノテーションを分けるのが有効な場合ももちろんありますが、それにはちゃんとした理由があります。リモートのサービスでインターフェースだけをクライアントから使うとか、昔のSpringがそうしていたように、JDK1.4をサポートするために、アノテーション依存の部分を分けるといったような例があります

*3:レガシーコードだったらともかくも、新しいプロジェクトでxmlに個々のbean定義を書くような規約だったら、これ自体かなり疑問な設計方針なのですが

*4:コンポーネント分割の構造とチームの構造がマッチしているのは基本的によいことだと考えられます。

*5:そして、多くの場合作成すべき各コードにベースとなる親クラスやインターフェースが存在してそれを継承して作成するルールになっているのですが、実際親はマーカーというか、実際になんら本質的な役割を持っていないという場合も多いです。これは親クラスが実際の必要性から作られたのではなく、最初からルールとして存在しているという何よりの証拠といえます。

*6:いわゆるPlain Old Java Object=POJOとして作成可能、継承などはアプリケーション側の裁量で自由に使えるようにする。

*7:StringUtilsやCollectionsのような標準のライブラリーにもみられるように、どこのクラスにも属さないロジックの格納場所として、最低限のUtilクラスは特に問題ではないと思います。ここで問題としているのは、大部分のビジネスロジックがUtilクラスで書かれているというようなケースですね。

ここぞというときの集中力Upのために、ヘッドフォンで音楽を聴きながらプログラミングしましょう

仕事や趣味でプログラミングしたり技術書を読みながら勉強したりする際には、言うまでもなく集中力を高めて維持することが大切ですね。職業プログラマーに必要な集中力ということには少なくとも二つの意味があるとは思いますが、

いずれにしても、自分の場合は寝不足だったり、周りの雑音で気が散ったりしてコンディションが悪い時にはあまり集中できずに、圧倒的に作業効率が下がってしまいます。逆に、調子よく集中できた時には時間がたつのも忘れて一気に仕事を片付けることができます。
もちろん、プログラミングで集中力を高めるためには、日頃から規則正しい睡眠や食事などが欠かせませんが、ここぞという時に一人で集中するにはヘッドフォンで音楽を聴くのが個人的には非常に効果的な手段だと思っています。
客先常駐の場合は、常駐先の会社の文化によってはヘッドフォンで音楽を聴きながら作業をすることを禁止しているところもあるかもしれませんが、幸運なことに自分のチームではOKなので、本当に一人で集中して考えたいときにはヘッドフォンを利用しています。もちろん、ヘッドフォンにはチーム間のコミュニケーションを阻害するという弊害もあって、周りの人に質問しづらくなってしまうという問題があるのですが、一日の作業のうちで集中する時間を区切って利用すればよいのではないでしょうか。
音楽を聴きながらプログラミングする際の問題は、どのような音楽が集中に適するかということですね。一般的には歌詞のない音楽でモーツァルトなどのクラシック音楽などがよいとよく言われますが、もちろん、これには好みによって個人差があると思いますし、人によってはクラシックはかえって心地よくて眠くなるという人もいるかもしれません。
私の場合はずいぶん以前からいわゆる「集中力Upのための音楽」というちょっと怪しげなジャンルの音楽に非常に興味があって、実際仕事や勉強でいろいろと活用しています。

Focus CD (フォーカス CD)

Focus CD (フォーカス CD)

たとえば、以上のCDは雨の音がひたすら聞こえるだけなのですが、左右の耳から周波数の異なる音を同時に聴くことでいわゆるバイノーラルビートと呼ばれる効果で脳の集中力が活性化するそうです。Amazonのレビューでも高評価なので試してみてはいかがでしょうか。このCDの製造元の説明は以下にあります。
immramainstitute.com
そのほか、同様のバイノーラルビートを活用した音楽でヘミシンクと呼ばれるシリーズのタイトルはいくつか利用していますが、個人的にはかなりおすすめです。(以下で部分的に視聴できます。)


インディゴ : Indigo for Quantum Focus [ヘミシンク]

インディゴ : Indigo for Quantum Focus [ヘミシンク]

コンセントレーション : Concentration [ヘミシンク]

コンセントレーション : Concentration [ヘミシンク]

アインシュタインズ ドリーム : Einstein's Dream [ヘミシンク]

アインシュタインズ ドリーム : Einstein's Dream [ヘミシンク]

イルミネーション フォア ピーク パフォーマンス : Illumination for Peak Performance [ヘミシンク]

イルミネーション フォア ピーク パフォーマンス : Illumination for Peak Performance [ヘミシンク]

Remembrance [ヘミシンク]

Remembrance [ヘミシンク]

ブレークスルー : Breakthrough [ヘミシンク]

ブレークスルー : Breakthrough [ヘミシンク]

以下は、ブレインシンクと呼ばれる別のシリーズで、ヘミシンクと同様に集中力や記憶の向上に役立つとされているタイトルがあります。
High Focus: Activate Lucid Thinking (Brain Sync Audios)

High Focus: Activate Lucid Thinking (Brain Sync Audios)

Brain Power

Brain Power

なお、これらの音楽は人によっては非常に深い集中状態をもたらすため、逆に外界に対する反応が鈍くなってしまうことがあり、自動車で運転中などには絶対に聴かないようにとの注意書きがあります。

転職して感じたウォーターフォール文化とアジャイル文化の違いについて

今月から新しい会社に転職して、あっという間に半月が過ぎてしまいました。いろいろな会社の規則や、開発環境、フレームワーク、仕事の進め方など、とにかくたくさんのことを短期間で詰め込む必要があり、もともと想定していたことではありますが自分としてはかなりたいへんでした。
やはり、自分としては、外資系の会社で英語でのコミュニケーションが必要となるということが、最も気がかりなことでした。実際、初日の歓迎ランチはいきなり名前もわからない多くの外国人に囲まれる状況でしたし、電話会議を使って中国やアメリカのチームと一緒に行う日々の進捗ミーティングも英語で行われています。自分としては、特に、リスニングが苦手ということもあり、いまだに完全に会話についていくのが困難なところはありますが、同僚やマネージャーもみんなすごく親切に教えてくれるので安心しました。私は新しい環境に慣れるのに結構時間がかかる方なので、まだまだ完全に新しい職場の文化に適応するというところまではいかないのですが、徐々に仕事のやり方を覚えて、チームの一員として頼られる存在となれるよう努力していきたいですね。
ということで、実はまだ新しい会社の文化を完全に理解したという段階ではないのですが、それでも以前私が働いていたSI業界の文化とアジャイルな考え方が尊重されるグローバル企業とでは、やはり大きな違いがあるなということは、実際にはっきりと感じられますね。
まず、第一に大きく違うと思ったのは、会社の売上や利益に直接つながる、ビジネスの中心に近いところに開発チームが置かれていて、当然プログラマーはプロダクトオーナーなどビジネス担当の人と密接にやり取りをしながら開発を進めるというところがありますね。ビジネス担当の人とプログラマーが同じ部屋で作業をするということはもちろん、たとえば「この項目を外すとプログラムはすごくシンプルになるし、顧客にとっても画面がすっきりしてメリットがあると思いますが。」といったような提案をプログラマーからすると、あっさり認められて翌月のリリースに変更を反映するといったことが日常に行われています。少しでも使いやすいシステムの開発に貢献することで、売上に貢献するのだというモチベーションも湧きます。ウォーターフォールが中心のSI業界のやり方だと、項目の追加はまだしも削除などと言うことを提案しても、稟議書などを上げて何階層にもわたった承認が必要で、何週間、何か月も待つといったことは普通だと思います。そのような状況があるので、PGの側でもよいアイデアがあっても、わざわざ提案しようという気にはならないし、逆に、仕様書に書かれていることのみを実装して、余程の問題がない限りそれ以上のことはやらないという傾向が強くなってしまうところがあると思います。
それから、チームのサイズが小さくて、業務担当の人とプログラマーが直接会話できる距離にあるため、作成する文書は非常に少ないというところがあります。これはもちろんチームによると思いますが、開発後に説明のためWikiに情報を書くということはあっても実装前にWordやExcelの文書を作成するということはめったにないですし、作業時間の大半はEmacsVimEclipseといったツールを立ち上げてのコーディング、単体テストの作業が中心となります。以前は自分自身がコードを書くといった作業にあてられる時間は、全体のプロジェクトの中ではせいぜい10%程度でしたので、そこは大きな違いだと感じています。逆に言うと、自分の英語力のなさから、口頭で英語で説明を受けても理解しにくいというところがあり、時としてきちんと書かれた仕様書が恋しくなる時もあるわけですが、そこは文化の違いですね。
さらに、B2Cでどんどん新しい機能をリリースしていくという環境では、システム全体を何年もかけて作り直すという機会はほとんどありません。むしろ、細かい機能改善やバグフィックスを行うというプレッシャーが常にあり、その中で空き時間を見つけてリファクタリングを繰り返すという方向になります。そういう意味では、SIerのように新システムの開発をゼロから行うという機会はめったにありません。だから、常に最新の言語やフレームワークでなくては嫌な人には向いていないかもしれません。一方、SIerの場合は自分のシステムを維持管理するという機会は少ないのですから、むしろ、最新の最良の開発手法を取り込めばすごく面白い仕事ができるのに、実際には古いフレームワークを使い続けているケースが多いというのは残念なことですね。
なお、気にしていた自分の年齢ですが、やはり、グローバルな会社では35歳定年などということは全くないですね。今の会社の場合は全くの新卒というよりも、ある程度経験を積んだ人を中心に採用しているようなので、プログラマーとして自分くらいの年齢でも結構普通みたいです。実際、おじさんというレベルを超えて、そろそろ孫がいても不思議でない、おじいさんという感じの年齢の現役プログラマーもたくさん活躍しています。もちろん、年齢というよりはスキルによってポジションが決まるので、年齢が下の人がより上級のプログラマーということも普通にあり得ます。(おじさんと書きましたが、もちろん、グローバルには女性のプログラマーもたくさんいます。)

SI業界の改革には責任者に対するショック療法が有効かもしれない

私の直属の上司ではないのですが、会社の大先輩がインドに1ヶ月程滞在し、現地のSIerの開発現場を視察してきました。現地での研修を提供している会社は、あのデータさんの子会社になっているみたいです。
http://www.vertexsoft.co.jp/services/learning-in-india.html
そこで、実際にインドのプログラマーアジャイルプロセスを使って開発をしている現場を目の当たりにし、いい意味ですっかり洗脳されて帰っておいでになりました。

  • 1週間ごとに追加機能をリリース
  • スタンドアップミーティングによるタスクの割り当て
  • 徹底的に自動化された進捗管理*1
  • 徹底的に自動化されたテスト
  • きわめて計画的で少ない残業時間
  • プログラマーの地位の高さと優秀さ

やはり、百聞は一見に如かずといいますが、日本のSI業界の開発手法が20年も遅れていると言われても、何十年も開発の現場から遠ざかっているとなかなか実感がわかないものですが、現地で一ヶ月も過ごすと相当意識が変わるようですね。それで、その年配の先輩社員は「一週間のイテレーションアジャイルを」などと、早速周りに宣伝して廻っているみたいです。
インドにおけるアジャイル開発については、以前にインドと日本におけるプログラマーの社会的地位の違い - 達人プログラマーを目指してでも書いているのですが、さすがにSIer大国だけあって、日本とはいろいろと違う状況にあるみたいですね。実際、想像以上にガラパゴス化した日本のIT業界? - 達人プログラマーを目指してで示した結果を見ても分かるのですが、インドはJava EEなどエンタープライズ開発の世界的な中心になっています。
ちなみに、インド人の平均年収は世界各国の平均年収を参考にすると35万円(日本人より一桁少ない)くらいなのに対して、プログラマーの年収は以下によると平均で(最大ではない)200万円程だそうです。*2
大手SIer(インド)の収益向上がとどまることを知らない件 - Thoughts and Notes from NC
もちろん先進国とはエンゲル係数などが全然違うのでしょうけれど、単純計算すると平均の6倍も給料をもらっているということであり、日本人の感覚からすると年収2000万円以上のセレブということになるのでしょう。インドにおけるプログラマーの社会的地位は医者以上という話も実際にインド人の方から聞いたことがあるのですが、年収の格差を考えれば十分に納得のいくものです。当然、そのような社会でプログラマーになれるインド人は専門の一流大学でコンピュータ科学を学んだような超エリート達なのであり、日本で言えば東大の理学部情報学科を卒業したような人たち*3SIerプログラマーとして働いているというちょっと信じられない状況になっているわけです。当然英語や数学もできて、オブジェクト指向や先進の開発ツールを活用しながらプログラミングしているというわけなのでしょう。
ちなみに、その先輩社員から聞いた話によると、インドの社員食堂のカレーライスは80円だったそうです。エリートの会社の食堂ですから、インドの一般庶民の感覚からすればこれでもかなり高いそうですが、日本における値段の10分の1くらいしかしないのですね。
そういった状況を考えて、コスト的にも人材的にも、インドは非常に有利な立場にあるわけで、日本と違ってSIerが高い収益を上げて成功しているという事実は仕方が無いことなのかもしれません。そういうところで日本のSIerがインドのSIerと同じ土俵で真っ向勝負してかなうはずもありません。しかも、単に人月辺りのコストの違いだけでなく、自動化などによる開発の効率化といったものの違いにより、日本とインドの金額辺りの生産性の差はさらに大きなものになっているのではないでしょうか。まずは、彼らの先進的な取り組みについて謙虚に学びながらも、今後我々としてはどういう方向に改革していくかといったことを考える必要があります。今のところインドより経済的には遥かに裕福で恵まれているのですから、お金や人材をもっと良い方向で正しく使う道もあるのではと思いますね。
明治維新で活躍した人物の一人である岩倉具視はちょんまげと着物でアメリカを訪問したという話は以下の写真で有名です。
ファイル:Iwakura mission.jpg - Wikipedia
しかし、当時のアメリカの進んだ文明に触れカルチャーショックを受け、以後大きく考え方を改めて鉄道の建設をはじめとして文明開化の推進者となったとのことです。

この旅の中で岩倉は各国で激しいカルチャーショックを受けた。アメリカの近代国家ぶりは岩倉の想像をはるかに超えており、よほど衝撃的だったようで三条に宛てた書状にも「殷富を進むるにおいて意想の外を出るに驚嘆」とまで称している。さらにその原因は鉄道にあるとし、日本の繁栄も鉄道にかかっており日本の東西を結ぶ鉄道の設置が急務とする。岩倉が帰国後日本鉄道会社の設立に積極的に携わったのもそのためである。またイギリスでは日本では考えられない工業技術に圧倒された。もはや条約改正どころではなく使節団は各国への留学が主要目的となった。
ちなみに、岩倉はこれまで髷は日本人の魂であると考え、落とすことを拒んでいた。そのため訪米時も髷と和服姿であったが、アメリカに留学していた子の岩倉具定らに説得され、シカゴで断髪している。

SI業界の意識改革を推進させるためにも、情シスやSIerの重鎮は、日本に留まって古いやり方を続けているのではなく、積極的に海外の進んだ状況を視察し、一度カルチャーショックを受けてくるのがよいのではと思ってしまいました。

*1:会議と線表ではなく、ツールを使って進捗を数値化した上で管理している。RallyVersionOneというツールを使って管理しているらしい。

*2:最近インドのプログラマーの人件費は上がっていると言われるけれど、確かにこの水準だと日本人プログラマーに比べて桁違いに安いわけではないですね。

*3:普通彼らはGoogleか海外に行くのかな。

自分の定めた目標に向かって努力するということ

最近id:j5ik2oさんの努力する人が最後には”できる人”になる - じゅんいち☆かとうの技術日誌というエントリーを読んだことがきっかけで、エンジニアとして「努力する」ということについてちょっと考えてみました。

努力と目標設定

普段意識していなかったのですが、もともと努力という言葉にはある目的に向かってがんばるという意味が込められているようですね。
努力 - Wikipedia
英語のeffortとかendeavorといった単語にも似たような意味がこめられています。だから、本来、努力とは、ある目的に向かっていろいろ試行錯誤するということが本質的なのであり、そう考えると2011-02-08で書かれていることも本来の意味での努力ということを否定しているものではないのかなと思います。ただ、日常では決まった目標もなく無駄に「あくせく努力する」などという否定的な使われ方もしますし、根性論 - Wikipediaと同一視されるところも多分にありますね。
ですから、本当の意味で努力するというのであれば、まず、自分が何をしたいのか、どういった人になりたいのかといった自分の目標を設定することからはじめる必要があります。努力が好きな人とそうでない人の違いはまずこの目標設定ができているかどうかの違いというところもあるのではないでしょうか。id:j5ik2oさんも

目的や目標を持たずに奔放に生きても、なかなか自分の思い通りにはならないのは自明。だから、今日は何をするための一日か決めて行動している人は理想に近づける人なんだと思う。どんなことがあっても、いわれても、自分の歩みを止めずに、諦めずに前に進めばいいと思う。

とおっしゃっているとおり、努力することが苦痛ではなく、好きになるためには、まずは主体的に自分の短期的、長期的な目標を定めることがポイントなのではないかと思います。

誰一人として同じ人はいない

ただし、この世の中ではどう考えても、人それぞれ、資質、才能、境遇といったものがはっきり異なっているという厳然たる事実があります。
以前は自分と他人とを比較して、劣等意識を感じたり落ち込んだりしましたし、正直なところさまざまなコンプレックスからいまだに完全に卒業できていないということがあります。ですから、

違うよ違うよ。できる人の理由を後付けで探したら、努力している点があったんだけど、努力していないで天賦の才の部分はないがしろにされていたり間接的な協力者が見えなくなっていたりするだけだよ。

のような意見が出てくるのも当然であり、単純にやり過ごすことができません。
自分のような凡夫人には、残念ながら今のところ、こうした矛盾や問題に関して完全な答えというか悟りを得られていません。世の中には成功者としてセレブな生活を送っている人もいる中で、アフリカの子供のようにその日に食べるものもなくて苦しんでいる人もいるという事実を忘れてはなりません。*1
この点については、id:j5ik2oさんの書かれているように

できる人と比べて勝ち負けではないのです。人それぞれに個性があって、華の咲かせ方は違うのだから比べてもしょうがないのです。比べるなら昨日の自分と比べて成長しかたどうかです。それしかないです。

ということなのかなと理解しています。当然、与えられた器や境遇は違っていても、人それぞれ目標を定め、それに向かって努力することは可能であると思いますし、そういった努力をする自由を、神様、仏様は与えてくれていると思います。器によって大小の差はあれ、目標に向かって努力し、それに近づく喜びや、自分や他人に対して価値を創造する楽しさを体験できるようになっていると思います。努力すれば誰でもオリンピックで金メダルを取れるとか、ハリウッドスターになれるといったことは残念ながら確かに違うとは思うのですが、自分の決めた目標に対して努力することで自己実現を達成するという意味で誰でも成功者になれる可能性があるということです。

自分が本当に面白いと思う目標に向かって努力する

目標設定は自分の好きにすればよいのですが、やはり、自分が面白いと思うこと、わくわくする目標に向かって努力するというのが大切だと思います。だから、偉くなって人の上に立つ存在となったり、新しいビジネスを考えてお金持ちになるという目標は自分が面白いと思えるのであれば、大いに結構なことであると思います。しかし、他人の評価ばかりを気にして、お金や名誉など物質的、社会的な価値観のみにしたがって、生きようとしても必ずしもうまくいかない場合もあると思います。少なくとも、私自身は以前年収をあげるために、「今後はプログラミングだけでなく、上流の設計やコミュニケーション能力を努力して身につけなくては」と思っていた時期があり、開発の仕事をやめて転職し、年収の高い外資系ソフトウェアベンダーのコンサルティングをやっている部署で仕事をしていたことがあります。その時の会社の上司から

  • 君は他人の話をまったく聞いていない
  • 君の話していることがよく分からない
  • 君は建前と本音の区別がつかず、白黒はっきり付けすぎる
  • もっと大人らしい考え方をしなさい
  • 話の話題がコロコロとよく変わる
  • 君のコミュニケーション能力は最低だ

などとよく注意され*2、自分はなんてコミュニケーション能力が低いのだろうと思って落ち込んでいた時期がありました。会社でも環境を改善しようと自分が積極的に動いたことが裏目に出て、同僚から村八分に近いような状態にされてしまったりとつらい経験もしました。しまいには、「そんなパフォーマンスが低いなら会社を辞めてもらう必要がある」とまで部長に言われました。自分なりによい仕事をしようとがんばっているはずなのに、どうしてという気がしました。それで、正直に言うと、それがきっかけでしばらく人間不信というか、対人恐怖症、社会不安障害のような状態になってしまい、1年近く精神科に通ったりしていた時期もあったくらいです。*3
結局、その会社での仕事は2年も続かず、年収が200万以上も下がることを覚悟の上*4で、開発の仕事に戻ったのですが、自分としてはそれが間違った選択ではなかったと今では思っています。その後、プログラミングの仕事に復帰して、水を得た魚というか、いろいろなシステムの開発にプログラマーやアーキテクトとして参加し、プロジェクトの成功に貢献することで、再び自分の自信を取り戻すことができました。やはり、自分に合った仕事を見つけるということは非常に大切なことだと思いますし、自分の面白いと思えるものに素直にしたがって目標を定め、いったん目標を決めたらそれに向かって努力するということが大切なのであると思っています。*5

これからはプログラマー一人一人の努力がもっと報われる時代に

でも、いくら好きな仕事であっても、プロフェッショナルな仕事であれば単なる自己満足で終わるのではなく、お客様や会社の上司に感謝、評価してもらいたいし、努力に対する対価を求めていくというのは素直な感情だし間違っていないとも思います。つまり、評価のために仕事をするわけではないけれども、よい仕事をしたいという理想を追求することが顧客や会社にとってもメリットになり、自動的に高い評価につながるということが理想的だと思います。本当はSI業界においても良いプログラムを作成するということは本来価値のある仕事だと信じていますが、たまたま、人月ビジネスモデルという慣習があって、プログラマーのよいプログラムを作りたいという価値観と会社の価値観とが一致していないという不幸な現実があるだけです。(エンジニアが人月商売の会社で働くのってどうよ? - GoTheDistance
ただ、このブログでも、他のところでも指摘されている通り、これからは本当に良いプログラムをできるだけタイムリーに効率的に開発し、長く使っていきたいという時代にならざるを得ないところがあると思います。つまり、上流や下流といった区別なくプログラマーが顧客に近いところで直接システムを提案する傾向になってきているということです。*6また、最近では気軽にOSSを作成して公開する*7ことも簡単にできる時代ですし、GAEで自分のWebサービスを公開したり、スマフォ向けアプリを書いたりいろいろなことが可能になっています。また、英語や中国語を本気で勉強して海外で仕事をしたりすることもできるでしょう。一人一人がその気になればチャンスはたくさんあるし、プログラマーとしての努力が報われる時代に確実になってきていると思っています。
なお、会社が悪いとか業界が悪いというネガティブな意見も少なからずあるかと思いますが、ペイ・フォワード (角川文庫)のお話のように、自分の身の回りから少しずつでも世の中を良くしていくことに貢献していくことができるわけです。今の時代はソーシャルネットワークなど、(プログラミングに限りませんが)一人一人の努力の成果が一昔前と比べると桁違いに急速な勢いで広がりやすい、本当にすごい時代になっているのではないかと思いますね。ちょうど、ドラゴンボール元気玉のように一人一人のパワーは小さくても、多くの人々の思いが集まることで凶悪な敵をも倒してしまうように、個々人が問題意識をもって努力すれば(内外から)SI業界をもっと魅力のある業界にリファクタリングしていくことは決して不可能ではないと信じています。
私も今後もいろいろなことを悩んだり迷ったりしながらも、達人プログラマーとなるべく努力を続けていきたいと思っています。

*1:自分の実家は浄土真宗で、お葬式や法事などの際には「南無阿弥陀仏」とお経を唱えるのですが、これは帰命無量寿如来、すなわち、無限のパワーをもった阿弥陀仏の本願力を信じて、日々感謝して生きるということのようです。つまり、現実世界のフィジカルな世界は矛盾だらけなのだけれど、それを超えたメタフィジカル(形而上)の世界には阿弥陀仏に象徴される完璧な世界(極楽浄土)があるのであり、阿弥陀仏の無限の大いなる力によって善人も悪人も我々全員が守られているとの思想ですね。Java言語などのプログラミング言語の世界で例えていうと、この世の現実世界が普通に業務ロジックを実行するオブジェクトやクラスの世界だとすると、浄土というのはメタクラスやリフレクションの世界ということでしょうか。そうすると、この世の中にはいろいろなクラス(型)や状態のオブジェクトが存在しており、その部分のみを見ると差別や矛盾だらけに思えるのですが、メタな世界では共通の法則(VM仕様)にしたがっているのであり、JVMのメモリ空間を共用しているという意味ではすべてのインスタンス(霊、ソウル)がお互いにつながっているということです。極楽往生を信じて生きるとはJVMが完全でバグっていないと信じてJavaのアプリケーションプログラムを作るようなものであり、よく生きるように努力するとは、メモリ使用量を最適化したり、リファクタリングしたりするようなものかとなんとなく思います。

*2:今から思えば、それは典型的なアスペルガー症候群の症状だったのですが、当時はそんな病名は知らなかったし、自分の能力の無さや不器用さがいやになりました。

*3:当時はなんてパワハラな上司だとその部長を恨んでいましたが、今ではそれも良い経験の一つであったと考えられるようになりました。

*4:気の許す同僚からはプログラマーでは将来食べていけなくなると親切に止めてくれる人もいたのですけれど、上司からは辞表を待ってましたという感じで一度たりとも引き止められることはありませんでしたし、お別れ会とかそういったものもありませんでした。全部の会社がそうではないと思いますが、外資系だと営業成績が悪くても社員をリストラできない場合はイジメをしてでも自発的に退職することを促すという文化があるのだと思います。

*5:理解や習得の速さも人それぞれだと思うので、たとえば本を読んですぐに理解できないからといって自分は才能がないとすぐにあきらめてしまう人はいますが、必ずしもそういう必要はないと思います。「好きこそ物の上手なれ」ということわざの通り、時間をかけてじっくりと習得するタイプの人もいるわけなので。私の場合は、大体新しい言語やフレームワークの本を読んでも最初ちんぷんかんぷんなことが多く、同じテーマの本を何冊か読んでようやく分かった気に成るということが多いですね。現在もプログラミングScalaを勉強中ですが、ところどころの記述でかなり理解できないことだらけです。あせらず、じっくり取り組んでいこうと考えています。

*6:そういう意味では、私のいままで「苦手」と考えてきた顧客とのコミュニケーション能力が重要になってきているということです。ただ、根回しとか行間や空気を読むといったコミュニケーション能力ではなく、プログラマーとして本音で顧客と話すといったことはまた違った能力であると思います。

*7:現在では個人ブログを開設するのと同じくらい気軽にオープンソースプロジェクトを開設できます。GoogleCode、GitHubSourceForgeなどを利用すれば、一人でも無料で自分のソースコードを公開してコミッターになれるのです。

自分は恵まれた環境で仕事をさせてもらっていることに感謝しなくてはいけないと思う

私の会社は一般的なSIerと比べてどちらかというと技術力を売りにしている会社だと思いますが、その中でも、現在はアーキテクトチームと呼ばれる部署で働いています。そういうこともあって、自分の周りには40歳過ぎてもプログラミングしているような人もたくさんいますし、同僚はみんな勉強熱心で技術好きの人が集まっているため話もよく合います。そういう意味ですごく居心地がよいですし、恵まれた職場環境で仕事をさせてもらっていると思います。
ただし、いわゆる研究開発専門の部署ではないので、設計や開発の支援のため実際の開発案件に入って仕事をすることになります。ほとんどが客先での常駐作業になるのですが、仕事のやり易さや満足度は、当然のことですが常駐先のお客様ごとに全然違いますね。
このブログで指摘してきたようなつらくて大変なプロジェクトもいろいろとありましたが、中には今でも成功体験として記憶に鮮明に残っているようなプロジェクトも何回か体験させていただくことができました。少なくとも私にとって働き甲斐のあったプロジェクトに共通して言えることは、技術者とマネージャーとの間でお互いに信頼関係を築くことができていたということですね。多くの場合、

  • PMもプログラマー出身者で今でも最新技術に興味がある
  • PMは技術を全然知らないが、技術上の判断はプログラマーの意見を尊重してくれる

のどちらかでしたが。DIがまだ珍しい時代でも、Springの導入をさせてもらったり、AspectJを導入させてもらったりしたこともありました。アナリシスパターンやDDDを設計に取り入れてもらってやっていたプロジェクトもあります。もちろんメリットに対してきちんとした説明を求められることは当然ですが。それから、上級者に対してワイドモニターやメモリー容量の大きな高速のPCを与えてくれたり(シャア専用PCと呼ばれていましたが)環境面のことも考慮してもらえましたね。そういうプロジェクトだと、毎日の仕事がものすごく楽しいというか、帰りがいつも12時過ぎという非常に忙しいプロジェクトにもかかわらず、すごくモチベーションが高いので苦にならないところもありますね。(逆に働き過ぎをマネージャーから注意されるくらい。)
一方、私の経験したいやな仕事としては、

  • チームメンバー全員電話を3コール以内にとることを求められる*1
  • インターネット接続環境もなく、Excelのドキュメント作成だけ何ヶ月もやらされる
  • つまらない会議に何時間も参加させられた上に議事録作成もやらされる
  • ステップ数とかバグ発生率とか古いメトリックスで生産性を計られる
  • 出社時間や服装やセキュリティールールなどに特に厳しい

などがありましたね。サラリーマンとしては当然のことかもしれませんが、ピープルウエア 第2版 ? ヤル気こそプロジェクト成功の鍵に書かれているように、もうちょっと技術の専門家として扱ってほしいという気がします。さすがに、現在はアーキテクトという立場で参加するので、オブジェクト指向を使うなとか無知なマナージャーから上から目線で変なことは言われることはなくなりましたし、ある程度自分の意見でプロジェクトの進め方を改善するようにアドバイスできる立場にあります。
自分自身の経験上は、PMやリーダーの考え方によってプロジェクト参加者の満足度や生産性はかなり変わってくるのかなと思います。SI業界のリファクタリングとしては、まずは現場レベルで職場環境の改善を行い、技術者の満足度やモチベーションを改善していくのが良いのではないかと思います。
ただし、仕事に対する自分自身の満足度が高く、顧客に対していくら評価の高い良い仕事ができても、人月の下請け常駐モデル(SES)では会社の収益もそれほど上がらないし、自分の給料にも反映されにくいというのは悲しいところです。そうかといって、大規模な一括案件といういわゆるSIer的な仕事は労働集約型で最悪パターンに陥る事が多くできるだけ避けたい気がしますが。この辺りは、ビジネスモデルというか、現場レベルではどうしようもないので、もうちょっと会社の経営レベルや業界全体のレベルで何とかいい方法を考案してもらわないとどうしようもないのかもしれません。

*1:下請けに電話対応させるのは今ではコンプラ的にかなり問題だと思いますが

あの認定試験問題の品質をSI業界の代表的なプログラム品質と考えることの是非

SI業界(日本)のJavaプログラマーにはオブジェクト指向より忍耐力が求められている?に対して、既に何人かの方々から

単に駄目試験だってだけなのでは。

これ確かにヒドイけどこんな資格試験の内容ひとつで業界全体を語られても

のようなご指摘をいただきました。実際に試験問題の品質を持ち出して、実際のSI業界全体の品質を語るのは議論の飛躍し過ぎたところがあり、私としても反省しております。
しかし、既に指摘させていただいているように、実際のSIerの開発したシステムで使われているプログラムの品質というのは会社の知的財産権や秘密主義といったことから、オープンソース化されることがめったにないというのが事実であり、本当のところどうなのかということについては残念ながら神のみぞ知る事実ということになると思います。*1
したがって、こういったところは自分の少ない経験を通して推測するしかありません。(グルーポンのおせち事件を受けてSI業界が本当に教訓とすべきことでも指摘したように、こういったプログラム品質の見えにくさはSI業界固有の問題だと思います。)
私がアーキテクトとして全体の設計や規約に対して責任を持って開発をすることができたプロジェクトでは、ここまでひどい設計はしてこなかったという自信があります。しかし、デスマプロジェクトの火消しや、うまくいっていないプロジェクトのプログラムをリファクタリングしたりレビューしたりする仕事の機会が今まで少なからずあり、そうしたプロジェクトではほぼ間違いなくこの試験問題のレベルかそれ以下の、まったくオブジェクト指向でない設計で行われたコードとなっていました。

  • クラスの長さが10000行を超えるGod Class
  • パラメータの数が60個を超える
  • 業務レイヤーのクラスが画面固有のクラスに平気で依存する
  • ほとんど同じ内容のコピペクラスが何十回となく繰り返される。
  • 同一の文字列メッセージなどの定数値がいたるところに繰り返しハードコードされる。
  • フレームワークの規約により無駄なクラスが大量に作られる(アンチパターン―ソフトウェア危篤患者の救出ではお邪魔妖怪アンチパターンとして紹介されている。)
  • まったく利用されていないデッドコードが多数存在する。
  • 番号つきのおかしなクラス名

などといったレベルのプログラムは今までに実際何度も目にしてきています。それゆえ、今回この問題のことを発見して、「やっぱりそういうことだったのか」と思ってしまい、不適切な類推で議論を進めてしまったというきらいがあります。
しかし、上のコメントをいただくような方は

  • 高度な技術を発揮してSIをしている稀有な非常に恵まれた会社で仕事をしている
  • SI業界での開発をした経験がない。
  • 上流専門の方で下流工程のプログラムの中身にまで関与したことがない。

という方が多いのではとも思ってしまいます。実際、全体的にみればあの記事に対するコメントの多くは、例の問題の品質が実案件の多くのプログラムの品質を実際に暗示するということを裏付ける内容のものでした。これは、こうした品質の問題があるプロジェクトが多数存在する事実が無視できない件数存在する証拠であると言ってよいのではないでしょうか?
だから、私は単に資格試験の品質の問題として片付けてしまうのではなく、ここでいったん現状のSI案件の品質や設計、開発の進め方、オブジェクト指向の理解度などについて関係者が胸に手を当てて反省するタイミングなのではないかと考えています。もちろん、うちのシステム開発のやり方は問題ないと思えるのであれば、非常にすばらしいことでしょう。

*1:場合によっては、2chWikiLeaksなどに裏情報が流れていたりすることもあるのでしょうか?