ドキュメント作成時の基本的な心構え

ドキュメント作成のコツについて一般的なことを書きます。
ドキュメントの良し悪しで意図が早く正確に伝わるかどうかが変わってくるので、スムーズに仕事をこなすには欠かせないスキルです。

ドキュメントには設計書からユーザ向けのマニュアル、運用手順等、色々種類がありますが、今回はどのようなドキュメントについても通じることを書きます。

【根→葉の流れで構造的に書く】

小説のように文章をつらつらと書くのではなく、適度に見出しを付けることが重要です。
また、その見出しは、根→葉の流れで構造的に書くことが重要で、見出しだけを見れば何がどこに書いてあるのかがわかるようにすることが理想です。
プログラム改修の設計書で言うと、以下のように書くのが良いでしょう。
 
 1.背景
  ……
 2.リリース日
  ……
 3.修正箇所
  3.1.プログラムA
   3.1.1.hoge対応
    ……
   3.1.2.fuga対応
    ……
  3.2.プログラムB
   ……
  3.3.プログラムC
   ……

【箇条書きや表や図で完結に書く】

・箇条書きの使用

並列である複数の事柄を書く時は、箇条書きを用いると文章が見やすくなります。
例えば、
「条件Aの時か、条件Bの時か、条件Cの場合に、hoge処理をする」
という文章は、以下のように書くとわかりやすくなります。

以下の何れかの条件に当てはまる時に、hoge処理をする。
 ・条件A
 ・条件B
 ・条件C

・表の使用

2×2かそれ以上の項目・条件が絡み合う事象を書く場合は、表を用いると状況をわかりやすく整理できます。

例えば、下記はリスクの対応策を表にまとめたものです。

これを表を使わずに表現すると、
「脅威に対しては回避と転嫁と軽減の戦略があり、回避とは…」
といういかにも冗長な文章になってしまいます。

・図の使用

複雑な事象を言葉で説明するのは難しいですが、図解するとわかりやすく説明できることが多いです。

例えば、理解が難しい概念である「モジュール強度」と「モジュール結合度」を図解した記事がこちらです。
「モジュール強度とモジュール結合度」の図解

日本語を読んでも何が言いたいのかわかりにくいと思いますが、図解することで意図を理解しやすくなると思います。

【誤解のない表現を使う】

・客観的な数値を示す

「性能が大幅に良くなった」「キャパシティに与える影響は軽微である」
といった主観的な表現だと、それぞれの受け手毎に異なる解釈をされる可能性があります。

ここは、異なる解釈をされないように、
「性能が10倍になった」「ディスク容量が100GBであるがデータ増加量は10MBである」
といった形で、客観的な数字で表すことが重要です。

・複数の意味で取られる日本語を避ける

例えば、「私は何度もコンソールがエラーを出力する所を見ました」という文章の場合、「何度も」の係り受けが曖昧であるため、以下の2つの意味で取られる可能性があります。
 ・私は「コンソールがエラーを出力する所」を何度も見た
 ・私は「何度もコンソールがエラーを出力する所」を見た

このようなことが設計書や手順書を書く中でも起こり得ます。

出来上がった文章を読み返して、複数の意味に取られないか考える癖を身に付けることが重要です。複数の意味に取られかねない時は、上手く書き換える必要があります。
特に、文章を短く区切る書き換えは、文章が分かりやすくなる可能性が高くお勧めです。
例えば、上記の例の場合、「コンソールは何度もエラーを出力しました。私はそれを見ました。」と書き変えると、意味が明確になります。

・要件、仕様等を明確にする

要件定義書なら誰がいつどのようにシステムを使うのか定義する必要がありますし、画面設計書なら画面項目のフォーマットや桁数等を定義する必要があります。

ドキュメントによって絶対に定義しなければならないポイントがあるので、そのポイントを落とさないようにすることが重要です。
もし定義が不十分だと、情報の受け手に自分の意図とは異なる解釈をされてしまう恐れがあります。

【情報の受け手に合わせて粒度を変える】

システムの利用者にとっては、システムをどのように操作すれば良いのかがわかれば良いので、詳しい仕様は冗長な情報になります。
逆に、システムの開発者にとっては詳しい仕様こそが重要になります。

このように、情報の受け手によって、どのような粒度で情報を求めているかが異なります。
受け手にとって粒度が細かすぎる場合は知りたい情報を誤解なく手早く知ることが困難になりますし、粗すぎる場合は知りたい情報を十分に知ることができなくなります。
ドキュメントを作成する際は、情報の受け手が誰であるかを想像して、適切な粒度で情報を提供することが重要になります。


いかがでしたでしょうか。

今回は、私がドキュメントを書く時に意識していることを列挙してみました。
ドキュメントはチームで仕事を進めていく上では欠かせないものですし、未来の自分が内容を思い出すためにドキュメントを読むこともあるので、今までドキュメントを重視してこなかった方は是非意識して書いてみてください。

なお、Slackのようなチャットツールでの会話でも、この記事で挙げたドキュメント作成のスキルを活かすことができます。
特に昨今はテレワークが普及しており、チャットツールでの会話も増えているかと思いますので、チャットでの意思疎通がスムーズにできるだけでも仕事ができる人だとみなされやすくなると思います。


アジャイル開発の概要

プロセスモデルの一つとして、「アジャイル開発」というものがあります。
ウォーターフォールモデルと比較すると新しいモデルです。

アジャイル開発はその名の通り迅速に開発を行うもので、短い期間(数週間~1ヶ月程度)毎にユーザにとって重要な機能から順番にリリースを行います。
一つの期間はイテレーションと呼ばれ、計画・設計・実装・テストがこの期間の間に行われます。
このように開発を行うことで、ユーザは少ない期間・コストで重要な機能を使用することができるようになります。ユーザの要求の変更にもいち早く対応することができます。
また、システムを実際に使うと新たな要望が浮かぶものなのですが、システムを早い段階で手に取ることができるので新たな要望を早く出すことができます。仮に、せっかくリリースした機能がユーザに響くものでなかったとしても、その問題に少ない期間・コストで気付き、軌道修正することができます。
これらの利点により、重厚長大なウォーターフォールモデルを採用した場合に比べて、ビジネス上で優位に立つことができるようになります。
(特にスタートアップ企業にとってはこれらの利点が重要)

しかし、アジャイル開発はユーザの要望が頻繁に変わる小規模システムの開発には向くものの、要望が固定されているミッションクリティカルな大規模システムの開発には向かないとされています。
アジャイル開発ではシステムを小出しで開発するので、システム全体の整合性や最終製品の品質を上手く管理しないと、システムの品質が低下する問題やシステムのスケーラビリティが損なわれる問題が発生してしまいます。
そのため、教科書的には、要望が固定されているミッションクリティカルな大規模システムの開発はウォーターフォールモデルの方が向いているとされています。

ユーザーの要件を満たすプロダクトを迅速に開発するためには、それを実現するための手法や考え方が必要です。
アジャイル開発を実現するための手法、またアジャイル開発と親和性の高い考え方としては、以下のようなものがあります。

・アジャイルソフトウェア開発宣言

アジャイル開発の価値観を端的に言い表した宣言である。
原文はこちら。

・エクストリームプログラミング(XP)

迅速にプログラミングを行うための手法。
リファクタリング(保守性を高めるためのコード見直し)、ペアプログラミング(一人がコーディング、もう一人がリアルタイムにコーディングを見ることで、即座にレビュー・知識共有を行う)、テスト駆動開発(テストケース・テストコードを先に設定してからプログラミングを行う手法で、テスト自動化が伴う場合が多い)、等により実現する。

・プロトタイピング

ユーザからのフィードバックを早期に得るために試作品を作成して提供する。
試作品はコーディングして作成するとは限らず、紙芝居のような形でコンセプトを伝えるペーパープロトタイピングと呼ばれる手法もある。

・スクラム

チーム一体となってプロジェクトを遂行して行くことに重点を置くプロセスモデル。
デイリースクラム(始業時に今日の予定と問題点を共有する)、プロダクトバックログ(システムの要求一覧)、スプリントバックログ(イテレーション内で対応する要求一覧)、イテレーション、スプリントレビュー(イテレーション内で開発した機能のユーザとのレビュー)、ふりかえり(イテレーション終了時の改善点の共有)等により実現する。

・バーンダウンチャート

縦軸に「残作業量」、横軸に「時間」を割り当て、残作業量を折れ線グラフにより記述したチャート。
ガントチャート等と比べて、プロジェクトの進捗状況をいち早く把握することができる。
誰もが見える場所に張り出すと効果が高い。

・リーン生産方式

トヨタ生産方式を元に編み出された方式。
開発工程におけるムダを排除することを目的として、製品および開発工程の全体にわたって、トータルコストを系統的に減らそうとするのが狙い。「ムダをなくせ(顧客に価値を与えない作業を無くす)」「学習を強化せよ(反復型開発)」「決断を遅らせよ(状況の変化に合わせた決断)」「できる限り早く出荷せよ(機会損失防止)」「チームに権限を(チームの手で最良のプロセスを採用)」「摺り合わせて作り込め(ユーザとのトライ&エラーの繰り返し)」「全体を見よ(全体最適化)」という7つの原則によって成り立っている。

・チケット駆動開発

スプリントバックログを約2~3時間のタスクである「チケット」に分割し、チケットを管理することで、メンバーの作業把握と成果物の更新理由の把握を容易にする。
チケットによる管理を行う場合は、チケットの完了(Done)の定義を明確にし、完了基準を満たすまでは完了とみなさないようにすることも重要である。

・ストーリーポイント

案件の規模や複雑性を「ストーリーポイント」と呼ばれる直感的・相対的な基準で測ることにより、俯瞰的な視点で直感的に迅速に見積もりを行う。


いかがでしたでしょうか。

日本ではアジャイル開発はあまり普及しておらず、アジャイル開発を採用しているプロジェクトには巡り合えないかもしれませんが、それでも顧客の要望に沿ったシステム開発を行う必要があることには変わりありません。
そのため、ウォーターフォールの開発だとしても、アジャイル開発の手法や考え方は部分的にでも取り入れることは有効ですし、実際に部分的に取り入れているプロジェクトも少なくありません。
開発者としても、アジャイル開発の手法について知っておくことに越したことは無いでしょう。

リーダーシップ状況論の理論と実践

今回の記事では、リーダーシップの理論と、IT業界における実践について述べていきます。
情報処理技術者試験対策としては理論を知っていれば良いですが、実際に現場で活かす上で役に立つ情報(経験則)も書いていきます。


【理論】

組織とリーダシップの関係は下記図のようになるとされています。
組織が成熟するにつれて、有効なリーダーシップの取り方がa→b→c→dに移行するとされています。

aは組織の発足時の段階です。
構成員のスキルも自主性も不足しているため、仕事関係本位でリーダー自ら先頭に立ってチームを引っ張る必要があります。
スポーツに例えると「選手をきちんと管理することが勝つための条件だ。」という状態です。

bはaから成熟度が進み、構成員がスキルを身に付け始めた頃です。
構成員を引っ張るだけでなく、リーダーが1から10まで指示しなくてもチームがパフォーマンスを発揮できるようにするために、構成員の自主性を育て大切にすることも考える必要が出てきます。言い換えると、仕事関係本位のリーダーシップだけでなく人間関係本位のリーダーシップも強めていくことが有効になります。
スポーツに例えると、「うるさく言うのも半分くらいで勝てるようになってきた。」という状態です。

cは更に成熟度が進み、構成員が自主性を身に付けはじめ、自分の仕事を自ら見つけ、必要なスキルを自ら身に付けるようになり始める段階です。
この段階になると、仕事本位のリーダーシップを取る必要性が薄くなり、構成員の自主性を維持するための人間関係本位のリーダーシップを前面に押し出すことが有効になります。
スポーツに例えると、「勝つためには選手と十分に話し合って戦略を作ることだ。」という状態です。

dは成熟度が最も進んだ段階です。
各々の構成員が自らリーダーシップを取るようになるので、リーダーは人間関係本位のリーダーシップも弱め、構成員に任せて見守るというリーダーシップの取り方が有効になります。
スポーツに例えると、「勝つためには選手に戦術の立案と実行を任せることだ。」という状態です。


【実践】

IT業界の開発の現場では、具体的に以下のことが言えます。

最も成熟度が低いaの状態というのは、構成員のスキルも自主性も不足している状態のことです。もう少し具体的に言うと、成果を出すために何をすれば良いのかわからない状態や、そもそも成果を出すための意欲が低い状態のことを指します。
現場としては、全くの新規プロジェクトの現場や、前任者が離脱して残された構成員が右往左往している現場、組織再編や短納期化等でこれまで頼っていた社内プロセスを見直さざるを得なくなった現場等が、これに該当するでしょう。
この状態の組織では、十分な能力や経験を持つ者がリーダーとなり、リーダー主導で作業計画や品質強化を行う必要がありますし、リーダー自ら設計や開発に関わる必要もあります。炎上プロジェクトの火消し役、というのもここに含まれます。
リーダーのワンマンプレイのようになるので人間関係に軋轢が生じることもありますが、この段階では副作用としてある程度受け入れざるを得ません

成熟度が少し高くなり、bの状態になると、構成員にスキルが身に付き始めます。この状態になると、末端の細かい判断や作業は構成員自らできるようになります。
現場で言うと、混沌とした時期を乗り越え、プロセスが正常に回り始めた現場と言うことができると思います。
この状態になると、構成員がプロセスに沿って自ら仕事ができるようになります。リーダーは、構成員がプロセスに沿って仕事ができるようにサポートするのが主な仕事になります。
まだまだリーダー自ら動かなければならない場面も多いですが、このあたりからは構成員に任せる仕事の範囲を徐々に広げ、構成員と良い人間関係を築くことも考える必要が出てきます。あまり長い間リーダーが前面に出ていると、構成員の自主性が育つのを阻害し、次の成熟度へ進むのが難しくなります。

成熟度が更に高くなり、cの状態になると、構成員に自主性が育ち、自ら考えられるようになります。
この段階になると、重厚長大なプロセスに頼らずとも、各々の構成員が適切な判断をするようになります。不測の事態が発生した時にも対応が楽になりますし、そもそも不測の事態が発生しないように各々の構成員が手を打つようになります。
この状態になると、これまでリーダーが行っていたような判断を構成員自ら行うようになりますし、その上で足りないスキルがあれば構成員自ら努力して身に付けるようになります。
この段階になれば、リーダー自ら動く必要はなくなります。構成員が気持ちよく仕事ができるように(このリーダーの下で働きたいと思ってもらえるように)、人間関係のメンテナンスに注力するのが有効になります。

成熟度が最高に高まり、dの状態になると、構成員自らリーダーシップを取るようになります。
各々の構成員が適切な判断をするようになるだけでなく、リーダーのように組織作りといったことも考えるようになります。
この段階に到達すると、リーダーは人間関係のメンテナンスをする必要もなくなります。
リーダーの仕事は、構成員に任せて見守るというものになります。この状態であれば、リーダーが更に上の立場に昇進したとしても、現場に問題は発生しないでしょう。


いかがでしたでしょうか。

今回は、リーダーシップ状況論について、情報処理技術者試験で問われることだけでなく、より実践的なことを経験則から補記しました。
実践的なことも知っていると、記憶が定着しやすくなりますし、知識も活かしやすくなると思います。

ソースコード修正の競合と統合

複数の案件が同時に動いており、1つのソースコードを複数の案件で修正する場合、ソースコード修正の競合(コンフリクト)の統合(マージ、差分取り込み)が必要になります。
統合には、全体のロジックの整合性や案件のリリース時期の違いを考慮する必要があり、機械的に判断できない場合もあるので、最終的には人の手で判断し統合する必要があります。


例えば、商品の販売価格を計算する以下のソースコードがあるとします。
(今回はjavaのソースコードであると仮定します)

・修正前ソース

このソースコードについて、下記3案件で修正するものとします。
案件1.消費税増税対応(3ヶ月後リリース)
案件2.店舗毎セール対応(3ヶ月後リリース)
案件3.タイムセール対応(6ヶ月後リリース)

3案件の修正後ソースはそれぞれ以下の通りとします。

・案件1

・案件2

・案件3

リリースすることを考えると、以下の2段階に分けてソースコードの修正を統合する必要があります。

・3ヶ月後を想定

 案件1と案件2を統合

・6ヶ月後を想定

 3ヶ月後のソースと案件3を統合


案件1と案件2の統合は容易です。
以下のように機械的に統合することができます。

・3ヶ月後のソース

対して、3ヶ月後のソースと案件3を統合は機械的に行うことができません。
修正ポイント2-5と修正ポイント3-4は同じ個所を修正しているので、両方の修正が反映されるようにソースを書き変えなければなりません。
そもそも、修正ポイント2-3でコンストラクタが追加になっているため、新たに追加したコンストラクタに対しても案件3の内容を反映しなければなりません。
よって、6ヶ月後のソースは以下のようになります。

・6ヶ月後のソース


なお、バージョン管理システムのGitのブランチやマージの機能を使えば、これらの統合の作業が楽になります。
機械的に統合できる箇所は自動で統合できますし、機械的に統合できないブランチについても以下のような方法を用いて比較的容易に統合することができます。
(具体的な操作方法は省略します。操作方法はWebで調べられるので、必要に応じて調べると良いでしょう。)

  • Gitが出力した差分を見てエディタで編集
  • 競合の原因となったコミットを取り消しコミットし直し
  • マスター管理しているブランチを元に新たにブランチを作り直し、作り直したブランチに対して同じ修正を行う

いかがでしたでしょうか。

「ソースコード修正の競合と統合」と言うと、Gitのテクニックが求められるように思われるかもしれません。
しかし、Gitの操作が多少不得手でも、何をしなければならないのかが理解できていれば、多少手間取ったり非効率になったりすることはあっても、最終的には問題無く修正作業を行うことができます。
まずは、何をしなければならないのかを理解することに努めましょう。
(それを理解する上で、今回の記事が参考になれば幸いです)

障害の発生原因の切り分けのポイント

テストや本番運用で障害が発生した場合、既知の障害等で原因が明らかな場合を除き、対応のために原因を調査する必要があります。
原因を調査する上ではどこに原因があるのかの切り分けが必要になります。
以下では、切り分け作業を行う上でのポイントを順を追って説明します。

1.障害が発生した状況を保全する

障害が発生したデータやその状況を記録したログは後の調査で使いますので、誤って更新したり削除したりしないように保全する必要があります。
テスト中であればそのデータを用いたテストは中断する必要がありますし、場合によってはコピーして別の場所に補完する必要があります。

2.期待される値との比較を行う

データやログを見て、設計上期待される値と異なる点を探していきます。
コーディングの単純な誤りであれば、大抵の場合は、データが期待値と異なるようになった箇所やログの出力内容から原因を特定できます。
場合によっては、その期待値自体が合っているのかどうか、設計や要件の確認・再検討が必要になる場合もあります。

3.障害発生手順を確立させる

ログの出力内容が不足している場合や原因が込み入っている場合は、データやログを見ただけでは原因がわからない場合があります。
その場合は、障害が発生した時と同じ手順で障害の再現を確認します。
障害が再現すれば、障害を発生させる手順が確立されたということになります。
厄介なのは障害が再現しなかった場合で、一意キー(顧客番号や受付番号の類)が障害発生時と異なることに注目して一意キーと結びつくデータを洗い出す、ランダムに処理が変わる箇所がないか(乱数を使っている箇所や振り分け先がランダムなロードバランサー等に注目する)、という観点で再現しなかった理由を調査し、障害発生手順を確立させます。
どうしても確立できない場合は、ハード障害である可能性を視野に、障害発生時の状況をまとめてハードウェアを提供するベンダーに確認する、というアクションを起こす必要がある場合もあります。
(私の経験上、「太陽フレアでビットが入れ替わってしまった」という冗談のような原因を告げられたこともあります)

4.再現手順を元に開発環境で原因調査を行う

再現手順が確立したら、開発環境で再現手順を試し、徐々に原因を絞り込んでいきます。
もし環境を変えたことで障害が再現しなくなった場合、環境問題である可能性が出てきます。
(例えば、マスタデータの不備、機器の構成の違いに起因する問題、等)
障害が再現する場合、開発環境ではデバッグを入れて変数の内容を表示することができますので、それをログの代わりにして原因調査を進めることができます。
また、開発環境ではデータも自由に書き変えられますので、データを少しずつ書き変えて挙動を確かめることでも、原因調査を進められます。


いかがでしたでしょうか。

障害調査は経験則で語られることが多いので、私自身の経験を基に文章にしてみました。
もし参考になれば幸いです。