アジャイルの原点に立ち戻る (DevLOVE Advent Calendar 2019)

開発全般

このポストは、DevLOVE Advent Calendar 2019の18日目です。
テーマは「それぞれの10年、これからの10年」ということで、自分自身や周りの環境の、「これまで・いま・これから」を考えてみたい。

10年前〜

2009年というと、今の会社に転職してまもなく2年という時期だった。当時は.NETエンジニアで、担当していた仕事も.NETベースの業務アプリケーションやパッケージソフトの開発・保守だった。前職は技術系のコンサル会社だったので当時からXPベースのアジャイル開発をやっていたけれど、日本におけるアジャイルの普及度は当時まだまだだったと思う。

当然ながら今の会社(SIer)はアジャイルとは程遠く、ウォーターフォールの開発プロセスを全社に定着させてCMMIを取るぜ、なんていう状況だった。なんで転職したかっていうと、アーキテクトとしてエンタープライズの大きなシステムのアーキテクチャ設計をするということに憧れていたから。ファウラーの『エンタープライズ アプリケーションアーキテクチャパターン』という本が売れたけど、アーキテクトはエンタープライズシステムの設計をやってなんぼ、という雰囲気が(少なくともぼくの中には)あった。

その後Javaエンジニアに戻りつつ、いわゆるバックオフィス系の基幹システム構築をいくつか経験した。金融のような超大型プロジェクトと比べるとそこまでではないけれど、それでも1,000人月を優に超える大きなシステムのアーキテクチャや方式の設計を経験したことは実際によい経験となった。

けれどもウォーターフォール、オフショア前提のプロジェクトでは試行錯誤で少しずつ改善していくというアプローチは取りづらくて、スパイク的に2,3の典型的なユースケースを先行実装したものをお手本として、あとは開発規約や実装ガイドを遵守して横展開で大量生産していくというやり方しかなかった。オフショアの技術レベルは高くないしコミュニケーションの壁も大きいから、余計なことを考えさせない、逸脱させないというまさに管理型の開発だった。

いま

3年ほど前から自社のパッケージ製品の開発を担当するようになって状況は一変した。
社員の比率が高いプロジェクトチームによる内製での開発。スクラムベースのアジャイル開発。
今年から新しいプロダクトの開発リーダーとして仕事をしているが、プロダクトのコンセプト設計から自分たち主導で行い、機能のバックログを作成して、スプリント毎に仕様の検討や機能の実装をインクリメンタルに進めている。
企画段階ではバリュープロポジションキャンパスやサービスブループリントといったサービスデザイン関連のツールを使ってワークショップをしたり、インセプションデッキを作りながらチームビルディングを行った。

だけど、十分アジャイルになれているか(Be Agile)と問うと、まだまだと感じている。

Clean Agile

ぼくは昔からロバート・C・マーティン(通称ボブおじさん)の本が大好きで、『Clean Architecture』も原書と翻訳版を持っていて4周は読んでいるのだけど、つい最近新作『Clean Agile』が出版された。副題は『Back to Basics』とうことで、アジャイルマニフェストが採択されてから20年近く経ったいま、改めてアジャイルの基本や原点に立ち戻ってみよう、という主旨となっている。

ボブおじさん曰く、今の社会ではソフトウェアなしには重要な物事は何もなし得なくて、ゆえにソフトウェアが、あるいはそれを書く我々プログラマが世界を支配している、と。品質の悪いソフトウェアは最悪人を殺したり、経済に損害を与えたり、ソフトウェアの関係者を不幸にしてしまう。だからこそプログラマはアジャイルの規律を守り、プロフェッショナリズムをもってソフトウェアを開発していなかくてはならない。アジャイル開発は急速に普及したけれど、プロセス面ばかりが強調され過ぎている風潮もある。もう一度本来のアジャイルプラクティスを確認、点検していこうよって本。

んでもって、いまの自分やチームを見たときに、まだまだできてないよな〜というプラクティスを順に考察してみる。

プラクティス:Collective Ownership

もちろん、ソースは書いた人の所有物なんてことはないのだけど、実際にはタスクのアサインはリーダーであるぼく自身がほぼ決めている。なぜか? 一つは、エンタープライズならではの仕様の複雑さや、製品ならでの汎用性要件のため、非常に実装難易度の高い機能が多いこと。一方でいまのチームは新人を含めて経験の浅いメンバーも多く、リリースから逆算して考えるとどうしても人の割当というパズルを先にやってしまっている。

これはマネジメント面でも非効率で、本来ならバックログのポイント総量を割ることのチームのベロシティという計算で、だいたい残り10スプリントで行けそうだとか、一部のストーリーの出し入れが必要そうといった判断ができるのが理想形。山積み・山崩しは大きなリリース計画をする上ではある程度やる必要はあるんだけど、状況に応じて柔軟に対処できるチーム作りをしていくこともマネジャーやリーダーの仕事のひとつであるはず。

そういう意味でぼくはまだ仕事ができていない(苦笑)。ただ理想としてはチームとして問題に立ち向かう、タスクをアサインするのではなくて開発者が主体的にタスクを選択するという状態を目指してはいきたい。そのために、モブプロ等のアクティビティを通してチームのスキルレベルの底上げを進めている、というのが率直な現状。

プラクティス:Small Releases

作っているのがサービスではなくてパッケージなので、リリースは固定されている。けれども、ボブおじさんが言うように、イテレーションの終わりでは技術的にデプロイ可能な状態になっているようにしなければならない。実際にデプロイするかどうかはビジネスの判断となる。パッケージなので本番にデプロイすることはないんだけれど、例えばテスト環境にデプロイするとか、デモ用に営業のPCにデプロイするとか、そういったことが可能な状態というのを目指すべきだ。

なぜできていないのか? やっぱりエンタープライズならではの複雑巨大な機能があるため、2週間のスプリントでユーザーにとって価値のある状態に仕上げるのが難しいというのはある。特に最初の骨格ができあがるまでは。とはいえ、薄いユースケーススライスを足していくような形にうまくストーリー分割ができれば、もっとうまくやれるんじゃないかなとも思う。

プラクティス:Acceptance Tests

Small Releasesを可能とするためには、イテレーションで開発する機能の完了条件を明確化し、受入テストを行わなければならない。いまのプロジェクトでは、ユーザーストーリーを以下の形式で記述することをルール付けている:

[ビジネス上の目的]のために、

[アクター]として、

[システムのフィーチャ]が欲しい。

これはこれで有用で、なぜその機能が必要なのか、それは誰のためなのか、というビジネス的な背景を開発者が理解した上で、仕様の議論に入っていくことができる。そしてその仕様は即ち受入条件として明文化されるべきである。CucumberなどのBDDツールを使ってGiven-When-Thenの形式で受入テストの仕様を記述して、自動実行できるテストコードに落とす。これはユーザー目線で見たブラックボックステストであり、開発者このテストをパスするように内部のコンポーネントやクラスを実装していく。

というのが理想形で、ぼくのプロジェクトでもCucumberやSerenityといったツールを導入しているけれど、まだまだBDDで進められてはいないので、これはこの先頑張りたい部分。

プラクティス:Test Driven Development

BDD以前に、TDDも部分的にしかできていないのが実状だ。いまのプロジェクトはClean Architectureを導入していて、そのモチベーションはいろいろあるんだけども、中でもテスト容易なアーキテクチャという点を重視している。ユニットテストフレームワークもJUnitではなくてSpockを採用したので、テストコードを書く面倒臭さもかなり解消された。実際、テストコードは結構書いてはいる。ただしプロダクトコードを書いた後で。。

TDDというプラクティスは、思った以上に難しくて、鍛錬を積まないと習得が難しい。それこそ、『テスト駆動開発』をひたすら写経するとか。考え事をしながら自転車に乗っていたのに気付いたら自宅に着いていた、といったレベルになるまで身に付けないとTDDをやっているとは言えないと考えている。ぼく自身、「今日はTDDでやるぞ。」と意識しないと、ふつうにプロダクトコードを書き始めてしまうのでまだまだ修行が足りていない。チームとしてもTDDの練習をしていきたいなと思っている。

Spockの素晴らしさ

いまのプロジェクトで新しく取り組んだことはいくつもあって、その一つがSpockを使ってユニットテストを書くこと。一度Spockを使い始めたら、正直もうJUnitには戻れない。戻れと言われたら死ねるレベル。

いいところはたくさんあるけれど、いくつか挙げるとしたら以下のような点かな:

  • GroovyベースなのでJavaのように冗長な記述をしなくて済む
  • Given-When-ThenのBDDスタイルで書ける
  • モック機能も内包している
  • 強力なアサーション機能
    def "一人分の料金が計算できる"() {
        given: "太郎は大人(20歳)"
        def taro = new Person("太郎", 20)
        and: "パーティは一人"
        def party = Party.of(taro)
        and: "料金表のモック"
        def feeTable = Mock(FeeTable)
        and: "料金計算機"
        def calculator = new FeeCalculator(feeTable)

        when: "料金計算を行う"
        def amount = calculator.calcTotalFee(party)

        then: "料金表が使用される"
        1 * feeTable.getFeeFor(FeeClassification.Adults) >> 1000
        and: "金額が正しい"
        amount == 1000
    }

これからの10年

これからの10年については、SIerに所属する技術者としては大きな危機感を持っている。DX(デジタル・トランスフォーメーション)の時代において、ソフトウェアは企業の競争優位を生み出す源泉に他ならない。そのことに気付いている先進的な企業は、優秀なIT技術者の確保や、主力事業・差別化領域の内製化を推進している。経済産業省の『DXレポート』では、2025年には約40万人のIT技術者が不足すると言われている。現在の国内のIT技術者の数が約100万人強と考えると、これは凄い数字だ。このような売り手市場では当然のごとくIT技術者の待遇も上がるはずで、事業会社に移るIT技術者も少なくないだろう。現在ではITベンダーと事業会社のIT技術者の比率は7:3くらいだったかと思うが、逆転して米国並みに近づいていく可能性だってある。

という環境下にあって、SIerはそのビジネス構造をどう変革させていくのか? SIerこそ、その収益の源泉はソフトウェア技術にあるはずで、優秀なIT技術者の確保は大きな経営課題であるはずなのだが、SIerのマネジメント層にその認識がある人間は非常に少ない。

組織の変革はとても難しいし、ぼく自身はなんの権限も持っていないのだけれど、まずは自分のチームをプロフェッショナルな技術者集団にしていって、自分たちの手で新たなサービスやプロダクトを生み出していけるようになりたいかなと思う。幸い直属の上司は理解のある人達なので、その方々に偉くなってもらえるとやりやすいかな(笑)

まとめ

ちょっと長文のポエムになってしまったけれど、ソフトウェア開発が大好きな一プログラマとして、この先も楽しく開発を続けていきたいと思う。

コメント

タイトルとURLをコピーしました