入社してからの2年間を振り返る

2022年4月に入社してから今年で2年が経ったので振り返ります。

新人研修

SIer企業に入社後、4月~7月の約3ヶ月間は新人研修をやっていました。4月中はPCのセットアップや、マナーやコンプライアンス系の講座をe-learningで勉強しており、時間に余裕があったため初任給でクロスカブ50を購入して、週末は横浜周辺をツーリングするのを趣味にしていました。

この時期に、大学院時代にやっていたデータ解析のアルバイト先から副業として続けてほしいと打診されたため副業をはじめることになりました。個人事業主としての業務(請求書の発行や経費精算)もまったく分からなかったので最初は苦労した記憶が…。振り返えってみると早めにfreeeとかを使い始めればよかったと思う。

6月~7月はJavaの演習をしていました。初回に受けさせられるレベル分けテストで上級クラスになりましたが、Javaに関する知識は大学の講義で使った程度だったので不安な気持ちのまま演習に突入しました。ところが内容は結構平易で、未経験の人でもついていけるように配慮されていた印象でした。演習クラスの中ではプログラミングができる方だったので、正直天狗になっていたところがありましたね。しかし8月からOJTに配属されるとすぐにその幻想は打ち砕かれることに…。

 

OJT配属~組織について意識する

8月から既存システムの運用保守という内容のOJTに配属され、名古屋に引っ越すことになりました。既存とはいうものの、システムには新しさがありましたし、規模の大きさ・身近さから、やりがいを感じながら携わっていた記憶があります。

OJT配属にあたってまず最初に、自分の組織的な立ち位置が把握できなかったことをよく覚えています。

  • 案件を持っている部署と自分の所属する部署は異なっており、自分は案件を持つ部署へデリバリーされている
  • 案件のチームメンバーにもプロパーや協力会社といった出自の異なるメンバーがいる

こういったよくある構造についても、組織の全体像を持たない新人にとっては把握しづらいものだったのだなぁと思います。こういうのは新人のうちに素直に聞いておいたほうが良いですね。

 

理解できない会議では何を得るべきなのか?

OJTに配属されるとすぐに業務の定例会議に招待されました。そこでは聞き慣れないキーワードが飛び交っており、最初の頃はほとんど理解できていなかったと思います。会議の内容も開発・運用状況に応じて変わっていくため、業務知識について理解の浅い新人では内容を理解するのが難しいのは当然といえます。

そんな定例会議ですが新人が出ることの意味はいくつかあるように思います。

  1. どのような会議が行われているか把握する
  2. 各種の話題について理解を深める
  3. 会議を聴くための技術を養う

2については前述の通り新人がすぐに理解するのは難しいですが、1や3であれば新人でも会議に参加する価値があります。とくに3については自分にとって得るものが多かったです。

たとえば各チームがそれぞれの開発の進捗を報告する場であれば、以下に挙げるように会議の内容によらない普遍的な聴き方の態度があると思います。

  • 誰がどのチームの代表として話しているのか?
  • 各チームの開発アイテムは何か?
  • いま話題に上がっているのは、どのチームの開発アイテムか?
  • 全チームに影響のある話題なのか?
  • いまの話題をどの程度の温度感で話しているのか?(深刻なのか軽傷なのか)
  • 直近について話しているのか?今後について話しているのか?
  • 自分の所属するチームはどのチームと関わりが深いか?
  • 関わりの深いチームの進捗が遅れている場合、自分のチームに影響はあるのか?
  • 逆に自分のチームが遅れている場合、どこに迷惑がかかるのか?
  • 遅れているアイテムがある場合、解決策はあるのか?
  • 解決策は恒久的なのか、対症療法なのか?
  • また問題は起きないか?起きることが予想される場合は、それについて対処可能か?
  • ケアすべきチームやメンバーはいないか?
  • いま議論されている話題について、見落とされている注意点はないか?
  • etc...

こうした聴き方は新人の頃を振り返ると圧倒的に不足していた気がしますねー…。

 

ヤクの毛刈り

ある程度大規模なシステムを扱うとなると、軽微な修正を行うにしても大量の承認プロセスが必要になることを身をもって知ることになりました。たとえばライブラリのバージョンアップをするにしても、既に本番環境が稼働しているものであれば完了までにおおよそ次のような作業が必要になります。

  1. ライブラリのバージョンを修正
  2. レビュー
  3. 承認&マージ
  4. 開発環境への配信
  5. 動作確認
  6. ドキュメントに記載されている開発環境のアプリバージョンを最新化する
  7. 検証環境ブランチへのプルリクエス
  8. レビュー
  9. 承認&マージ
  10. 動作確認
  11. ドキュメントに記載されている検証環境のアプリバージョンを最新化する
  12. 本番環境への配信予定をチケットで発行し、承認の依頼をする
  13. 本番環境への配信の承認
  14. 実行役と監視役の2人体制で、各国の本番環境へ配信(国ごとに配信可能な時間が異なる場合がある)

実際はこれらの承認プロセスに加え、ライブラリのバージョンアップに伴うデグレーションなどの副次的な問題が発生することもあります。こうした本来の問題解決(ライブラリのバージョンアップ)に伴う副次的な問題解決のことを「ヤクの毛刈り」と呼んだりしますが、何度もヤクの毛刈りをやっていると、次第に見積もりに対して慎重になっていくようになりました。たかがライブラリのバージョンアップで1スプリントかかるという見積もりはバカげて見えるかもしれませんが、次第に真っ当な気もしてくるんですよね。

 

少し慣れてきたところで日々の業務を俯瞰してみる(偶有的複雑性と本質的複雑性を区別する)

会議の場数を踏み、ヤクの毛を刈りまくったところでようやく少しだけ運用業務に慣れてきた感じがしました。しかし慣れてきたとはいえ時間や業務に追われる日々で、それなりに残業をしていた思い出があります。この頃に一つのヒントになったのが、偶有的複雑性と本質的複雑性を区別することです。

本質的複雑性とは解決しようとしている問題の本質的な難しさのことで、偶有的複雑性は問題解決のために選んだツールやプロセスによって生じた副次的な問題による難しさのことです。例えばC++を使って素因数分解をO(log n)で求めようとすることは本質的に困難ですが、C++を使っている際に生じたメモリ管理によるバグ解決はC++というツールを選んだことによる偶有的複雑性です。C++ではなくガベージコレクションのあるプログラミング言語を使っていればこのような問題は起こらないからです。

OJTに戻って、日々の業務で多くの時間を割いている原因を考えてみると偶有的複雑性によるもののほうが多いような気がします。前述した承認プロセスが肥大化する原因は、品質を担保する理由がコードレビューや動作確認に任せられているせいであることがわかります。これらは定義からわかるように選択したツールやプロセスに問題があるので、ツールやプロセスを変えれば解決できる可能性があります。

たとえば信頼のおける自動テストが走っている前提であれば、ライブラリのバージョンアップ程度でレビューに時間をかける必要もありませんし、手動の動作確認で時間をかける必要もありません。自動テストが成功したあとにCICDでドキュメントを最新化したり、次のレベルの環境へのプルリクエスト作成やチケット作成なども自動化できるでしょう(自分の担当したシステムについては自動テストはありましたが、失敗していることも多く、信頼されていなかったようです。せっかく自動テストがあるのにテストが腐っていてはもったいないなぁと常々思っていました)。

経験が増えてくると徐々にこうした改善方法について考えられるようになってきて、実際に改善案を提案することでプロセスを改善していくことができました。また、改善案を提案するということにはもう一つ大事な要素が隠れています。それは自分のボールを他人のボールにするということです。問題点や解決策を整理することができれば、自分の負担を人と一緒に解決することができます。あたりまえのように思えるかもしれませんが、新人の頃はタスクをかかえてしまいがちだったので、ボールを持ちすぎないという発想は自分にとって大事でした。こうした観点を身に着けてから、時間に追われることが減っていった記憶があります。

 

開発業務への移行

OJTは8月から翌年の3月までで、一旦OJTとしては区切りがつき、4月から同システムの次世代バージョンの開発案件に配属されることになりました。開発体制としては大規模スクラムで、チームが複数あり、各チームに開発アイテムを分けたマイクロサービスアーキテクチャをベースにした体制です。

最初の1ヶ月はチームの開発アイテムや開発手順、スクラムイベントなどを把握することに費やしました。2ヶ月目からは単独で開発に入るようになっていったのですが、まだまだ自分を含めチーム全体として技術要素についての理解が浅く、改善すべき点が多くありました。主に使われている言語はJava(Spring)だったので言語理解については問題はなかったのですが、テストフレームワーク(Junit, karate)やインフラ構築(terraform), クラウド(AWS)については習熟度がバラバラで、チームの技術レベルに偏りがあったと思います。

こうした技術レベルの差を埋めるために、いろいろな本を読んだりしていたのですが、今振り返るとベクトルの違う努力だったと思うものも少なくありません。

例えばクリーンアーキテクチャについて理解を深めても(既にアーキテクチャは別のものが採用されていたため)プロジェクトへのインパクトは小さいですし、どちらかというとテストフレームワークについて理解を深めたほうが初期の段階からアプリの品質を高められて手戻りが少なかったでしょう。terraformについてもモジュール化に関する理解がもう少し深ければ、全アプリをモノリスのようなmain.tfにまとめたりするといった所業に早めに喝をいれていたでしょう。

振り返ると技術を学ぶにしても、開発段階ごとに優先度があるなぁといった印象です。個人的には品質やコードのクリーンさについては、初期の段階のうちに徹底しておいたほうがあとが楽になるので、いずれ残業して問題解決しなければならないのであれば、初期段階で残業をして品質を高めておきたい気持ちがあります。初期段階ではまだ手探りなこともあり、品質的に不十分なコードでも良しとされがちですが、そのコードはやがて村の風習となり、呪いになります。

また、プロジェクトにもよりますが、開発中期~後期ごろになってくると別の仕向けを追加したり、DR環境を作ったり、負荷試験をしたり、ペネトレしたりするのでインフラ関連(とくにterraform)について、ある程度いろいろできるようになっていたほうが仕事は楽だった印象があります。

 

副業と本業の両立

最初は無限に学ぶことがあるように見えたプロジェクトも、数ヶ月も経てばある程度手癖でこなせるようになってきました。この頃から自分の中に、ある程度確信を持った自信が湧いてきた気がします。新人研修の頃のような虚勢ではなく、どのプロジェクトに行ってもそこそここなせるだろうという、経験に裏付けされた確信です。

精神的にも時間的にも余裕を持てるようになってくると、さらに別の挑戦をしたくなってくるのが自分の性のようです。本業については先述のシステム開発だけでなく、社内で募集のかかっていた別案件に手を上げてスクラムマスターをやってみたりしました。そこではスクラムマスター兼開発者として、新規のシステム開発フルスタックで経験することができて楽しかった思い出があります。スクラムマスターとしてPOとの調整や、メンバーの育成といった普段ではできないタスクの面白さもありました。こうした新しい業務についても、新人の頃と比べるとかなりのスピード感で慣れていくことができたので、社内で2つの案件を同時に抱えててもあまり残業せずに退社できるくらいにはなっていました。

そうした背景から、副業についても力を入れていくことにしました。データ分析では異常検知のアルゴリズム開発や、評価指標の開発なんかで学会発表に行ったり、開発にフルスタックで入ったりなどいろいろ挑戦しました。次第に、人づてにいくつか他の案件を紹介されるなど、副業の方も軌道にのってきました。

副業が順調だと必ず考えてしまうのがフリーになるか?ということですが、個人的に以下の理由から、早急にフリーになる必要はないと思います。

  • 現在の本業は残業が少なくあまり邪魔にならない
  • 待遇的にも周りのメンバーにも恵まれた環境である
  • 中には自分がロールモデルとしたい凄腕のエンジニアがいる

とくに、ロールモデルとしたい人がいるというのは本業を続ける強い理由となっています。私は自分の実力をある程度信用していましたが、足元にも及ばないと思う経験はすごく悔しかったのと同時に、強い尊敬の念に変わりました。

 

2年間を振り返って

まだまだ振り返りたいことはたくさんありますが、自分の成長を感じながら楽しめた2年間だと思っています。3年目となる2024年度はさらに副業を頑張ってみたい気持ちがあります。最近はwantedlyでいくつか案件に応募したりしていました。いい返事もいただけているので、幸いなことに今年度はさらに忙しくなりそうで、すごくわくわくしています!(いま冷静に考えるとワーカホリック気味かもしれないですね。倒れない程度にがんばりたいです)