リリース作業をかんたんに! git-pr-release + Google Apps Script + Ruby スクリプト + GitHub Actions によるリリース作業改善の取り組み

ジモティーでサーバサイドとインフラを担当している吉田です。

前回は ISUCON10 に参加した話を投稿しました。今年もちょうど ISUCON11 を終えたばかりですが、残念ながら予選敗退となりました。ISUCON への参加はウェブエンジニアとしてのキャリアを見つめ直すとてもよい機会で、来年こそは決勝に進みたいと思っています。

さて、今回はジモティーのサーバサイドで1年ほど運用している、リリース作業の一部自動化の取り組みについて、背景から実施までをご紹介します。

従来のリリースフローとその課題

まず、弊社サーバサイドのリリースフローについて、当時の概要は次の様になっていました*1

変更前のリリースフロー
変更前のリリースフロー

  1. コードレビューを経て、トピックブランチを master ブランチにマージ(作業者: 各機能担当者
  2. リリース PR を作成(作業者: リリース担当者
  3. 機能担当者にリリース前テスト環境での動作確認依頼(作業者: リリース担当者
  4. 動作確認(作業者: 各機能担当者
  5. Jenkins のジョブを実行してリリース(作業者: リリース担当者

リリース担当者はリリースしたいメンバーによる立候補制で、サーバサイドのメンバーであれば誰でもこの役割になる可能性があります*2

この作業の1番の課題は、マージされた PR の「タイトル」「作成者」を目視で抜き出す事が大変な点です(図の2. および 3. に該当)。

詳細な流れは次の内容になります。

リリースPRの作成と動作確認依頼
リリースPRの作成と動作確認依頼

  1. master ブランチへのコミットログの中からマージコミット (メッセージが Merge pull request #xxxx from jmty/xxxx) を確認
  2. マージコミットの PR から「タイトル」「作成者」を確認
  3. 確認した「タイトル」をリリース PR の本文に入力
  4. 確認した「作成者」にリリース前テスト環境での動作確認を Slack のメンションで依頼

また、PR の「作成者」は GitHub のアカウント名なので、Slack のアカウント名に変換して Slack で本人にメンションする必要があります。そのため、たまに誤って違うメンバーにメンションをしてしまう問題も発生していました。

変換ミスによる誤メンション
変換ミスによる誤メンション

これをマージ済み PR の数だけ繰り返す必要があり、リリースタイミングによっては1度に10件を超える事もあります。

改善

事前準備

まず、課題を明確にします。こちらは前述の通りです。

  • リリース PR 作成時に、マージされた PR の「タイトル」「作成者」を目視で抜き出す事が大変
  • 誤って違うメンバーに動作確認依頼を行ってしまう

次に、その解決方法を調べます。

基本的に手作業で行っていた、マージされた PR の「タイトル」「作成者」を目視で抜き出して作業担当者に依頼する作業を自動化する方針で、かんたんな実装を行いました。これは、次で行う提案のための準備になります。フィードバックの結果、内容を大きく変更する可能性も十分あるため、あまり作り込まず、かつ GO サインをもらえるレベルにします。

KPT での提案

準備した内容をもとに、週1で実施しているウェブチームの KPT で下記の提案をしました。

  • 課題の共有
    • リリース作業がツラい
  • 解決案の提示
  • FAQ
    • リリースフローはどう変わるのか
    • 導入・運用コスト
    • メリットだけではなくデメリットも
    • なぜ CI は既存で利用している CircleCI ではなく GitHub Actions で動作させるのか、など

想定していた実装工数は比較的小さいため、一気に導入する手もありますが、次の観点から提案のステップを挟むことにしました。

  • 共通の課題である事の確認および、ニーズの確認
  • 異動や退職などで技術的な負債となる可能性がある
  • リリースフローの変更により、障害に繋がりやすくなる可能性がある

結果はおおむね期待していた良い反応だったため、具体的な実装に移りました。

変更後

最終的に次の流れになっています。

変更後のリリースフロー
変更後のリリースフロー

  1. コードレビューを経て、トピックブランチを master ブランチにマージ(作業者: 各機能担当者
  2. リリース PR を作成(作業者: リリース担当者
  3. 機能担当者にリリース前テスト環境での動作確認依頼
    1. 本文を自動更新 (git-pr-relase gem)
    2. GitHub と Slack ID のマッピングを取得 (Apps Script)
    3. 動作確認依頼 (Ruby スクリプト)
  4. 動作確認(作業者: 各機能担当者
  5. Jenkins のジョブを実行してリリース(作業者: リリース担当者

「機能担当者にリリース前テスト環境での動作確認依頼」の作業を自動化しています。

それぞれの技術トピックについてご説明します。

git-pr-release

git-pr-release はリリース PR を作成・更新する gem です。マージされた PR からタイトルや担当者を取得して、PR を作成・更新してくれます。

当初自作をしようと考えていたところ、希望の機能を満たすこちらの gem が見つかり、OSS かつ定期的にメンテナンスされていたため採用しました。

最近 GitHub の仕様変更があり、期待する動作をしなくなる事がありましたが、すぐに対応されたものがリリースされました。

もし自作していた場合、同様の対応を行う可能性が高かったはずです。

Google Apps Script

GitHub アカウント名と Slack ID のマッピングを JOSN として返すウェブアプリケーションサービスです。

次はサービスのURLに対して curl からの擬似的なアクセス例になります。

$ curl -H "Authorization: token xxxx" -L \
  --dump-header - \
  "https://script.google.com/xxxxxx"
(省略)
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
(省略)

[
  {
    "slack_member_id"=>"XXXX",
    "slack_display_name"=>"kyoshida", 
    "github_login_name"=>"kyoshidajp"
  },
  {
    "slack_member_id"=>"YYYY",
    "slack_display_name"=>"yyyy",
    "github_login_name"=>"zzzz"
  },
  ...
]

マージされた PR からその作成者(機能担当者)のアカウント名を取得した後、Slack ID に変換する際にこのマッピング情報を参照します。

事前に Google スプレッドシートにそれぞれの対応を記載しておきます。新しいメンバーが加入したら都度こちらに追加します。このシートのメンテナンスが手動になってしまいますが、他の利用用途でも使えるようになります。

Ruby スクリプト

リリース PR の本文から、マージされたPRの「タイトル」「担当者」を取得して Slack に通知します。

Ruby は弊社サーバサイドにてメインで利用しているプログラミング言語です。ユニットテストや JSON の変換など、豊富なライブラリが付属している事に加えて、Slack や GitHub 連携など16万を超える*3サードパーティのライブラリによる素晴らしいエコシステムがあります。

同様の目的には、後述する GitHub Actions のワークフローコマンドから gh や jq を駆使して行うことも可能だと思いますが、上記観点から Ruby スクリプトとしました。

GitHub Actions

git-pr-release および、Slack に通知する Ruby スクリプトの実行環境です。

master から release ブランチへマージするリリース PR が作成されたタイミング、もしくはmaster ブランチにコミットが行われたタイミングで実行されます。後者については、リリース PR が作成された後に、追加でリリース機能を含めるケースに対応するためです。

CI 環境としてすでに利用している CicleCI ではなく、GitHub Actions を採用したのは次の理由によるものです。

  • 世の中の流れとして GitHub Actions がかなり普及してきており、キャッチアップをしておきたい
  • 想定の利用ケースでは無料枠に十分収まる
  • 面白そう

結果

改善により、当初の課題であった、リリース担当者による目視かつ手作業での依頼が不要になりました。

自動で通知される動作確認依頼
自動で通知される動作確認依頼

また、誤って別のメンバーに確認依頼してしまう問題も発生していません。

さらに、工夫したポイントとして、デプロイ時に Slack で通知されるリリースノートの内容が分かりづらかったため、同様の仕組みで整理しました。

整理されたリリースノートの通知
整理されたリリースノートの通知

この結果、エンジニアだけでなく、CS を含む社内メンバーは機能概要機能担当者リリース担当者が明確になりました。

まとめ

日常で感じた課題の解消をモチベーションに、その改善の提案、そして実施までをご紹介しました。

自動化した作業は、以前は1回あたりおよそ5〜15分程度だったので、リターンを時間で換算するとどうしても投資効果を低く感じてしまいがちです。しかし、日々課題に感じていて改善の目処が立っているのであれば、積極的に取り組むべきだと思います。

そもそも、対象の作業は手作業で日々繰り返され、自動化が可能なものでした。こういった、いわゆるトイルの撲滅は(インフラ)エンジニアが価値を発揮しやすい領域ではないでしょうか?

少なくとも、以前の状態には戻りたくないのが率直な気持ちです。

宣伝

ジモティーではエンジニアを募集中です。

jmty.co.jp

日々の不満や課題を一緒に解決していきましょう!

*1:master ブランチへのマージ後にリリース前テスト環境への自動反映など、細かい内容は省略

*2:これは執筆時点も同じ

*3:執筆時点の https://rubygems.org/stats より

ジモティーのフロントエンド事情

初めまして。

2020年末からジモティーでフロントエンドエンジニアとして開発している山口です。

今回はジモティーのフロントエンド事情について紹介します。

ジモティーフロントエンドの現状

現在のジモティーのフロントエンドはRailsのAction Viewを用いて

  • jQuery で Javascript 周り(一部のページの一部の DOM に対して jQuery 代替として Vueも利用)
  • Rails の decorator でフォーマットして Haml でマークアップ
  • Sass でスタイル付け

といった構成になっています。

しかしサービスの規模が大きくなってきたこともあり、どのidやclassをどの jQuery コードが参照しているのか追いづらかったり、 似たスタイルを持つ似た名前のclassが乱立してしまいどれを利用すべきなのかの見通しがつかないなど、開発が辛くなってきているのが正直なところです。

Railsの開発チームはアプリ向けのAPIの作成やバックエンドの開発と並行してフロントエンド開発も行っているため、 辛さが出てきた現状が会社として求める開発スピードUPの足枷になってきています。

新規プロジェクトにてReact(NextJS)を利用

今月リリースした新規プロジェクト、自治体向けの電子申請・申請承認システム「LOCONET(ロコネット)」にて、弊社としては初めて React を利用した開発体制を敷きました。

バックエンドはジモティーに引き続きReilsを利用し、フロントエンドはバックエンドとは完全に分離してReact(NextJS)+Typescript で作成、さらにOpenAPIによる APIドキュメント整備とStorybook によるコンポーネントのドキュメント整備を行うことでバックエンド開発者やデザイナーとのコミュニケーションを取りやすい環境を構築しました。

技術負債との比較

前述した現在のジモティーの開発状況と比べると今回の開発体制では

  • styled-compomentsを利用でスタイルのスコープを制限してスタイルの見通しが付きやすくなる
  • contextの利用を避けてあえてpropによるバケツリレーを選択することでstateなど変数の変更が追いやすくやる
  • Typescript によりコードがよりドキュメントとして理解しやすい形で残るようになったため、第三者がコードを追いやすくなる
  • バックエンドと分離されることでアプリチームと似た分担で開発が可能になり、適材適所の分担で開発が行えるようになる
  • デザイナーとパーツ単位で実装しているスタイルを見ながら密なコミュニケーションが取れるようになる

などのメリットを得ることができました。

代わりに

  • Typescript 導入により、追加で工数が発生してしまう
  • 保守していかなかればならないものが増えた(OpenAPI,StoryBook)

といったデメリットは発生しています。

Typescript導入において型管理以外に特に時間を要したのは次に紹介する2項目です。

外部ライブラリ利用時の型調査の時間

外部ライブラリ使用した際にライブラリ内に定義されている型の内容、利用方法の確認に時間を要しました。

特に初めて利用するライブラリの場合、javascript時の倍は時間がかかる感覚です。

直で呼び出す場合より子コンポーネントへライブラリの一部を受け渡しする必要があった場合など子コンポーネントのpropの定義に悩むことが多かったです。(大抵公式のドキュメントにその場合の型の定義方法が書いてないので直接ライブラリを追ってみるしかなかったです)

例) React Hook Formの場合 https://react-hook-form.com/jp/get-started/

const { register, handleSubmit, watch, formState: { errors } } = useForm<Inputs>()

useFormで呼び出してきた各種メソッドregister, handleSubmit, watch, errors をコンポーネントへ受け渡したい時、どのような型で待ち受けるべきかがドキュメントからはわからず、なるべくanyなどを使わず実装しようとすると最適解を見つけるのに時間がかりました。

型推論のための追加記述

頻出するわけではないですが、遭遇した場合に解決の時間を用意したのがこちら。

適切な型推論が行われるようにするために javascriptだけならそのままで要件を満たして動作するコードに対して - typescriptが型推論に対応しているメソッドに書き直す - 自前で型推論させる処理を追加する(javascriptの動作上は必要のないコード) という対応をする必要が発生しました。

例) filterを利用してarrayを整理しても方が絞り込まれない例

const x = [123, null] // 型推論結果 const x: (number | null)[]
const y = x.filter(v => v !== null)
console.log(y) // [123]
// 型推論結果 const y: (number | null)[]
// number[] にならない

このままではビルドが通らないので型ガードを駆使したりして型を絞り込む必要が出てきますがチームへのTSの知見が溜まっていないと解決まで時間がかかってしまいます。

...

しかしながら、 Typescript導入やOpenAPI、Storybookはある程度のコード規模が大きくなり、チームの人数が増えてきたときに効力を発揮する要素なので投資として受け入れるべきコストだと考えています。

VueとReactの違い

実は私はジモティージョイン前までVueをフロントエンド開発に利用していたため今回のプロジェクトが React に触れる初の機会でした。

そのため Vue 開発と比べた時の違いについてもいくつか感じることができましたので紹介します。

自由度が高く、良くするも悪くするも開発者次第なReact vs 形式がしっかりしており、とっつきやすいVue

Vue はコンポーネント内で何をどこに定義すべきかはっきりしているのに比べて、React はとにかく自由度が高いため、開発者がやりたいように柔軟な書き方ができる反面、選択肢が多いため、知見がない状態ではベストプラクティスを見出すのが難しいと感じました。

コンポーネントファイル内でstateやeventなどを定義する場所(Vueはdataやwatch,methodなど書き場所が固定されていて開発者でバラつかない)や、スタイルの定義方法は他のオープンソースの事例をいくつか参照してみましたがどれもバラバラで自分たちに合ったやり方を見出す必要がありました。

スタイル付けに関してはスコープをコンポーネント内に留めたいのと、なるべくcssそのままの形で記載ができることをとってstyped-componentをチョイスしましたが正直Vueの方がシンプルにcssそのまま埋め込め、sassなども導入しやすかったので扱いやすかった印象です。

Typescriptとの親和が進んでいるReact、やれることが多いNextJS

自分がしっかりTypescriptに触れていなかった原因でもあるのですが、どうしてもVueの方がTypescript導入が遅れているので、きれいに導入できるReactの方が今のところは軍配が上がるという印象でした。

また、NextJSの方がISRなどへの対応が進んでおり、よりサービスに適した形でビルド方法を検討することができる点も好印象でした。

今後のフロントエンド開発

今後ジモティー自体でも Reils の MVC モデルに乗っかって jQuery を利用している現環境をやめて、今回 LOCONET で作ったようなフロントを分離した開発体制へ移行していく予定です。

かなり機能が多いサービスになっているため、大掛かりなプロジェクトにはなりますが、移行後はより良いユーザー体験と開発スピードを実現できると思います。

ジモティーは今回の私のように未経験技術へ挑戦する機会を積極的に与えてくださり 新規技術への興味関心度合いも高く、エンジニアとして働くのが非常に面白い組織です。

今後もこのサイトではジモティーのフロントエンド事情についての記事を投稿予定ですのでご期待ください。

ジモティーのUI/UXに関する取り組みについて🧸

f:id:jmty_tech:20210625183109p:plain:w250

ジモティーエンジニア紅一点のnaruです🧸
iOSチームで開発を行っています。

最近は自粛で気軽に外に行けないこともあり、自分の所有する車を擬人化したりなどしておうち時間を過ごしたりしてます🧸

f:id:jmty_tech:20210625172747j:plain:w200

前回は↓こんな記事を書いております。 jmty-tech.hatenablog.com

今回もデザイン関連についての話をしたく、UI/UXに関して自社で行っている取り組みの一部を紹介しようと思います。

まず、UI/UXに関するコミュニケーションは今年に入ってからより活性化するようになりました。

f:id:jmty_tech:20210625183029p:plain:w200

というのも、
会社全体のチーム編成や考え方の見直しや、
ジモティーの根幹のDesignSystemの見直しについてデザイナーエンジニア間でMTGする機会が増えたこと、
エンジニア側からもUI/UXの提案を行うようになったことで、
よりお互いが互いの分野に歩み寄って一緒に学んでいきたいという思いが強くなってきた部分があるのかなと思います🤗
(DesignSystemについては、絶賛検討が進んでおりますので、然るべきタイミングでまた話ができれば😌)


#design_infoというオープンチャンネルを作り、


他社の事例を紹介したり、 f:id:jmty_tech:20210625183422p:plain


デザイナーがプログラムについて調べてみたり、 f:id:jmty_tech:20210625183506p:plain


新しいOSの変更点などを共有したりしています🌟 f:id:jmty_tech:20210630135741p:plain

そして、今回メインで紹介したいのが、「UIパッション会」という取り組みです💪

UIパッション会

f:id:jmty_tech:20210625191255p:plain

「もっと色々話したいよ〜🥺」というところで
名前の通り、「UIにもっと目を向けていこうぜ!意見交換しようぜ!💥」という名目の共有会を月1で有志を集い開催しています。

f:id:jmty_tech:20210625182115p:plain:w250

もともと自分は月1で他社アプリのアップデートの内容を共有する、
ということをやっていたのですが

f:id:jmty_tech:20210630135803p:plain

もっと具体的に詳しく話し合ったり、

デザイナーから「こういうの実装したいんだけどどうかなあ」などをフランクに聞いてもらったり

f:id:jmty_tech:20210625194718p:plain:w250


ゴールは案件化ですが、あくまでもざっくばらんに話すを目的にしています:)


これまで実際話された内容としては、

「xxxみたいなUIって難しい?🤔」
「xxx画面の改善を考えているんだけど....🥺」 f:id:jmty_tech:20210630141144p:plain

「某アプリ考察した!😀」
f:id:jmty_tech:20210625201543p:plain:w280

「ios14からAppleが提供するようになったこんな機能があるんだ😏」 f:id:jmty_tech:20210625201744p:plain

あとは、
「〜〜〜っていう機能を作りたいからちょっとざっくり感想教えて欲しい🤗」

などなど....



実際ここから案件起案があがったりもあり、
新しい視点での発見や学びもあり良い取り組みだというところで今後も継続して実施できればと思います。

その他の取り組み

カスタマージャーニーワークショップ

有志で集まってはじめてのカスタマージャーニーマップワークショップという本を参考に、自社サービスについて分析。 各画面の優先度や既存機能の重要さ、改善ポイントをユーザー視点で考えるきっかけになりました💪

f:id:jmty_tech:20210625174342p:plain

UXきんにくん

ディレクターやUXチームを中心に、チームに分かれて他社アプリを洞察して発表し合う、なども行っています。

おわりに

ジモティーでは上記のような取り組み以外にも 色々な分野でユーザー視点での考えを推奨し、評価される制度となっています。
今回書いた内容に興味をもっていただけたり、共感いただけたら幸いです。

jmty.co.jp

AndroidのローカルDBをSQLiteからRoomに置き換えてみた

はじめに

はじめまして。ジモティーに2021年1月からAndroidアプリエンジニアとしてい働いている谷です。

今回はAndroidアプリエンジニアとしてローカルDBをSQLiteからRoomに置き換えた話をさせていただければと思います。

Roomとは

置き換えの話に入る前にさらっとRoomについて説明したいと思います。 RoomとはGoogleが推奨しているSQLiteのORMです。 SQLiteHelperの作成やCursorの操作などめんどくさい処理を一手に引き受けてくれます。

実装も非常にわかりやすく、3つのコンポーネントを作成するだけでローカルDBの構築が可能です。

  • Entity
  • Dao
  • Database

合わせて非同期処理としてRxやKotlin Coroutinesなどのサポートもされており、非常に使いやすいです。

さらにデバッグツールとしてAndroid Studio 4.1から追加されたDatabase Inspectorというものがあり、APIレベル26以上の端末でアプリを実行している時に使用できます。 作成したテーブルの中身をSQLを使って操作したり、Database Inspectorのウィンドウでそのまま書き換えたりといったことが可能です。 こちらにどんな感じのものか詳しく書かれている記事がありますので、是非見てください。

そして以下簡易的ではありますがRoomの実装例です。

まずはEntityを作ります。 これがテーブルの役割を果たします。

 @Entity(tableName = "tbl_todos")
 data class Todo(
     @PrimaryKey(autoGenerate = true)
     val id: Long,
     val title: String,
     val isActive: Boolean
 )

続いてDaoを作成します。 データを取得したい場合はこちらに定義したメソッドを呼び出すことになります。

 @Dao
 interface TodoDao {
     @Insert
     suspend fun insertTodo(todo: Todo)
 
     @Query("SELECT id, title, is_done FROM tbl_todos")
     suspend fun getAll(): List<Todo>
 
     @Query("SELECT id, title, is_done FROM tbl_todos WHERE is_done = :isDone")
     suspend fun getDoneTodo(isDone: Boolean): List<Todo>
 
     @Update
     suspend fun updateTodo(todo: Todo)
 
     @Delete
     suspend fun deleteTodo(todo: Todo)
 }

最後にDBを実装します。

 @Database(entities = [Todo::class], version = 1, exportSchema = false)
 abstract class TodoDatabase : RoomDatabase() {
     abstract fun getTodoDao(): TodoDao
 
     companion object {
         private const val DATABASE_NAME = "todo-db"
 
         fun createTodoDatabase(context: Context): TodoDatabase {
             return Room
                 .databaseBuilder(
                     context.applicationContext,
                     TodoDatabase::class.java,
                     DATABASE_NAME
                 ).build()
         }
     }
 }

おそらく基本的にはDaggerなどでインジェクションすると思いますが、以下のように呼び出すことが可能です。

 // Daoの取得
 val todoDao = TodoDatabase.createTodoDatabase(context).getTodoDao()
 
 // 取得したDaoから各種メソッドでローカルDBにアクセスする
 todoDao.insertTodo(Todo("保存したいTodoのタイトル"))

ここまでが基本的なRoomの使い方となります。

背景

元々ジモティーのAndroidアプリではローカルDBとしてSQLiteとRealmが採用されておりました。 ジモティー内での使い分けとしては以下のような感じです。

  • SQLite
    • サーバーから取得したマスターデータをキャッシュするために使用。
  • Realm
    • 検索結果の履歴保存などに使用。

上記の内、SQLite部分で

  • 実装されているコードが古い。
  • 可読性が低くマイグレーションなどが発生した際にメンテナンスしづらい。
  • ローカルDBへの接続処理がUIスレッド上で実装されている。

という負があり、その辺りが解消されるのではないかということで導入することにしました。

以下、置き換え実施時に参考にした情報です。

  • Migrate from SQLite to Room
    • SQLiteからRoomへのマイグレーション方法について基本的なことが書かれており非常に分かりやすかったです。
  • Incrementally migrate from SQLite to Room
    • 後述するのですが、今回は完全な置き換えができなかったので段階的に置き換えをするにはどうしたら良いかが書かれておりこちらも非常に有用でした。

結果

結果は完全な置き換えはできず、段階的な置き換えを実施する形になりました。 修正範囲が当初想定していたよりも広くなってしまったのと、アーキテクチャに則って作られていない部分の改修難易度が高く時間的にも厳しかったためこの判断になりました。

完全な置き換えはできなかったのですが、最終的には以下が実施できました。

  • 既存テーブルをRoomのEntityとして再定義
    • Stringの配列で設定されていた既存のテーブルがKotlinのdata classとなったことで可読性が上がりました。
  • SQLiteを呼び出していた箇所の一部RoomのDao化
    • Dao内に定義しているQueryアノテーションでSQLが書けるので何をしているのかすぐに把握できるようになった。
    • さらにRoomには決まった形で使われる挿入や更新、削除はコンビニエンスクエリとして事前に定義されたアノテーションが存在するためSQLを書く手間が省け、小さいですが実装時の工数削減になりました。
    • RoomのDaoに置き換えられた箇所では、ジモティーではRxをまだ使用しているのでSingleを返却するようにでき非同期実行できるようになりました。(アプリ全体としてKotlin Coroutinesへの移行を行っているのでどこかのタイミングでsuspend functionに変更する予定です。)
  • SQLiteからRoomへの置き換え時に発生するマイグレーション処理の追加
    • Migrationを使うことで各スキーマバージョン単位でマイグレーション処理を記述することができるため、処理が追いやすく、メンテナンスしやすい状態になりました。
  • SQLiteOpenHelperをSupportSQLiteOpenHelperに置き換え
    • これにより既存のSQLiteの実装を壊すことなく、Room側のSQLiteに移行することができ、今後他の箇所のDao移行も行えるようになりました。

まとめ

今回移行してみて、置き換えたことにより非常に可読性が高く、UIスレッドをブロックしないように作れるためパフォーマンスも良いアプリになっていくだろうと思っております。

今回置き換えを行っていて、途中で方針転換をしないといけなくなったり、リリース直後にマイグレーション周りで不具合を出してしまったりと進め方として改善すべき点も見えてきた経験でした。

今後はSQLiteの処理からRoomのDaoに置き換えることができていない部分がまだまだあるので、そちらも随時進めて行きたいです。

弊社iOSアプリにアーキテクチャを導入してみた ~計画編~

はじめに

サーバサイドチームに所属している丁(てい)です。

前回の記事弊社のiOSアプリにアーキテクチャを導入する前の状況とアーキテクチャを導入してどう変わったのか?をスーパーざっくりご紹介させていただき、その記事を皮切りにアーキテクチャ導入過程の紆余曲折記事を順番に書いていくことを予定していたのですが、その後全く気が向かず長いこと放置していました。

4月に入り気候も少し暖かくなってきたこともあり気が向いてきたので、本日はアーキテクチャ導入当初のお話をもう少し詳しくお話しできればと思いますので、気が向いた方は暫しの時間お付き合いいただけますと幸いです。

導入計画の策定

アーキテクチャを導入しよう!ということは決まりましたが、意気込みだけでは何も前に進みません。 そう、何をどうしていくのか?という計画が必要になります。 そこでまずはこんな項目を網羅した導入計画書を作成しました。

・目的
  ・アーキテクチャを導入することの素晴らしさについて嘘をつかない程度に誇張表現を交えつつ400字程度でまとめた。
・方針
  ・MVP+CleanArchitectureを採用するメリットなどをなるべくわかりやすく400字程度でまとめた。
・進め方
  ・担当者が誰でどの画面から着手してどの順番で進めていく。。。などをもっともらしい文章で800字程度でまとめた。
・ガント
  ・進め方をベースに週単位、月単位でスケジューリング。

実際のガントイメージ f:id:jmty_tech:20210427155317p:plain

この導入計画書はチーム内の意識共有のためという側面ももちろんありますが、主目的は他部署に対する説明です。

アーキテクチャ導入はリファクタリングの範疇なので長期的視点に立つと生産性の向上に大きく寄与するのですが、短期的には特に非エンジニアの方から見るとメリットをいまいち把握することが難しいです。

また画面単位で大きく手を入れることになるのでその期間は該当画面に対するエンハンス案件を回すことが難しくなり、仮にビジネスサイドの人が「この画面の改修案件進めたい!!!!」って思っても、「いやいや今リファクタリング中だから無理っす。。。」というなんとも気まずい空気を作り出す危険性を孕んでいます。

そう言った認識齟齬や納得材料として非エンジニアの方にもある程度納得いただけるように少し時間をかけて導入計画書を作成して他組織に展開して同意を獲得する作業を一番最初に行いました。

ここで一番効果があったのはやはりガントをある程度ちゃんと引き共有して、該当画面の作業期間中は事前にエンハンス案件検討から外してもらえるように調整できたことで、組織間コンフリクトを少なく抑えることができたことだと思います。

回帰テストケースの作成

計画書を作って全体共有もして、さあいよいよ待ちに待ったコーディングだ!!!。。。とは残念ながら行きません。

アーキテクチャが適用されていない画面にアーキテクチャを適用しようとするとかなり膨大な修正となり、(Objective-Cで作られてる画面など)場合によっては完全リプレースとなる大掛かりな修正となります。

アーキテクチャが適用されていない画面はほぼ全てのビジネスロジックがViewControllerに無秩序に記述されているのでその部分にガッツリ手を加えるとビジネスロジックが簡単に壊れることは想像に難くありません。

また画面の仕様を全て表す仕様書などがあればそれを拠り所とすることは可能かもしれませんが、日本全国津々浦々のどのシステム開発現場においても、現状の機能と寸分違わない仕様書の存在は都市伝説だと思っています。(偏見) ※ 日々刻々と変わっていく仕様を全てドキュメントに落としていくのは無駄という側面もありますしね。

したがってアーキテクチャ適用後もビジネスロジックの挙動に変化がないことを何かしらの手段で担保する必要があるのですが、我々は画面別に回帰テストケースを作ることで担保する方針としました。

回帰テストケースイメージ f:id:jmty_tech:20210427155011p:plain

ここで言う回帰テストケースとは「画面の全ての機能を網羅したぽちぽちテストケース」のことを指します。 ※ 「ぽちぽちテスト」とは自動テストじゃなく人間の手で行う動作確認テストのことを指しますが、この言葉を使ってるのは私だけかもしれません。

実装者はまず担当画面の仕様をくまなく洗い出すために以下の二つの切り口で画面の全機能を洗い出していきます。

  • FatViewControllerを頑張って読み解いて機能を洗い出す
  • 対象の画面をぽちぽち触りまくって見てソースリーディングで見落とした機能がないかを洗い出す

もしソースが綺麗に分割されていて洗練されていたら後者の作業は必要なかったかもしれませんが、残念ながらそうではなかったので非常に地味でつらい作業ですがこの過程を無視することはできませんでした。

この地味で孤独できつい作業を一通り終えて乗り越えたらいよいよ本番のアーキテクチャ適用作業に取り掛かることができるようになります。

今回のまとめ

iOSアプリへのアーキテクチャ適用に関する記事の2回目ですが、いまだにXcodeのXの字も出てきませんね。

ただし広範囲にわたるソースコードの改修は関係各所至るところに大きな影響を与えるので、前準備をしっかりすることがかなり重要なキモとなります。

今回ご紹介させていただいた内容の範疇だと以下の2点ですかね。

  • リファクタリングをスムーズに進めるためには計画をしっかりと立てて、他部署への共有をしっかりとしましょう。
  • 大規模改修の際はできるだけ緻密なテストケースを作りましょう。(回帰テストケースは仕様書と同様にその後の画面改修の仕様に追いつかせるのが大変(無理?)という課題はありますが。。。)

次回はいよいよ導入編に入る予定ですが、また気が向かない期間が長くなりそうな予感はしてます。

気が向いたら書こうと思いますので、その時にはまたお付き合いいただけますと幸いです。

学生プログラマと社会人エンジニアの違いについて

自己紹介

はじめまして。ジモティーで2020年4月からエンジニアをしている水上と申します。 前項を担当した阿部と同じく新卒での入社をいたしました。 学生時は情報システムを専攻しており、ジモティーには一月ほど実務インターンを経て入社いたしました。

いくつかインターンを経験したのですが、その中でも、人間関係が非常によく、意見の言いやすい環境が非常に魅力的でした。会社説明会時に現弊社取締役が述べた

「うちに嫌なやつはいない」

そんな言葉を体現している労働環境に惹かれ入社する運びとなりました。

まえがき

実際に入社してから1年が経とうとしていますが、いろいろなことを経験させていただきました。 私の担当記事では学生プログラマと社会人エンジニアの違いについて感じたことを書かせていただこうと思います。

これから先、弊社でも新卒採用も増えてくるのではないかと考えているため、こちらの記事が学生の目にとまり、そして就職活動に役立つことを願っています。(あわよくばジモティーで一緒に働けると嬉しいです)

学生時代

当時出身大学では地域をあげたハッカソンが開催されていました。

ハッカソンとは 出資企業を募り、各社エンジニアを派遣し、学生+αが2日間でプログラミングを用いた成果物を作成 それらを出資企業が評価し、表彰を行う催しです。

そのハッカソンに参加していた私は、実際のエンジニアさんと触れ合うことで非常に貴重な経験をできたと思っています。 そのときに感じた学生と社会人の違いを今回述べていきます。

学生プログラマと社会人エンジニアの違いについて、入社後1年経って思うこと

当時学生から見たエンジニアは非常に頼もしく、作りたいアプリケーションの説明をするとすぐにおすすめのツールや言語等を提示してくれました。さらに、開発時に難所があれば、颯爽と解決策を提示してくれる等、ありありと社会人エンジニアの凄さを見せてくれました。

それらの根幹にあるのは

  • 経験量

  • 知識量

  • 解決策の調べ方

そして、それらが身につく環境だと思っています。

社会人エンジニアは仕事(プログラミング)に対して報酬をもらっています。 対して学生プログラマは趣味や学術の延長線上です。(私の場合のお話です。もちろん学生さんでも責任感をもって報酬を対価にプログラムを作成している場合もあるかと思います。) 決定的に違うのは

  • 自身の成果物に対する責任感

だと思います。

当時、私はプログラミングを用いたソフトウェア開発をやっていましたが、そこまで期限に追われず、また自分しかコードを見ることが無いため、「動けばよかろう」の精神で作成していました。 入社後基礎知識の学習を終え、実務に入ったところ多量のコーディングルール違反によるシステムメッセージが発生してしまったことをよく覚えています。

社会人エンジニアは、自身の成果物の向こう側にその成果物の利用者、成果物の編集者など、関わる人数が学生に比べて非常に多いです。 加えて、学生時代と比べて自身の制作物が正当に厳しく評価されます。会社はそのソースコードを用いて売上を出しているため、中途半端なものを出すわけには行きません。 また、差配された案件によっては、要件通りに作成するばかりではなく、エンジニア観点からの作成方法の提示や、更に良い案のエスカレーション等の能力が必要になることもありました。

そのような経験を責任感を持ちながら積むことで、知識として定着する速度や量が学生と比べて多いと感じました。 解決策の調べ方に関しても、制限時間内に解決するための方法を模索し続けた結果として、早く正しい解決策の探し方が身についていくのだと思います。 実際に社会人エンジニアとなりましたが、日々の業務の中で成長を実感します。(半年前の自身のコードをみると非常に恥ずかしくなります)

おわりに

様々な業務を通して上記の学生と社会人の違いを身にしみてわかりました。最初は自分もハッカソン時に対応頂いたエンジニアのようになれるかと不安が大きかったのですが、やはり、実務に身を置くことで確実に成長し近づいていけていると感じます。まだまだ経験不足ではあるゆえ、上記の考え方は変わっていく可能性もありますが、この記事を読んでいただいた学生さん、もしくは業界未経験の方たちの参考に少しでもなれば幸いです。 もしジモティーにご興味ありましたら、以下にてエンジニアの方の募集を行っております! jmty.co.jp

新卒エンジニアでも貢献できることはある

ジモティーとの出会い

初めまして。iOSチームで開発を行っている阿部と申します。 本日は「新卒のエンジニアでも課題を克服することで、会社の成長に貢献できる」ということを体験談を元にお話しできればと思っています。

(連続して未経験者から・・・という記事が続いてることは目を瞑っていただきたいです🙇‍♂️)

自分は元々、北海道のとある工業大学で「情報技術を使って地元の観光を盛り上げよう」という研究を行っていました。この時点でお気づきの方もいるかもしれませんが、自分は地元が大好きです!

就職活動ではその地元に貢献できるようになるために、自分のスキルを高める会社を探していました。 そんな時に所属していた大学とご縁があったジモティーから内定をいただき1ヶ月のインターン期間を経て入社することを決めました。

・地元と連携し、地域活性のために働ける

・目の前に上場が控えており、成長スピードが高い

・仲間とパートナーを大切にするという文化

この3つの観点が何より魅力的に感じての決断でした。

その後、2020年の4月からジモティーでの新卒採用第一号のiOSエンジニアとして働くことになります。

研修期間から実業務に入るまで

入社してから1ヶ月は基礎的な部分を指定の書籍で学習する(いわゆる新人研修)期間でした。 ※この部分は前回の記事と同様ですね。

その後iOSのコードに触れ、導入しているアーキテクチャを学びながら実際に簡易画面を作ってみるアーキテクチャ研修に入ることになるのですが、この時の自分は「アーキテクチャとはなんぞや」という状態でした。

弊社iOSアーキテクチャはMVP(GUIアーキテクチャ)+CleanArchitecture(システムアーキテクチャ)という形を採っていることは先の記事を読んでくださった方ならご認識あるかもしれません。

f:id:jmty_tech:20201015120550p:plain

※ もし、未読の方がいましたらこちらの記事をご参照ください。

研修を進めていくと、「責務が明確に分かれているお陰で、どのレイヤーでどの挙動を担っているかが分かり易い!」と「なんぞや」状態だった自分でも実感知としてメリットを体感することができました。

その後、簡単な案件を行いながらその中で勉強していくという体勢に変わっていきます。

簡単な案件の中でも新たなテクニックが出現します。汎用性のあるcellを作成してそれを使い回すというものです。 この既存のcellを使うことで開発時間が短縮され、全くiOSを触ったことが無かった自分でもほぼ工数通りに開発を終えることができました。

※汎用性のあるcellのお話も過去のiOSエンジニアの記事に詳細が書かれているのでご参照ください。

このように弊社のiOSの開発では未経験者でも開発を効率的に行える環境が存在し、チームへのjoinがスムーズにできます。

※他にも開発効率化のために様々なツール導入など行っているのですが、それはまた別の記事をお楽しみください。

障害とモンキーテスト修行

さて、ここまで順調のように進んでいた様に見えると思いますがここから軽めの挫折が始まります。 それは自分が担当した機能でボロボロと障害が出てきてしまっていたことです。

弊社では障害のレベルを五段階に分類しており、そのうち4段階目,5段階目は重大障害として扱われています。 入社半年でこのレベルの障害を自分は出してしまい、QCDのQuality(品質)が課題となっていました。

同時期にアプリチームでも自動テストだけでは補えないケースに対応するためにモンキーテストの担当者を立てて、 結合テスト時にできるだけエッジケースのバグを洗い出そうという試みが計画されていました。

そんな個人と組織の課題感がマッチし、自分がiOS開発チーム側のモンキーテストの担当者となりAndroid開発を行っている先輩にモンキーテストをみてもらうことになります。

弊社のアプリチームでは、リリース日の前週木曜日に結合テストAndroid/iOSの両デバイスで同時に行うため、 先輩に結合テスト毎に30分時間をいただきモンキーテストの観点を教えていただきながら修行をつけていただきました。

教わった観点はkibelaにまとめ、アウトプットを出しさらにモンキーテストを実施する、これを3ヶ月続けていくことになります。

成果と成長

ざっと教えていただいた観点を書くと

- 並列と上下を考慮する
   - 構造的なデータ
       - 上下・並列の関係に位置するデータが選択される場合データの不整合が起きないか
   - UI観点
       - 表示が不必要に重なっていないか
       - アクションイベント時に不要な箇所が連動していないか
- ユーザが繰り返し使う機能は要注意
- 実際にはバシバシ負荷がかかる使い方をされるので思いっきり負荷をかけてみよう
- 見え方は問題ないが通信で余計な情報を送っていないか

などなどでした。(もちろんこの他にもまだまだありますが)

この様な観点を教わり、着々とモンキーテスト担当者としての役目を全うできる様になりました。 チームで行う結合テストの際に高負荷時にだけ起きそうな不具合の発見など、着実に成果としてチームへ貢献できていました。 もちろん、個人の課題でもあった障害の数も着実に減っていき「今月一回も障害出してない!」というところまで到達です。

さらに、この修行は別の箇所でも生かされることになります。

エッジケースやユーザの使い方をモンキーテストで考えるため、構造化された考えが身につき始めたのでしょう。 ディレクタから要件をヒアリングする際にも細かな仕様まで目が届く様になり、見落としがちな部分などをヒアリングできる様になっていました。 案件遂行のための成長にも繋がっていたのです。

この様に弊社では、個人と組織の課題を結びつけ個人の成長と組織の成長を結びつける習慣があります。

これは、

・自分の成長を実感できる

・組織への貢献も実感できる

とモチベーションが上がる2つの実感を同時に実現できる文化であると考えています。

この文化のお陰で「考え方」のスキルを身に着け、新卒エンジニアながら組織への貢献も行えたのでしょう。

まとめ

今回は新卒のエンジニアの失敗談を元に成長できる文化の一端を書かせていただきました。

今回の記事が新卒エンジニアの方や未経験の方の考え方の参考になれば嬉しいです。 また、これまでの記事で弊社の文化・技術に興味持たれた方がいらっしゃれば、この先ご縁が生まれると嬉しいです。

自分も次回執筆までにはtechのことをお伝えできる様にさらに勉強していきます!

最後になりましたが、ここまでお付き合いいただきましてありがとうございました。 もしジモティーにご興味ありましたら、こちらでエンジニアの方を募集しております!