Androidプロダクトのアーキテクチャの過去未来

はじめに

 ジモティーでAndroidアプリを開発している杉田です。

 この記事では、ジモティーのAndroidアプリのアーキテクチャの変遷とそれを通してチームが成長していった話を書きます。そして最後に現状とこれからの方向性に触れます。

アーキテクチャとは

 プログラムの設計思想のことです。プログラムを大きな責務の単位ごとにコンポーネントで区切ります。そうすることでどこに何を書いてあるかがわかるので、チームに参加したばかりの開発者でも開発がしやすくなります。

アーキテクチャ導入前の課題

 私が入社した2017年当時は、Androidチームには共通認識としてのアーキテクチャがありませんでした。それどころかほとんど全てのコード(ビジネスロジック、通信処理、DB周りの処理)はActivityに書かれていました。そのため以下のような課題がありました。

  1. ビジネスロジックが共通化されず、色々なActivityで重複して記述されている
    • ビジネスロジックに変更が入ると、同じロジックが入っている全ての画面に変更を加える必要がある
    • 重複したロジックの変更が漏れて、バグが発生する
  2. 複数の役割を持った超巨大なメソッドが存在し、その変更によって思わぬバグが発生する
    • 例えば、巨大メソッドの最初に出てくる変数の値を変更したときに、その変数をメソッドの下の方でも参照していてバグが発生する
  3. Activityに色々な処理が書かれているため同時に同じActivityの改修作業をするとコンフリクトやデグレが発生する

 上記の様な状態なので、チームとしてもバグが頻発する状態ですし、3年前に新人として入社した私はバグをしょっちゅう出していました。  

 リリースの度にリグレッションテストにかなりの工数を取られ、リリース当日はビクビクしながらリリース結果を見守っていました。リリースの度に心理的疲労が溜まっていく状態でした。

 この状態にチーム全体の危機意識が高まり、どこに何を書けば良いのか明確なルールを作ろうという動きが始まりました。

アーキテクチャ導入に向けて格闘する日々

 まず最初に始めたのは、Activityに集中している処理を分離する方法を模索するところからでした。

 処理の分離の単位として下記の候補が上がりました。 - GUIロジック - ビジネスロジック - 通信処理やDB周りの処理 

 この処理の単位で分離する方法として、GUIアーキテクチャとシステムアーキテクチャを導入したら良いのではないかという案が出て、話し合われました。

・GUIアーキテクチャ・・・主にUIにあるロジックとシステム関連のロジックを分離するためのアーキテクチャ
・システムアーキテクチャ・・・通信処理やDB周りのロジックを分離するためのアーキテクチャ

 そこでGUIアーキテクチャとシステムアーキテクチャの組み合わせで注目されたのは、以下の組み合わせです。

  1. MVP + Clean Architecture
  2. MVVM + Clean Architecture
  MVP MVVM
メリット ・Viewと表示のためのロジックの分離がシンプルにかける ・よりモダンなアーキテクチャである。
・データバインディングと組み合わせることで、Viewに値をセットするコードを省略できるので、より少ないコード量で実装できる
デメリット ・Viewに値をセットするためのコードが必要なため、記述量が多くなる ・実装が複雑になる。検討当時、Activityのライフサイクルと非同期処理のライフサイクルが合わない時にケアするコードが大量に必要

 当時チームで議論した結果、MVVMの方がActivityのライフサイクルと非同期処理のライフサイクルが合わない時にケアするコードが大量に必要で、ライフサイクルをうまく合わせるための知見がなかった私たちには難しそうだということでMVPを採用することになりました。

 また、システムアーキテクチャとしてClean Architectureが流行していたのと、当時アーキテクチャ導入のために参画してくれた技術顧問の方がMVP + Clean Architectureの導入経験があり、MVPの方がチームに導入しやすいということでClean Architectureを採用することになりました。

▼導入後のアーキテクチャはこんな感じになりました。 f:id:jmty_tech:20201009105843p:plain

 アーキテクチャの導入にあたって、全員に知見が行き渡る様に、全員が順番に工数をとって導入を行っていきました。ただし、全員が実行するにしてもメンバー間でプロダクト仕様の理解に差があるため、下記の様な分担の方針を建てました。

仕様の理解が深い人 新人などの仕様理解が浅い人
・ビジネス上重要な主要導線の画面
ビジネスロジックが複雑な画面
・開発規模が小さく、ビジネスロジックが少ない画面

 最初はチームリーダーが一つの画面にアーキテクチャを導入し、その知見をwikiにまとめてチームに共有しました。その後各メンバーがアーキテクチャ導入する際には、クラス図を書いて設計レビューを行ってから実装を行いました。その結果、実装前からアーキテクチャに対してある程度の理解を持つことができたので、各自のアーキテクチャ導入がスムーズに進みました。

アーキテクチャ導入の成果

 ここからはアーキテクチャを導入した結果を説明します。

アプリの品質が向上

 まず、メンバー間の技術レベルを問わず、ある程度の品質を担保できるようになりました。新人だった私もアーキテクチャの概念をキャッチアップすることで、何が良いコードで何が悪いコードなのか、それがなぜなのかを理解する助けになりました。また思想が同じなので、私が書いたコードと先輩が書いたコードの品質に大きな乖離はなくなり、レビューでも先輩に対して指摘しやすくなりました。  

 次に、デグレによる障害が劇的に減少しました。これはプログラムをコンポーネント化することで、同じ画面を開発した時にコンフリクトを起こすことがほとんどなくなったためでした。  

iOSにも同じアーキテクチャが適用できた

 さらに、もう一つ想定外の成果がありました。それはプラットフォームに依存しないアーキテクチャを採用したので、iOSにも同じMVP + Clean Architectureを導入できたことでした。その結果、iOSチームとAndroidチーム間でメンバーのコンバートを行う時のスイッチングコストが激減しました。  

 その結果、iOSAndroid両方を開発できる人が増えたので、プロジェクト実行時の人材配置が柔軟になりました。また、iOSチームとAndroidチーム間の意見交換が活発になり、アプリチーム全体でプロダクトをよくしていこうという思考になりました。

アーキテクチャのこれから

次の課題

 Androidは最終的に、主要導線の画面だけにアーキテクチャが導入されました。まだアーキテクチャが導入されていない画面も残っています。

 アーキテクチャが導入された画面にも問題がないわけではありません。緊急案件などがあり、設計せずに継ぎ足したコードがあるせいでアーキテクチャが崩れてしまっている部分もあります。設計されている画面でも、MVPを採用したことが原因で、ボイラープレートコード(お約束で重複して書かなければならないコード)が量産されていて、そのせいでコードベースが多少膨らんで生産性が良いとは言えない面もあります。  

 また、アーキテクチャ導入時に試行錯誤をしたコードも残っています。MVP + Clean Architectureの後に一時MVVM + Clean Architectureを目指した時期があったため、MVPの代わりにMVVMを導入した画面も存在しています。

 さらに、例えば、MVP導入時に非同期通信ライブラリにRxJavaを採用しましたが、サードパーティライブラリは今後メンテナンスされ続けていく保証がありません。そのため、なるべくAndroidプラットフォーム標準のライブラリを活用したいところです。

 つまり、プロダクト全体としてみるとアーキテクチャがバラバラになっていて、MVPが適用されている画面に関してはボイラープレートが多いため生産性が上がりきっておらず、中には歴史的経緯でアーキテクチャ化した後にコードの設計が崩れてしまっている部分があるのです。

これからの方針

 これからの方針ですが、Androidチームは崩れてしまったコードベースを改善するためにMVVM + Clean Architectureに切り替えていく検討を始めています。

 2017年にアーキテクチャを導入した時に比べると、Androidプラットフォームは大きく進化しました。当時は、MVVMへのAndroidプラットフォームのサポートがなく、技術的に導入が難しかったのですが、現在はAACAndroid Architecture Components)を導入することで比較的簡単にMVVMを導入可能になっています。

 MVPからMVVMにアーキテクチャを切り替え、全画面にMVVMを適用することによって、下記の課題が解決することが見込まれます。

  • アーキテクチャの混在によって、コードの見通しが悪くなる
  • MVPを採用していることによる大量のボイラープレート
  • Androidプラットフォーム標準のライブラリを活用できていない

アーキテクチャの混在によって、コードの見通しが悪くなる

 これは説明しなくてもご理解いただけると思いますが、MVVMにアーキテクチャが統一されるのでコードの見通しは良くなります。

MVPを採用していることによる大量のボイラープレート

 MVPを採用したため、Viewへの値の設定や通信処理とActivityのライフサイクルの調整の処理が大量にボイラープレートとして書かれています。  

 AACを導入することで上記の様なボイラープレートをかなり削減できることが見込まれます。

Androidプラットフォーム標準のライブラリを活用できていない

 非同期処理にRxJavaを使っていましたが、AACとKotlinのコルーチンを組み合わせることで代替できるなど、2017年当時にサードパーティーライブラリに頼らざるを得なかった機能についても標準ライブラリでかなり補える様になっています。

その他

 MVVMの導入時に、先に述べた継ぎ足されたコードの設計も見直し、より開発がしやすいコードに生まれ変わらせていく予定です。

最後に:みなさん待ってます!

 上記の様な方針で進めて、開発生産性をあげ、サービスの成長にガンガン貢献できるチームになっていきます!

 Androidチームでは、この今後の改善に一緒に取り組んでくれる方を募集しています!

 一緒に頑張りましょう!!

ジモティーのデータ活用フローのご紹介

ジモティiOSチーム所属のエンジニアの橋本です。

普段はiOSアプリの開発に従事していますが、 Webやネイティブアプリ(iOS/Android)の各種計測データの収集や社内への展開などの業務にも従事しています。

今回は、自分が担当しているデーター活用周りでの取り組みのご紹介をしたいと思います。

組織のコンディション判断と意思決定に利用されるデータ

Webアプリやネイティブアプリ(iOS/Android)が生み出す様々なデータは

収集・蓄積・加工  ▶  分析・活用

という過程を経るわけですが、その利用目的は大きくは2つです。

  • ジモティーというサービスの現状がどうなのか、 サービスのコンディションの善し悪しを判断するための利用
  • ユーザーの利用状況の傾向を把握し、次の打ち手を決める判断材料としての利用

この利用目的を達成するためにデータをどのように利用者に届けるかが重要となります。

エンジニアだけが利用するのであれば,BigQueryなどSQLが実行できる基盤・インターフェース(以下,SQL I/F)を用意しておけば事足ります。

しかし,ビジネスチーム(ビジネス企画,マーケティングなどを担当)やカスタマーサポートチーム(ユーザからの問い合わせ対応、ジモティーの運用ルール策定を担当)にSQL I/Fだけを提供すると、簡単なデータ取得・分析であればよいのですが,ある程度複雑なものになってくるとエンジニアがサポートする必要があります。

SQL作成で手間がかかっていると,ビジネスの意思決定のスピードが遅くなりますので,ある程度複雑なSQLが必要でKPIなど重要指標に関わる数値など,サービスのコンディションを確認するために必須な要素については自動的に取得してデータや分析結果を自動で必要な社員に送付する仕組みも整えています。

次の節からジモティーのデータ分析基盤の構成要素とデータがどのようにエンドユーザー(データ利用者)まで流れていくか図解しながら説明したいと思います。

データ基盤の大きな構造と利用フロー

データ基盤とSQL I/Fについては弊社のSREチームが2016年の段階で整備を進めており,その上でSQLの社内教育もあわせて進め,ビジネスチームメンバーの大半がSQLを書けるまでになりました。

Redash + Redshift + embulkでデータ分析基盤を構築した話

しかし,ある程度基盤整備とSQLの教育はできたものの,時代の変遷と共に例えば,ネイティブアプリのデータ収集・分析に使用していたGoogle Analyticsが廃止になりFirebaseに移行したり、 SQLの実行スピードやコスト面のメリットでRedshiftからBigQueryに移行するなどサービス規模の拡大と技術の進化にあわせてかなり構成が変更されています。

現在は,データ分析基盤はBigQuery中心の構成になっており、各種データは一度BigQueryに集約してからSQL I/F,Google Spreadsheetやメールを含めフロントエンドに(分析)データが供給されています。

下記にデータフローの観点での見取り図を示し,以降は図中に示した番号毎に説明していきます。

図1. 分析用データのフロー観点での見取り図 

分析用データのフロー観点での見取り図
分析用データのフロー観点での見取り図

[1]BigQuery

以前は、データ分析基盤の主軸としてAmazon Redshiftを利用していたのはこの記事の通りで、下記のメリットをかなり享受できました。

  • AWSで構築している既存サービスとの親和性
  • クエリに依存せず固定額(SQLに不慣れなメンバーも実行する前提なので)
  • データ量がまだそれほど多くないので安価に始められる

しかし、分析の幅を広げるため、分析対象をRailsアクセスログまで拡張したい要望があり、大幅に分析するデータ量が増加しました。それに合わせて、改めてSQLの実行スピードといったパフォーマンス面とコストメリットの部分で検討をして、2017年にBigQueryの利用を開始しました。

当初はRedshiftとBigQueryを併用していたのですが、SQLの利用面で両方で持っているデータで JOIN(テーブルの結合)ができないデメリットがあり、2018年にBigQueryにすべてのデータが集約されました。

また、結果的にではありますがネイティブアプリのデータ収集・分析に利用するFirebaseやGoogle Spreadsheet、 Google Apps Scriptとの親和性が高かった(API連携が非常にやりやすかった)点もBigQueryに移行して良かった点です。

[2]データ転送はembulkとfluentd

データ転送にはOSS の データ転送ソフトウェアの emublk と fluentd を使用しています。 個々のRuby on Railsが動作するサーバー から出力されるアクセスログは fluentd によってAmazon S3に転送されて集約されます。

mongodbやAWS Aurora、 Amazon S3上のアクセスログ から BigQuery の転送には 現状は基本的に日次でデータを転送しています(アクセスログについては1時間毎に転送しています)。

embulkとfluentdのメリットは、 プラグイン機構によって様々なデータベース/データストレージ/ファイルフォーマットに対応でき、結果、連携先が増えても比較的新しく覚えることが少なく、対応にスピード感が出る点だと思います。

[3]FirebaseとBigQueryを連携

Firebase の Bigquery Exportを使用して、iOS / Android のネイティブアプリのイベントデータを蓄積しているFirebaseとBigQueryを連携させています。 BigQueryの転送先のスキーマ定義もカチッと決まっているので、慣れるとSQLも素早く書けるようになります。 このFirebaseのデータとRailsアクセスログを組み合わせて分析することも多いです。

[4]Redash

弊社のSQL I/Fの要となるツールで、SQLの実行はもちろんのこと、下記のようなことも可能です。

  • ビジュアライズ : クエリの結果から円グラフ、折れ線グラフ、散布図などを描画
  • スケジューリング : 保存したクエリにスケジュールを設定し定時実行できる

Redashについては、当初、不具合も散見されましたが、弊社SREチームの吉田が、Redash コミュニティーに不具合の修正パッチをちょくちょく送っていました。そうしたら、いつの間にか吉田がRedashのコミッターになっていて、吉田と昼休みにご飯を一緒に食べているときに聞いてびっくりした覚えがあります。

弊社のRedashに保存されているSQLの量は年々着実に増えており、Redashと共に弊社のデータ分析文化も成長していっている感じがします。

[5]Google Apps Script /[6] Google Spreadsheet /[7] Gmail

前述の通り、 ビジネスチームに対するSQL I/Fの提供だけでは、

  • 複雑なSQLが必要な場合にエンジニアがサポートが必要な点
  • ある程度複雑なSQLが必要で定期的に確認する必要があるKPIなど重要指標に関わる数値が存在し、SQL I/F だけではその確認が困難な点

といったことに対応できないので、重要なデータや分析結果を自動でGoogleSpreadsheetに反映したり、メールで必要な社員に送付する仕組みも整えています。

[5]Google Apps Script

Google Apps Scriptを利用して、BigQuery・Google Spreadsheet・GmailAPI連携してBigQueryからデータを取り出し、必要なデータをGoogle Spreadsheetとメールに出力しています。

Google Apps Script についてはGoogle Spreadsheetと紐付けて管理しており、claspというツールを利用してローカルの開発環境のスクリプトGoogle Spreadsheet上のスクリプトを同期させます。これにより、ローカル開発環境のスクリプトGithubで管理できるようにしています。

[6] Google Spreadsheet

ビジネスチームのメンバーはSQL自体はRedash上で開発して、定期的に確認しなければならない分析データ(例えば、サービス上の新しい施策の状況確認等)はRedash上ではなく、Google Apps Scriptを定期実行して日次で自動的にBigQueryからデータを取得してGoogle Spreadsheetに出力して確認します。

ビジネスチームがGoogle Apps Scriptを書くわけではなく、Google Spreadsheet上に用意されたSQLタブにSQLと反映するタブ名、取得開始日次、取得終了日時を記載すると自動的に定期実行して、結果を反映するフレームワークGoogle Spreadsheet+Google Apps Script のテンプレート)をエンジニア側が開発して、それをビジネスチームに使ってもらっています。

これらの仕組みのおかげで、ビジネスチームが自分たちの要求に応じてスピーディーにデータの分析と定期的な確認ができるようになりました。 以前のBlogに記載されていた下記のような状況は遠い過去のものとなりました!

これまでは、

「ディレクターがデータ抽出を依頼→エンジニアが指定されたデータをCSVに出力して渡す」

という形になっていました。

データの抽出の依頼が週に5、6件発生し、1件毎にエンジニアの工数が数時間取られるという状況です

[7] Gmail

弊社では、KPIメールというジモティーのサービスのコンディションを診断するためにWebアプリとネイティブアプリ(Android/iOS)の厳選された指標データを当日から30日前までの分をリスト化して毎日2回、社員に送信するようにしています。

このKPIメールにより、直近のサービスの状況を全社員が毎日、日次の変化を含めて確認することができます。何か指標に異常があった時に原因を含めて同じ数字でチーム内で議論できますので、社内での数値に対する関心を高める効果と共にコミュニケーションツールとしても非常に役立っています。

[8]Google Analytics

Webアプリに関するデータ分析に関しては、Google Analyticsを長年利用し続けています。

今後の展望

以前と比較してかなり、データ分析基盤は整ってきましたが、先進的な企業と比較するとまだまだやることがたくさんあります。

SQLを使った分析を更に容易にする

全社的にSQLの活用がかなり進んできていますが、複雑なSQLを組むときはエンジニアのサポートが必要な状況です。これは、アクセスログやFirebaseのイベントデータなど複雑なテーブルに対してそのままSQLを組むとどうしてもSQLが複雑になるのが原因です。

そのため、一度複雑なデータに関しては分析しやすい中間テーブルに分解して、自動的に中間テーブルにデータを流入させるデータフローを構築する手段が考えられます。

中間テーブルの設計がかなり難易度が高そうですが、実現できればSQLを書くのがかなり容易になると期待されます。

ストリーム(即時)データの分析

現時点のデータ分析基盤では一番鮮度が高いデータでも1時間前のデータです。 現在のジモティーのサービスではそこまで即時性の高いデータは必要ないのですが、エンジニア側が障害や異常があった時に即時性の高いデータが必要になります。 各種、開発者向けのモニタリングツールでも原因の推定はやれなくもないのですが、アクセスログなどのデータがすぐに参照できた方が障害・異常の原因特定はかなり容易になります。

かつてその目的で kibana を導入したことがあったのですが、サービス規模が巨大になりログ転送含めて運用がかなり大変になったため、使用をやめています。 こちらも kibana の代わりにうまく大量データを非同期で投入できるようなストリームデータ分析基盤の導入が待たれます。

現状、案として出ているのが flutnd + BigQuery streaming insert なのでこちらを試すところから始めたいですね。

データの可視化、ビジネスダッシュボード

現在データを可視化するのにGoogle SpreadsheetやRedashのグラフツールを利用していますが、 ストリームデータを扱えるようになったらKPIの状況などをリアルタイムに可視化できる基盤の導入なども行えるとよいと思っています。 まずは手始めにGoogle Data Studioの活用などが考えられるでしょう。

終わりに

というわけで、ジモティーは絶賛エンジニア募集中です。 データ基盤の整備をやってみたいという思われた方、課題は本当にたくさんあります!ぜひ一緒に取り組んでいきましょう。 よろしくお願いします!

ISUCON 10 予選参加も1139点で見事敗退 また来年

こんにちは、ジモティーエンジニアの吉田です。

普段はジモティーのバックエンド (Rails) とインフラを担当しています。2020/9/12 (土) に行われた ISUCON 10 の予選に参加したので、その内容をご紹介します。

ISUCON とは

ISUCON とは、お題となるWebサービスを決められたレギュレーションの中でチューニングして、そのスコアを競い合う大会です。

いい感じにスピードアップコンテスト、略して ISUCON (Iikanjini Speed Up Contest) のゆるい名前とは裏腹に、今年で10回目、参加チーム数は490組(1チーム最大3名)と国内でも比較的規模の大きいイベントです。ウェブ・インフラエンジニアであれば参加した事がなくても、一度は耳にした事のある方が多いと思います。

予選を勝ち抜いた上位30チームが本戦に出場し、優勝賞金はなんと100万円です。賞金額も大きいですが、業界でも有名なエンジニアがたくさん参加していて、その中で本選に出場できる事はスキルの高いエンジニアとしての証明にもなります。

チームメンバーとモチベーション

チームのメンバーは、まず、暑い季節もスカッと爽やかなギャグを飛ばす H さん、以前インフラとバックエンド、今は iOS を担当しています。次に、ビジネスチームとのブリッジングや仕様策定にとても強く、以前は主にバックエンド、最近は Android も担当している S さん、それに自分の3名です。

ジモティーではこのように複数の担当領域を兼務しているメンバーが多いのが特徴の1つです。

他の2人は初参加ですが、自分は過去に ISUCON 8 に参加した事があります。その時は再起動試験で失敗したのか、スコア0の残念な結果に終わってしまいました。

毎年この時期にタイムライン上で ISUCON が話題になると過去の記憶が蘇り、「あの時こうしておけば」「今の自分だったらどこまでいけるのか」といった思いに馳せる大会経験者は多いのではないでしょうか。ISUCON 9 はタイミングが悪く不参加に終わりましたが、技術研鑽よりもこういった思いが強く、参加を決めてすぐにメンバーを募集しました。

当日の朝から終了まで

前回参加時の失敗を踏まえて、事前に打ち合わせをして、担当や実施内容のおおまかな確認を行いました。プログラミング言語は複数から選択することができ、ジモティーでもバックエンドのメインで使用している Ruby を選択しました。

12:20に開始し、まずは準備していたプライベートリポジトリにアプリのソースコードや設定ファイルを登録して、初回のベンチマーカが無事成功する事を確認しました(スコア: 410)。

その後、インフラ周りのタスクとして alp のインストールや Nginx のログフォーマットを変更したり、Mackerel エージェントをインストールなど実施しました。alp で確認したところ、検索のエンドポイントが圧倒的に遅いのでここをなんとかしたいよね、と当たりをつけます。

ベンチマーカの挙動を確認した後、インデックスの追加でクエリの実行速度を改善できないか検討しますが、すぐに手を付けるのが難しそうだなと話しました。自分は Nginx の設定を変更してみたのですが、ベンチマーカとポータルが不安定で、変更の影響が不明なため、アプリ側をじっくり確認する方針に切り替えました。

16:00頃get '/api/estate/low_priced'get '/api/chair/low_priced' の結果を常に DB から検索していましたが、キャッシュ化できそうだったので Memcached をインストールし dalli 経由でキャッシュしました(スコア: 543)。また、get '/api/recommended_estate/:id'SQL クエリを改善し、以後参照のない変数で mapmap! に置き換えました(スコア: 558)。

その後、DB をインメモリ化しようとしてしばらく色々とやってみたのですが、ベンチマーカがことごとく失敗し作戦は断念しました。細かい改善をしながら、スコアが徐々にしか上がらず苦しい時間が続きます。

17:17頃、突如メインのサーバに SSH で接続できなくなり、Mackerel からも接続不能のアラートが飛んできたため、運営にマシンの再起動をお願いして事なきを得ました。この間ベンチマーカを実行できない事から、2台目と3台目にも同じ環境を構築し、打ち手を並列して試せるようにしました。事前の作戦でローカルには実行環境を構築しない方針にしていたので、これはもっと早い時間に実施しておくと良かったと思います。

18:21頃、ユニットファイルに指定されていた unicorn の実行環境を production に指定したところ、若干スコアがあがりました(スコア: 625)。

18:40頃MySQL のクエリキャッシュと InnoDB の設定を変更して、さらにスコアが伸びました(スコア: 928)。

18:50頃、どうしても DB の負荷が高いので、それまでアプリケーションと同じサーバで起動させていた DB を別サーバにする方針に舵を切ります。ところが設定ミスに気づかず、結局最後まで実現する事が出来ませんでした。estate と chair テーブルもそれぞれ別サーバに分けられそうだよね、と話していましたが、実現にはいたらず、これが一番の失敗だったと思います。

その後も細かい改善を実施しながら、19:00頃に、Nginx で一部の User-Agent のアクセスを一律 503 で返し、ベンチマーカを何度か実行するとスコアがかなり上がりました(スコア: 1066)。

終盤に chair と estate の検索をキャッシュ化しようと粘っていましたが、こちらはベンチマークが失敗し、残念ながら実現には至りませんでした。

ラスト20分はあわてないように予定通り変更をフリーズし、再起動後の動作確認を行って終了を迎えました。

振り返り

メンバーそれぞれができることを模索しながら、スコアアップに向けて手を動かす時間は何事にも代えがたい体験でした。また、仮説を立てて検証し、失敗を繰り返しながら正解した時にはそれまでの苦労がすべて吹き飛んでしまうほどの高揚感は、まさにエンジニアリングの醍醐味でもあります。

しかし、冷静にふりかえってみるといくつものミスや改善すべき点があったのも事実です。クエリの最適化にほとんど手を入れられなかった点、ボトルネックが DB の処理にある事に気づきながら別のサーバに切り出せなかったのは大きな失敗でした。

最後に

後日発表されたスコア(参考値)を確認すると予選突破ラインが 2100 付近だったようで、我々の 1139 ではまだまだ及ばない事が客観的に分かりました。来年こそは予選突破できるようにレベルアップをしたいです。また、ISUCON は普段の業務にもつながるとても素晴らしいイベントなので、社内でも複数チームで参加して感想戦をしたいです。

ジモティーではエンジニアを募集中です!一緒に ISUCON の話で盛り上がりましょう!

ジモティーを支える技術2020(サーバーサイド編)

こんにちは、ジモティーのエンジニアの鈴木です。

タイトルの由来とか

日本に5人くらいいるハードコア・ジモティーウォッチャーの皆様におかれましては「ジモティーを支える技術」という記事が2012年に当時のスタッフブログに掲載されていたことをご記憶されているかと思うのですが、8年の時を経てついにリライトされるわけですね。感慨深いです。

オリジナルの記事はWebアーカイブで見られますのでご興味がおありの方は探してみてください。

ネイティブアプリの技術スタックについてはきっとアプリチームのメンバーが書いてくれると思いますので、今回はサーバーサイド〜インフラ周りについて紹介します。

Webフロントエンド

  • jQuery
  • Vue.js
  • Foundation
  • FLOCSS

古くからある画面はjQuery、新しい画面はVue.jsで構築しています。 Vue.jsのデータバインディングに慣れた結果、jQueryの肥大化したコードにアレルギー反応が出るようになってしまったのが悩みの種ですね(もうレビューすらしたくないんや…)。 隙を突いてVueに書き換えたい。

CSSフレームワークはFoundationを利用しています。 FLOCSSのルールに基づき弊社のデザインガイドラインコンポーネントの整備を進めています。

今後は、Nuxt.jsなどのサーバーサイドレンダリング層を導入して、フロントエンドとバックエンドを疎結合にしていった方が、生産性が高いのではと考え、再構築も検討しています。

Webバックエンド

おなじみのRailsですね。 Railsの「Fat Model, Skinny Controller」の思想に基づきFat Model OKとしてここまで来たのですが、さすがに9年開発を継続しており、メンバーも増えてくるとそうも言ってられないなーという状況です。 サービスオブジェクトの導入については結構うまくいったなーと持っているのですが、それだけだとシステムの複雑化に対抗するにはまだ武器が足りないなーという印象。 ということで、肥大化したModelに対して、再設計して責務を分割していくというリファクタリングを地道に進めています。

開発環境

  • Github
  • CircleCI
  • rubocop
  • brakeman
  • reek
  • Docker

GitHub Flowに基づいて開発を進めています。 またwebhookでコミットがプッシュされるたびにCircleCIで自動テストが実行されるようになっています。 テストとレビューが通ったものだけがmasterブランチにマージできます。 またCircleCI上で、rubocop、brakeman、reekといった静的解析ツールも実行されるようになっており、お行儀の悪いコードを書くと自動的に指摘されるようになっています。

ローカルの開発環境にDockerを利用しており、開発環境構築の手間を減らしています。

デプロイ

デプロイタスクは半自動化されており、Jenkinsのジョブを実行するだけで本番環境にデプロイすることができます。 デプロイの詳細処理はCapistranoで書いています。 ブルーグリーンデプロイを採用しており、リリース直後に障害が発生した場合は迅速に切り戻すことができます。

ミドルウェア

  • Nginx
  • MongoDB
  • Elasticsearch
  • Aurora(MySQL
  • memcache
  • Redis

メインのDBにMongoDBを採用していることが特徴ですかね。 トランザクション制御が必要な場合はMySQLを利用しています。 MongoDB 4.0でトランザクションが追加されるわけですし、全部MongoDBに寄せられるのでは?などと密かに期待しています。

MongoDBはスキーマレスなのでフィールドの追加がめちゃ楽なのですが、それゆえに安易にフィールドが増えがちなので、長期的に開発を継続する際にはデータモデリングをまじで頑張った方が良いです。 まじで頑張ってください。約束です。

データ分析

  • Redash
  • GAS
  • BigQuery
  • Fluentd
  • embulk

Fluentd、embulkを用いてアクセスログトランザクションデータをBigQueryに集約しています。 Redashでデータ分析を行ったり、データを可視化(グラフ化)してます。 ビジネスサイドのメンバーにもSQLを習得してもらっているので、ディレクターがバリバリSQLを書いて分析したりしています。 GAS(GoogleAppScript)でBigQueryにクエリを実行し、結果をスプレッドシートに吐き出す、といったこともしています。

自然言語処理

テキストの解析用途でPythonも使っています。機械学習には欠かせない言語なので今後も活用範囲が広がっていくと思われます。

インフラ

メインのインフラはAWSです。 BigQueryなど一部の用途でGCPも利用しています。

AWSのリソースはCloudFormationで管理しており、サーバープロビジョニングにはitamae、serverspecを活用しています。 もう手順書をみながら手作業でインフラ構築しなくて良いんですね。すばらしい。

サーバー監視にはmackerelを使っています。設定やカスタマイズが簡単で良いですね。

おわりに

8年経つとさすがに進化してるなーというところですが、 一方技術負債もかなり溜まっているのできっちり返済していきたいですね。 個人的にはフロントエンドの再構築に挑戦したい。

ということでジモティーでは新規開発にリファクタリング、リアーキテクチャとやりたいことが山積みですので、一緒に開発してくれるメンバーを募集中です!

デザイン制作が捗るSketchプラグインについて

はじめまして。デザイナーの藤井(理)です。
現在、ジモティーでは様々なページやUIの改修・制作などを同時に取り組んでおり、デザイン制作をする中でクオリティはもちろんのことやはり、スピード感も重視されます。

そんな中、私がデザイン制作をクオリティを意識しつつ・効率よく素早く完了させるために日々、よく使用しているデザインツールがSketchになります。
f:id:jmty_tech:20170512125126p:plain Sketch - Professional Digital Design for Mac

Sketch自体はUIもシンプルで使い方もで簡単に利用できるため、デザイナー以外にも利用されている人は多いと思います。 そんなSketchでデザイン制作が捗るプラグイン3つご紹介させて頂きたいと思います。

Sketchプラグイン3つご紹介

数多くのプラグインが用意されている中でより、制作が捗ると感じたプラグインご紹介させて頂きます。

1.「Sketch Guides」

手作業でガイド引くを手間を省けるプラグイン f:id:jmty_tech:20170511181847g:plain https://celynxie.com/sources/sketchguides.html

オブジェクトに対して上下左右の中央を自動で簡単にガイドを引くことができます。 デザインをする中で必ずと言って良いほど行う作業の一つでもあるため少しでも負担を軽減できるのはいいですね。

2. 「Craft」

プロトタイプで有名InVisionから出ている多機能プラグイン
※Craftの機能の中の「Duplicate」を使用

f:id:jmty_tech:20170512113336g:plain

https://www.invisionapp.com/craft

いくつかの機能を持ち合わせている中の一つ「Duplicate」はデザイン要素を複製でき、要素を垂直・水平にピクセル単位で正確に複製することができて繰り返しの作業がとても楽に出来ます。リストの制作の際などで時間短縮も出来、とても便利です。 その他にもCraftにはダミーテキストや写真を入れられる便利なプラグインなどがいくつか用意されてますので色々な場面でとても便利です。

3. 「Sketch Measure」

実装に必要な情報を自動で書き込んでくれるプラグイン f:id:jmty_tech:20170512113504p:plain https://github.com/utom/sketch-measure

オブジェクトのサイズ・余白・距離・スタイルなど実装に必要になる情報を生成してくれるプラグイン。アートボードをエクスポートすることでワンクリックでHTMLページを自動的に生成しオフラインでCSSスタイルなどの実装に必要なデザイン詳細を見ることができます。エンジニアとの様々なやりとりの効率化出来るので、デザイナーとエンジニア間のやりとりでのプロセスの改善に期待大です。

まとめ

日々の業務の中で小さなことではありますが、何気なくやっていることや完了後に振り返ってみると地味に時間がかかってしまっているような作業(オブジェクト複製作業だったりetc..)を効率化することで当初、予定していた工数見積もりよりも早く終わらせることも出来たりもした案件もありました。

今回は3つのみの紹介ですが、他にも様々な高品質なプラグインがあるので用途などに応じて、今後もプラグインを追加してみてより効率よくデザイン制作を進め、より良いプロダクトを世に出していきたいと思います。

ジモティーでのタスク管理について

こんにちは ジモティーでiOSエンジニアをしている小林です

今回ジモティーで利用しているタスク管理ツール「JIRA」の活用及び利用促進活動をメインで担当する機会があったので、JIRAについて書いてみようと思います!

日頃、誰がどんなタスクをどのくらい抱えていて、進捗はそれぞれどうなっているのか。プロジェクトの管理者やマネジメント者はその辺りを把握するためにタスク管理ソリューションを何かしら使っていると思います。

ジモティーでなぜJIRAが採用されたのか、使ってみてどうだったのかをご紹介していこうと思います!

背景

弊社ではもともとRedmineを利用して課題の管理をしていました。 なぜJIRAにしたかというと、非エンジニアとのタスクについてのコミュニケーションに課題を感じていたからです。

実はチーム単位ではTrelloなど導入していて個々に最適化はしていたものの、全社導入するにあたっての諸要件をクリアできなかったので数あるサービスから消去法でJIRAが候補として残った経緯があったりします。

JIRAとは

JIRA Softwareは、Atlassian(アトラシアン)社が開発した課題管理ツール(プロジェクト管理ツール)です。その高度なカスタマイズ性により、バグ管理ツールの枠を超えて、タスク管理、工数管理、進捗管理、スケジュール管理などプロジェクト全般を広く管理します。複数プロジェクトの進捗やタスクを一元管理します。

JIRA Softwareは、チーム内でのタスクの見える化を簡単に実現します。

スクラム、カンバンに対応しています。 参照:ricksoft

アジャイル開発で課題となるタスク管理、工数管理、進捗管理、スケジュール管理、振り返りが1パッケージで可能で、しかもある程度の見易さ・使いやすさが売りという感じです!

JIRAの良さ

Kobito.RTkna4.png

ジモティーではアジャイル開発を行っているためスクラムモードで運用しています。 スプリント毎にタスク・アサインの管理ができるのが選択のポイントでした。

  1. 誰が何をしてるのか分かる! Kobito.P522It.png 進行中のスプリントが表示されている画面で、進行中のタスクはそれぞれ誰が担当しているのか一目瞭然!

  2. 誰がどれだけ作業しているのか分かる! Kobito.JrHSiR.png 進行中のスプリントでメンバーがどのようなアサイン状況か一覧できるのでスプリントにどれだけタスクを入れられるか判断しやすくなりました

  3. 非エンジニアからも進捗が把握し易い! これだけビジュアライズされているので、Redmineに煩雑さを感じていた方も直感的にみやすくなったのではないでしょうか!

  4. 作業依頼がしやすくなる! スプリント毎にどの程度タスクが埋まっているのか把握できるので、Aさんの工数余裕ありそうだから、〇〇の修正やってもらえるかな?など見込んでから依頼ができるのでスムーズなコミュニケーションができるようになりました

  5. 振り返りが明快になる! JIRAにはスプリント毎のレポート機能があり、バーンダウンチャートや完了タスク・繰越タスクを確認しながら振り返りを実施できます。 ジモティーでは要振り返りタスクにラベルを設定して振り返るべきタスクを明確にしリリース結果の数値を見ながら円滑に振り返り会議を進めています 次回スプリントへのフィードバックもタスクのコメントにメッセージを残すことで振り返り会議に参加していないエンジニアへの情報共有も漏れがなくなりました!

  6. 適切なワークフローを意識して手戻りが減る! JIRAの使い始めは特にフローを意識せず作業前-作業中-完了でやっていたのですが、ヒアリングを行い現状で最善なワークフローとなるよう整理してJIRAヘ反映させました。 タスク毎にどのような観点が必要かアサイン者が理解しやすくなる、或いはレビュー者のレビュー観点漏れ抑止にも繋がり手戻りが減り気持ちよく作業ができる環境へ近づいたのではないでしょうか。

運用のコツ

2ヶ月程ですが運用した気づきを書いていこうと思います

ワークフロー

ワークフローの整理は導入初期にするべきです。自分たちのタスク遂行がどのようなフローで行われていて、どこでスタックしているのかを整理することで最善なフローへ導くことができると思います。そのフローをJIRAへ反映させ、タスクを遂行する上での留意点を意識しやすくすることで考慮漏れや共有漏れが減るのではないでしょうか。

工数見積もりの見える化

最初の設定が煩雑な気もしましたが、徐々に使い慣れていき「JIRAの良さ」で説明した通り、工数の把握がしやすい形にしていきました。

JIRAコメントでの進捗共有

レビューや重要なチェック要素についてはコメントにログを残すようにしています。例えば予想見積もりを超える工数を要したタスクの振り返り時にログを見返すことで適切なフィードバックを得られるようになります。

エピックの活用

エピックは通常長期に渡る案件を管理する箱のようなものですが、ジモティーではタスクの振り分け用に使用しています Kobito.bIffej.png 各エピックへ関連づけられたタスクを、エピック毎に把握しやすくなり手薄になっている観点や今後の施策立案の適正さの維持に役立っています

振り返り

タスク毎に振り返り記載用のフィールドを用意して、数値的振り返りが必要なタスクについて担当者が記載するようにしています。 振り返りが必要なタスクへのラベル付けと合わせて、円滑に振り返りミーティングを進められるようになり、適切なフィードバックが行えるようになりました。

まとめ

今回、エンジニアメンバーへのJIRA利用促進と合わせて、マネジメントサイドへのJIRAを用いた状況確認の方法の共有をさせてもらいました。 そこでの気づきは、作業フローの属人化やスタックしやすいフローを継続しているシーンなど散見されることを認識出来たのが改善に直結したと感じました。 把握できた課題をJIRAを通して改善へ導くことも非力ながら貢献できたのかなと思います。

JIRAは機能が豊富だし、拡張性も非常に高いので各組織での最適な利用方法は千差万別だと思います。しかし、できることをしっかり理解して組織に根付くことを最優先に運用することで作業する側もマネジメントする側も気持ちよく働けるようになると実感しました。

このエントリーが参考になれば幸いですが、JIRAに限らず色々な管理手法を試していこうと思うので何か発見があったときに、またここでご紹介できればと思います!

Kotlin勉強会をしました

ジモティーのアプリチームにて、Androidの開発をしている小林真です。

ジモティーではよく勉強会が行われます。

勉強会では、自分が新しく知ったことや、メンバーに知っておいてもらいたいことを中心に話されています。

今回は、1月の社内勉強会で私が発表した、Kotlinについて説明をしたいと思います。

Kotlinとは

https://kotlinlang.org/ f:id:jmty_tech:20170203174553p:plain

  • Java言語で書かれたライブラリを呼び出すことができます
  • Javaの記述をより短く書けます
  • Null安全などJavaにはない安全に書ける仕組みがあります
  • AndroidTomCat等、Javaフレームワークにも対応しています

Javaでできることをより短く、安全に、便利に書けるようにした言語です。

Javaとの書き方の違い

  • 変数
    • Javaで型宣言していたところはvar/valに統一できます。

java

public int i = 1;<-Kotlinではデフォルトのアクセス制限がpublicとなります
public MyObject obj = new MyObject();

kotlin

var i = 1  <- 型推測でInt型になります
val obj = MyObject() <- newが必要ない
val str : String = "foo" <- 型を指定することもできます

val

valはjavaでいうfinal(変数の変更不可)です。

変数を変更不可にし、意図しない変更を行えないほうが良いので、基本的にvalを使い、どうしても後で変更したい変数のみをvarにするのが良いでしょう。

java

public final String str = "foo"   

kotlin

val str = "foo"
str = "bar" <- コンパイルエラー

null安全

Kotlinを使う大きな理由の一つです。

「null安全」と聞いて、「nullが存在しない言語」と思うかもしれませんが、そういう意味ではないです。

「nullを入れられない変数」と「nullを入れられる変数」を明確に区別して、nullの影響範囲を最小限にします。

そして、「nullを入れられる変数」にnullを入れて、メソッド参照等をしようとした時(JavaだとNullPointerExceptionになるような動き)、 例外が発生しないような振る舞いをしてくれる仕組みです。

一方、「nullを入れられない変数」にnullを入れようとしたり、nullが入るかもしれない参照をしている場合、コンパイルエラーが出てくれます。

これにより、意図しないnull参照、代入を防ぐことができます。

  • Nullが入れられる変数(nullable)には、String?のように?を追加します
  • nullableのメソッドを呼び出すには、?.とする必要があります
//var nonNull1 : String = null <- コンパイルエラー
var nonNull2 : String = "foo" <- 通る
var nullable : String? = null <- 通る
var i : Int? = nullable?.length <- 落ちない(nullが入る)

?を!!にすることで「この変数は絶対nullじゃない」と宣言できます。

しかし、NullPointerが発生する穴を生むので、あまり使わない方がいいでしょう。

var nullable : String? = null
var i2 = nullable!!.length <- nullPointerException

AndroidでKotlin使ってみた

AndroidはKotlinでも書くことができます。

Javaより使いやすい言語なら、結果的に効率よく開発ができるのではないかと思い、個人で作成しているアプリをKotlin化してみました。

ここでは、良かった点、悪かった点を書きたいと思います。

ここ良かった

  • 「とりあえずval」が可能

javaでfinalは目立つし、わざわざつける必要があるので、あまり使っていませんでした。

valなら、一文字しか変わらないので、「これは変更しないな〜」って思って初めてvarにする、といったコードの書き方ができます。

  • useが便利
    • DBアクセス等で必要なclose処理を勝手にしてくれます f:id:jmty_tech:20170203174438p:plain
  • 開発時にNullで落ちない Java -> Kotlin変換時に!!を使った時以外、Nullによる例外は発生していないです。
  • 変数、メソッドが揃ってて見やすい
    • fun/var/valとみんな3文字&型記述があとになるため、揃う f:id:jmty_tech:20170203174527p:plain
  • Scalaみたく重くない
  • 型推測がすごい楽
    • 型を変えたい時に、いちいち2箇所変える必要がない
  • AndroidStudioの言語サポートもJavaと変わらないくらい便利になっています

ここ悪かった

  • Kotlin+DataBinding+XMLではまる

DataBindingでミリ秒を時刻表示するためにのDataUtilクラスを使っていました。

Kotlinでは外から見てJavaのStaticメソッドとして扱うには@JvmStaticアノテーションが必要でした。

なのに、「DataBindingの構築に失敗しました」としかでないから、KotlinでDataBindingを使うための設定をいじったりしていました

エラーが出ても丁寧な情報がネットに載ってないので、情報を正しく得る力が必要です

  • valとかnull安全とか有効に使うためには、MVCとかMVVMとかの導入が必要かなと思った

AndroidライブラリがJavaなので、Activityに処理を書くと意味がなくなります(JavaライブラリをKotlinで呼び出すときは、Nullableで値が来ます)。

そのため、View層、Model層って分けないとvarや、Nullableの変数ばかり必要になります

勉強会をしてみて

自分一人で勉強していたことを、いざ発表することとなると、結構曖昧に覚えていた知識とかがあり、確認ができていい機会でした。

iOSアプリ開発者の人と、Swiftと似ている所、違うところを話したりして、有意義な時間でした。

Kotlinをジモティーで使うか

チーム内でKotlinに関する知見をためていき、タイミングを見て移行していこうとチーム内でKotlin熱が上がっています。

現状にとどまらず、新しいことをしていくことで自分たちも、新しく入る人達も古いコードを見て悩まないようにしていきたいです。