クリアコードの結城です。
この度Supershipさまからご依頼を頂き、先方のグループ各社内の新入社員の方々を対象とした研修の一環として、「既存のコードを変更するノウハウ」を学ぶワークショップを2018年9月に開催しました。 この記事では研修の実施に至った背景事情と、実際に研修の中でお伝えした内容をご紹介します。
「社会人レベルのコードを書けるようになる」とはどういう事か?
本件は元々、Supershipさまのグループ各社横断で行われる新人研修の一環で、「社会人レベルのコードを書けるようになる事」をテーマに1日かけて行う特別プログラムとしてご相談を頂きました。
そこでまずは、「社会人レベルのコードを書ける」とはどういう事か、「学生レベル」や「趣味レベル」との違いはどこにあるのかという事から考え直してみることにしました。 その結果、以下のようなトピックが挙がりました。
-
「チームでプログラムを開発する人」としての能力
-
既存のコードを自然な形(周囲のコードに馴染む形)で変更する能力。
-
発生した問題の原因を調べる能力。
-
他の人が見て分かりやすい(他の人がメンテナンスしやすい、他の人が調査しやすい)コードを書く能力。
-
テストしやすいコードを書く能力。
-
-
「ビジネスマン」としての能力。
-
納期に間に合わせる能力。
-
予算(想定工数)の範囲内に収める能力。
-
「納期が厳しくてメンテナンス性を諦めないといけない」のような二律背反の状況で、物事の優先順位を付けて判断する能力。
-
ただ、研修の実施日程を考慮すると、これら全てを扱うことはできません。 そこでご依頼主さまと相談し、この中で特に「既存のコードを自然な形(周囲のコードに馴染む形)で変更する」という話題に焦点を当てた内容とする事にしました。
課題の選定
研修にあたっては「課題のための課題」は避けたいという思いがありました。やるなら、そこまでに実施された研修の内容を踏まえて、なるべく日常的に実プロダクトで行う事に近い事をしてもらうのが良いはずです。
ただ、ご依頼主さまの会社内の機密情報に基づく内容とした場合、資料の二次利用は困難になります。 当社の期待としては「成果をフリーソフトウェアにしたい」「実施した事の内容を公開して、同様の事でお悩みの会社さまに見付けていただく」という事があるため、できれば公開可能な情報のみに基づく資料としたい所でした。
事前に伺った情報では、ご依頼主さまの事業においてRuby on Rails の大規模なコードベースを長期わたって運用されているとの事でした。 実際の業務では、そのようなプロダクトに対し変更を行っていく機会がそれなりに見込まれます。 そこで、著名な公開プロジェクトの中でも条件が近い物として、Redmineを題材にすることにしました。
また、Redmineに対してどのような変更をするかに関しても、題材に使いやすそうな規模の既知の要望が見つかりました。 目標を「この要望を実現するパッチを作る事」に置けば、既存の大きな実装に対して変更を行う際の一通りの作業を体験できるはずですし、進度次第では成果をそのまま公開でき、ご依頼主さまの会社自体の社外向けのアピールにも繋がります。
この要望については、既に同様の事を実現するプラグインが存在しているというのも好都合でした。 実装が難しい部分はプラグイン自体のコードをそのまま流用する事で手間を省けるため、「既存のコードに馴染むように機能を組み込む」という点に集中して取り組めるはずです。
以上の事を踏まえ、研修当日にソースコードのダウンロードやHTTPサーバーのセットアップ等の本質的でない部分で手間取る事がないよう、必要なソフトウェアやソースコードなど一式を用意した状態のVagrant Boxを準備し、研修当日に臨みました。
座学:既存のコードを変更する時の心得
当日の研修開始直後からいきなり「さあ、やってみましょう」で作業を始めてしまうと、参加者の皆さんが途方に暮れてしまうのは目に見えています。 そこで、研修当日の内容は2部構成とし、まず最初に「既存のコードに変更を行う」という作業の一般的な流れを説明する座学の時間を設け、実作業を伴う演習はその後に行う事にしました。
ここで用いたプレゼンテーション資料はgitlab.com上のリポジトリにて公開しています。 また、スライドはSpeaker Deckでも見る事ができます。
新機能の追加にせよ不具合の修正にせよ、継続的に運用されるサービスに関わる開発業務のかなりの部分は「既存のコードの変更」となります。
既存のコードに合わせた変更を行う・既存のコードに馴染むコードを書くためには、既存のコードを読んで内容を把握する必要があります。 しかし、膨大な量のコードを頭から1行ずつ読んでいくというのは非現実的です。 業務でコードを書く人は常に時間に追い立てられているなので、見るべきポイントを押さえて少しでも効率よくコードを読みたいものでしょう。
そのため、座学の前半では「どんな情報を読み取るためにコードを読むのか」という点に焦点を当てて、「コーディングスタイル」「設計方針」「背景事情」のそれぞれを読み取るために注目するべきポイントやコードの読み進め方を説明しました。
座学の後半では、コードを読んで得た情報を元にして変更を行う時の具体的な流れとして、「変更計画の立て方」「(TDDでの)自動テストの書き方」「自動テストをしやすい形での実装の仕方」などについても説明しました。 ただ、前半の話題に比べるとこれらの点は一般化が難しく、一般的に語れるレベルの話となると抽象度が高すぎて研修の趣旨にそぐわなくなると予想されたため、後半の説明は軽めにして、なるべく長い時間を実際にコードと向き合う演習に充てられるようにする事にしました。
演習:Railsアプリケーションへの機能追加
休憩を兼ねた昼食を挟んだ後は、研修の第2部であり本題となる演習の時間としました。
教材のセットアップ
最初にgitlab.com上のリポジトリで公開されている資料を皆さんの手元にcloneしていただき、記載された手順に則って教材用の環境をセットアップしていただきましたが、ここで1つ多くの方が躓かれていた点がありました。
この手順でセットアップした環境はVagrant Box(実体はVirtualBoxの仮想マシン)となり、その中に置かれたファイルを編集するためにはSSHでリモートログインするなどの手順を踏む必要があります。 今回の研修に参加された方々のほとんどは、それまでの研修ではVisual Studio CodeやAtomなどのテキストエディタを使われていたことから、ここで「VS CodeやAtomでVagrant上のファイルを閲覧・編集する」という事を実現するための設定が必要となっていました。
この時は、手間取っていた人には既にうまく行っていた人が情報を共有するという形で相互に助け合ってもらい、本題に取り組む段階に無事進む事ができました。
コードの読解と設計の把握、実際の変更
準備が整った事でようやく本題に着手です。
前述の通り、今回の課題はRedmineでコメントの変更があった時にメールで通知できるようにするという物です。 これについて、とりあえずソースコードを検索して読んでみる人、送信されるメールのテンプレートを起点に探してみる人、怪しそうな所をとりあえず変更してみる人、同様の事を実現する既存のプラグインを実際に組み込んでその動作の様子を追う人など、各人各様のアプローチで課題に取り組まれている様子が窺えました。
ただ、中には、いきなり大規模のソースコードに触れた事で混乱が生じたためか、どこから切り崩していけばよいか判断に迷って途方に暮れている人も見られました。 そのような場合の取り組み方について座学でいくつか方法を紹介したつもりではあったのですが、知識として知ったという事と、それを実際の場面に適用できるという事の間には隔たりがあるのかもしれません。 そのため、室内を巡回しながら、戸惑っている様子が見られた方には個別に声をかけて、「座学で述べたこの話をここで活かすと、こういう風に調べていける」という補足説明をしていく事にしました。
そうこうするうちに実装案を思いつく所に到達した人も現れてきて、講師が意見を求められたため確認した所、Controllerのレイヤで目的を実現するという方針を取っていました。 このアプローチは、目的とする機能を実現できているという点は良いのですが、Redmineの他の部分に自然に馴染むかという点では、違和感が大きいというのが講師視点での印象でした。 というのも、Redmineには既に「チケット自体の変更をメールで通知する」という仕組みが実装されており、それらとはかなり異なるアプローチでの実装と言えます。 将来的にRedmineプロジェクトに変更を取り込んでもらうという場面までを考慮に入れると、このように「既存の実装に馴染まない」「収まりの悪い」変更内容は、マージに至らない事が多々あります。 そのため、その人に対してはアプローチの再検討を試みてはどうかと講師から促しました。
実装の進度には受講者同士の間で差が生じていたため、進度が高い人には適宜、他の詰まっている人にノウハウや情報を共有するという事もしてもらいました。 何かを自分で人に説明してみるというのは、説明対象についての理解を深める上で非常に効果的です。 これは、筆者がワークショップに関わる際に意識している点の1つです。
より小さい規模での実践の機会も
研修の実施中、思いがけない出来事もありました。 参考になる実装例として紹介した既存のプラグインの動作を確認していた人が、その動作に奇妙な点があると気付いたので深掘りしてみた所、なんとプラグインの方に不具合があるという事が明らかになったのです。
対象とするソフトウェアの規模的には想定から外れますが、この問題に取り組む事は、「既存のソフトウェアに変更を加える」という本旨の部分では研修の趣旨に沿った物である言えます。 そのため、講師の側で判断して、その人には当該プラグインに対するフィードバックを行ってみてもらう事にしました。
こちらは、最終的にはプルリクエストの形で変更を提案し、いくつかのやりとりを経て微修正後に無事マージされるに至っています。
成果の報告とまとめ
研修は1日の予定でしたが、当日に台風が接近しており帰宅困難となる恐れがあったため、後半の演習を途中で打ち切り、日を改めて続きを実施しました。 初日に引き続いての作業の後、研修の最後の30分はそこまでの成果の報告会としました。
報告会では複数の参加者から、既存の実装を読んでメソッドの呼び出し元を辿り処理の流れを追う事の意義を実感したという声が聞かれました。
Railsというフレームワーク自体の理解が浅かった参加者からは、メソッドの呼び出し関係を辿るのに苦労したという声も聞かれました。 フレームワークを使ったアプリケーションの処理を追う上では、そのフレームワークの一般的な作法の知識が必要になります。基本的にはフレームワーク自体のチュートリアルを一通り実施して、そのフレームワークの作法に触れた上で、実際に作られたプロダクトに触っていくのが望ましいでしょう。
メールの送信に関わっていそうな部分を当てずっぽうで変更してみたものの期待した結果を得られず、後になってみると見当違いの所ばかりを見てしまっていた、という反省の声もありました。コードの全体を把握するのは時間がかかりすぎるという状況においては、ある程度は推測に基づいて調査範囲を絞り込む必要がありますが、完全な当てずっぽうでは、当たるか当たらないかは運次第になってしまいます。仮説を立てる際は、「ここで表示されているメッセージがここで定義されているので」や「必要な処理がここで呼ばれているので」のように、その仮説の根拠を説明できるようにしておくと良いでしょう。
進捗が良かった参加者の中には、処理を追ってControllerの該当部分を特定できたという人(プラグインを参考に処理を組み込む方法を検討している所で時間切れになった)や、実際に動作してコメントの変更内容の差分がメール送信される所にまで到達した人もいました。この方々には思考の整理も兼ねて、どのように調査してその実装に至ったのかについて他の参加者に情報を共有する事をお薦めしました。
また、成果発表の時間の最後には模範解答例として、講師がこの作業を行った際の手順もご紹介しました。この時は担当した講師にRailsとRedmineの知見があったため、クラスの定義箇所に見当を付けて探すなど、効率よく調査を行えたケースとなっていました。
今回の研修で使用した課題そのものは一般に公開可能な内容のため、研修の終了後に自主的な取り組みとして、以下のような事にも挑戦してみて頂きたい旨ご案内しました。
-
差分を出力する処理について、Redmine独自の処理と、プラグインが使っているGemのどちらを使うべきか(あるいは全く別の選択肢を取るべきか)の検討。
-
通知設定に基づいて、自分自身の変更を送らないようにする方法の検討。
-
実際にRedmineプロジェクトの当該チケットにパッチを提出してみる。
まとめ
以上、Supershipさまにて実施した「既存のコードを変更するノウハウ」を学ぶ研修の様子についてご報告しました。
当社はフリーソフトウェアとビジネスの両立という理念に則り、フリーソフトウェア・OSSの開発に長く関わる中で培ってきた技術的な知見をビジネスに繋げる形で、開発やテクニカルサポートなどの業務を行っています。 その中には「知見そのものを伝える事」も含まれており、過去にはSEゼミのリーダブルコード勉強会やアジャイルアカデミー「実践リーダブルコード」などのようなワークショップ形式のイベントの開催に度々携わってきました。また、テクニカルサポートやコンサルティングのような形で顧客企業内のOSS推進の取り組みを支援させて頂いた事例もあります。 今回の研修も、その流れの中にある事例の1つと位置付ける事ができます。
本件の研修と同内容の研修や、その他のフリーソフトウェア・OSSの開発に実際に関わる形での研修を社内で実施したいとお考えの会社さまは、ぜひお問い合わせフォームよりお問い合わせ下さい。