新規印刷事業の立ち上げ、開発、運用業務
# 技術スタック Golang, PHP, CodeIgniter, TypeScript, Vue.js, Nuxt.js, AWS_Lambda, RDS, S3, serverless-framework, GitHub_Actions, BigQuery, SalesForce, Re:dash, SQL # プロジェクト概要 写真印刷サービスの新規立ち上げ、開発、運用を担当した。 サーバーサイドエンジニアとしてスクラム・チームにジョインし、プロダクトの開発はもとより、デザインやUXの検討会にも積極的に参加してきた。総じて、コードのみにコミットするのではなく、ユーザーストーリーにコミットする働き方を意識し続けてきた。 開発の面とチームの面それぞれでどのような貢献をしたのかを記述する。 # サービス概要 ## 写真印刷サービスとは 本プロダクトは、正方形の家族写真を手軽に印刷できるスマホアプリである。ユーザーがアプリに写真を登録し、アプリ内の機能で加工し、住所を指定して購入すると後日印刷された写真が配送されてくる。 ストア機能も備わっており、アルバムなどの写真の付属商品を購入することもできる。 スマホで写真印刷をするサービスは既出であったが、それでもスマホ写真印刷市場に後発での参入をした。1.価格設定を他社より下げられる可能性があること、2.社内のデザインノウハウの蓄積があり、よりUIがわかりやすいプロダクトを開発できる素地があること、3.すでに弊社内では印刷事業を展開しており、事業的な知見の援用も期待できることなどの理由から、後発で参入しても勝算はあると判断し、新規開発を決定した。 # プロジェクトに対する貢献 ## 1.開発への貢献 ### 実際に開発を担当した機能について プロダクトに直接関わる本機能としては以下を担当した。 - クレジットカードを使った決済機能 - まとめ割引実装(写真、ブック) - 無料キャンペーン(写真、送料等) - 友達紹介機能 - キャンペーンタブ開発 本機能はAPI Gateway, Lambda, Aurora MySQLの構成で開発し、Lambdaはドメイン駆動設計(以下DDD)に則った設計のもとGo言語を用いて実装した。一部の機能は従来からある基幹システムを流用して作られているため、バックエンドシステムの中にはCodeIgniter(PHP)を使っている部分も存在する。 本機能以外には社内向けシステムの構築も行った。管理画面はVue.jsとNuxt.jsを使ったSPAで開発。分析基盤についてはSalesForce、Redash、BigQueryを使ったデータ連携やダッシュボード構築を担当した。 総じて、プロダクトの開発、運用、分析に必要なバックエンド全般(インフラ含む)を担当した。これらのうちGoを使った本機能開発が私の担当した業務の大部分を占めている。 ### アーキテクチャについて 本プロジェクトは新規立ち上げ案件であったため、最初から設計方針のコンセンサスをとってから開発にのぞむこととなり、DDDを採用した。 創業期から開発・運用されている弊社の基幹システムは、MVCの設計のもとCodeIgniterで書かれたモノリシックなシステムである。EC2の上に搭載され、一つのフレームワークに複数のサービスが詰め込まれている状態であった。 そこで、新規プロダクトに関してはDDDの設計思想に基づいたフルサーバーレスなシステムを基本に開発を進めていく方針をとった。 DDDにのっとって開発を進めていく中で感じたメリットは以下である。 #### メリット1:追加機能開発やリファクタリングがしやすい 基幹システムの追加改修をしていた際はModelがFatであったため、ビジネスロジックとデータストレージとの連携処理が密結合に記述されている箇所があったり、似たような機能が別の関数として複数箇所に実装されていたりすることがあった。 DDDを採用した本プロジェクトの場合は、ドメイン層とその他インフラ層(adapter, repository, etc...)が区別して書かれているため、追加機能を実装するときに、ビジネスロジックを新規に書きつつ既存のインフラ層の機能は流用するといった書き方ができた。 また、疎結合を意識した書き方をチームで心がけていたので、基幹システムを改修していたときと比べてテストコードが書きやすくなった。複雑化した精算ロジックのリファクタリングなども、テストコードによる品質担保をしながらスムーズに行うことができた。 #### メリット2:システムやプロダクトの構造の捉え方が変化する どれだけ本を読んでも、現場のドメイン知識をドメイン層のコードに落とし込む方法は学べない。日々仲間たちとディスカッションしながら実装を進めていくことで、何が中央のドメイン層に書くべき事柄で、何が周縁の層に書くべきことなのかを切り分けて考える思考回路が鍛えられた。結果、自分達のビジネスに固有な箇所はどこなのか、逆に代替可能な手段のレイヤーに位置するものはなんなのかを考えることができるようになった。この発想は後述する「チームへの貢献」でアジャイルを推進していく際の考え方にも影響を及ぼすこととなる。 ## 2.チームへの貢献:アジャイルを推進する アジャイルな開発を進めていく中で、ユーザーストーリー単位で物事を考えることにも注力してきた。私のチームが担当していたバックログのユーザー・ストーリーには必ずWhat(何を作る/為すのか)とWhy(なぜその行為が必要とされているのか)が書かれており、このWhyの意味を深堀りしたり、その妥当性をチームで議論することを心掛けてきた。 アジャイルを推進する姿勢として心がけたことは二つある。一つ目は工程に拘泥しない協働姿勢である。 自分の専門担当はバックエンドだが、ほかにも開発には様々な工程が存在する。Whyとしっかり接続されたWhatを達成するためにはどのようなHow(=実装手段、開発手段)が必要なのかを、上流/下流工程の区別や、デザイン/フロント/バック/QAの区別なく考えてきた。 ストーリーのWhyに応えるには、職能横断も必要となる。PMが担当していたユーザーインタビューの設計/実施や、ユーザー分析のためのダッシュボード設計/構築などを代わりに引き受けたりもした。 二つ目の心がけは「根源的な思考を絶やさない」ということである。一つ目の心がけはWhyに最適なWhatやHowを考えていたが、二つ目の心がけはWhyそのものを問う、すなわち「コアなサービス価値」とは何なのかを深く考え抜く姿勢を指す。 弊社には定期購入型の類似サービスを既に展開中であり、本プロダクトはそれとは異なる「ショットで買える写真事業」として始まった。しかし競合製品を模倣し機能追加をしていく中で、弊社開発陣も定期購入を促す競合製品の設計思想に染まるようになる。ストーリーに書かれたWhyがキックオフ時の前提とずれはじめ、メンバーはそのようなずれがあることを認識できていなかった。それゆえ新規機能のデザインや仕様についてもどちらの前提に立つのかで意見が食い違う現象が起きた。この時チームに在籍していたPMが退職しエンジニアとデザイナーだけのチームとなったことも舵取りの方向性を失う要因ともなっていた。 そこで「このプロダクトは誰が発案し、その出発点にはどのような着想と思想があったのか。どのようなライフスタイルのユーザーに使ってもらいたいのか」を私はチームメンバーに確認していった。結果、メンバーの心中にある「プロダクトオーナー(PO)のやりたいと思っているだろうこと」が複数あることが判明した。さらにPOに確認すると、実際のPOがやりたいことともずれていた。 PO主催で仕切り直しの認識合わせ会が行われたのちは、ユーザー・ストーリーに書かれるWhyの性質が同じ方向を向くようになり、チームの足並みも揃って生産性が向上した。 プロダクト開発を続けていれば、複雑性は指数関数状に上昇していくものである。そのような中で、本当にチームやPOや会社が成し遂げるべきことはなんだったのかを常に考え、チームに問い、組織の向くべき方角を見失わないようにするチームワークを発揮することが、私の重視してきた働き方である。