副業先で3ヶ月でやったこと #仕事ください
あけましておめでとうございます!🐉
最近仕事でやっていること
今年からフリーランスエンジニアとして日本で腕を磨きたいと考えております。
自分が最近何をしているかシェアすることでいろんな方とつながれるかなと思い(仕事ください)、副業先で3ヶ月でやったことをシェアします。
ちなみに週二日稼働で3ヶ月でしたので、フルタイム換算だとすると1ヶ月強くらいの日数です。並行して、機能開発/バグフィックスなども行っていました。
背景
2023年暮れ、週二日の契約でウェブ開発の副業をはじめました。
ご縁があって面談に至り、面談時では具体的な仕事内容はあまり決まっていませんでした。が、
- PMF(Product Market Fit)をすでに達成しているように見えたこと
- 自分がもっともインパクトが出る、Railsを中心にした技術的知見が活きそうな現場だったこと
- 働きやすそうな職場だったこと
があり、ぜひご一緒させていただきたいとお返事しました。
コミュニケーションが良かった
- Photo by Brooke Cagle on Unsplash
その中で一番の決め手は、創業メンバーでエンジニアであるAさんのコミュニケーション方法が自分ととても合うものだったから、というものでした。
業務委託は正社員と違って、傭兵としてすぐに結果を出す、というマインドセットがある程度必要だと思います。
正社員であればカルチャーをラーニングして徐々に価値を出していくという道があると思いますが、フリーランスでそれをやると期待値調整がうまくできないまま契約終了となるリスクがあります。
即結果を出すために、スタート時点でのコミュニケーションのフィット感はとても大事でした。おかげさまで、入社すぐに以下に記すことをチームで、またAさんと二人三脚で進めることができました。本当に感謝しています。
実際にやったこと
Rubyを2系から3.2にあげた(1ヶ月)
Rubyのバージョンが2系と古く、すでにEOLを迎えていました。
言語やライブラリのバージョンアップは、ワークフローが一旦廃れると後周りにされがちです(Dependabot..)。ですので、なぜやらなければいけないか、全社的に説明できるような言語化に努めました。
分かりやすい理由としてはセキュリティリスクですが、それだけでなくパフォーマンス改善や、後述のSorbetの導入のしやすさなど、これが攻めのバージョンアップでもあることを伝えると、なぜ今やらなければいけないのか、という提案が通りやすくなると思います。
Rubyの型チェックSorbetを導入した(2週間)
諸事情あって、テスト駆動開発(TDD)があまり機能していませんでした。テストカバレッジがほとんどなく、低凝集で蜜結合なモジュール・クラスが沢山ありました。
そこからユニットテストを効率よく増やしていくためには、スタブを多用してその場をしのぐか、結合度合いを下げるためのリファクタリングが必要です。 どちらも長期戦です。
このようにTDDの復活が難しい現場では、Ruby3で正式にサポートされたタイプチェックが有効なように思えます。
実際に並行してやっていた機能開発タスクでリグレッションが起きそうになったときのふりかえりで強く感じ、実際に導入の相談をしました。
実際に何が良かったか
(rbiファイルはこんな感じ)
# -- example.rbi --
# typed: strict
# Declares a class
class Parent
# Declares a method with input and output types
sig {params(x: Integer).returns(String)}
def bar(x)
end
end
具体的には、外部ライブラリ(LINE SDK)が期待する引数に何を渡せばいいのか、社内で認識ミスが過去にあり、コードで数十箇所使われているその呼び出しの一つが サイレントエラー(期待すべき挙動が起きていないが、エラーにも上がってこない) になっていました。
このときに、LINE SDKで提供されているそのメソッドにRBI(型定義)を書いてあげることで、容易に開発時にチェックできるようになりました。これは、今後追加される呼び出し側全てに対しても機能するので、とてもコスパが良いと感じています。
DBが密結合になっているサービスのリタイア(1ヶ月+)
最後に、現在進行形のものですが、稼働しているサービス群のパターンとして「アプリケーションレイヤーが分かれているがDBが同じものに接続している」という状況でした。
DBが密結合な限り、アプリケーションが分かれたことによるメリットはほとんど享受できません。
これは別記事で詳しく書きたいと思うのですが、DBこそが、各サービスを個別に独立して開発・デプロイ・運用する上でのボトルネックになるからです(標準的なウェブアプリの場合)
DBが密結合の裏ボスである
N個のアプリケーション実行環境が、1個のDBに接続している状態は、自分が最も「におい」を感じるパターンの一つです。
分けた気になっているのですが、実際に何か開発をしようとすると、片方のモデル層の変更やクエリの変更の副作用で、もう片方へ予期せぬ害を生むので全く分けられていません。
「分けた気になっている」というところが厄介で、これで技術的負債をかえしたと思っていたらその後の開発でスピードや安定性が改善されなかった、ということになりますので、ぜひ注意してください。
具体的にどう直すのか
間違った分離を正しく分離させるためには、再統合が必要です。今回のケースで最も分かりやすかったのが、二つの独立したRailsアプリでした。
片方は社内管理画面用で、もう片方はAPIサーバーとしての運用でした。一見理にかなっているように見えますが、DB(もっといえばテーブル)が同じものを向いている以上、今後のリファクタリングや運用の問題を先送りにしており、データの不整合のリスクが増えています。
実行環境さえ分かれていなければ、DB(そしてモデル層)の重複は一目瞭然だったはずです。まずはモジュラーモノリスを目指し、必要であればDBの再整理をする、というステップが必要不可欠だと思います。
今回のケースはとてもわかりやすく、管理画面をつくっていたRailsアプリのモデル層の95%ほどが、API側のRailsアプリのモデル層と同じコードでした。その差分に注意しつつ、コントローラーやルーティングをガツっとメイン稼働しているアプリケーション側(今回は管理画面をAPI側へ)に持ってくることで、社内でQAできる段階まで進めることができました。
おわりに
今回は、自分が副業先で行った技術施策を三つほどご紹介しました。それぞれかかった日数は、
- Ruby2から3へのバージョンアップ:1ヶ月
- Sorbet導入:2週間
- DBが密結合しているサービスの統合:1ヶ月(QA開始までの日数)
ほどです。
日数を短くするときのコツ
その施策によって生じうるリスクをどれほどヘッジするかで、日数は大幅に変わってきます。
早ければいいというものでもありませんが、
- リバートできる変更で
- エンドユーザーへのインパクトがきちんと予期できているのであれば
早くに技術的負債をある程度返済した状態にして、プロダクトチームをがんがん回すサイクルに貢献するのも手かなと思います。
今回はかなり一足飛びに進めさせていただいた感触があります。それも上長や社長の理解、エンジニアリングの負債をかえすことでプロダクトが成長する認識が一致できたからだと思います。本当に良い現場に恵まれました。感謝しかないです。
もしこのような仕事内容にピンときた方がいましたら、ぜひご連絡ください。TwitterやGithub、LinkedInはこちらです。
似たような案件や現場で困っている方がいましたら、ぜひ話しましょう!ご相談ください。
それでは近いうちに!またね。
Discussion