ガジェット通信 GetNews

見たことのないものを見に行こう

ヤフーがAndroidアプリに関する技術や開発事例を共有する「CAMPFIRE Android」を開催

DATE:
  • ガジェット通信 GetNewsを≫

Yahoo!知恵袋をRxJavaでフルリニューアル

ヤフーのAndroidにおける技術情報を共有するMeetup「CAMPFIRE Android #1」が、4月19日にヤフーのコワーキングスペース「LODGE」で開催された。

「Yahoo! Japanでの取り組みや開発のコツを知ることができる」「Androidアプリ開発の情報をアップデートできる」ことから、定員100人を超える人たちが集まった。

まずはドリンクで乾杯。ラフな雰囲気で始まった

最初のセッションを行ったのは、Yahoo!知恵袋を担当している(取材時)中里直人氏。タイトルは「RxJavaを1年使って見えてきたこと」。

Yahoo!知恵袋は1年前にフルリニューアルしている。リニューアルに取りかかったのは2015年11月。その際に導入したのが、RxJava(RxJava1)だ。アプリの基本構成は次の通り。

RxJavaを使ってよかったのは「非同期処理が簡単になったことと、複数箇所で最新情報を表示できるようになったこと」。

まずは非同期処理が簡単にした方法について。API Requestについては、通信処理をRxでラップ。「OSSを使えば勝手にやってくれることも多いので」と中里氏は説明する。

またModelについてはレスポンスクラスをデータクラスに変換することで、適宜キャッシュを返したりするようにした。Activityについては、データを受け取って表示更新処理などを行い、エラー時の挙動も書いた。

続いて複数箇所で最新の情報を表示するために、ModelにBehaviorSubjectを保持し、観測用の関数を用意した。またdoOnTerminate() for Singleについては、成功しても失敗しても実行する処理を書いた(ObserbleにあるものをSingleに実装)。

そしてProgressDialogを簡単に表示するように実装、さらには二重リクエストを防止するようにした。

中里氏いわく「こうしておけば良かった」ことは、まずは通信要求と通信状態を分けること。画面回転などをしたときに、通信状態が引き継げなくなるからだ。

次にunsubscribeする場所をよく考えること。第三にストリームに流す値をimmutableにすること。第四にストリームにnullを流さないこと。なぜならRxJava2に移行できない可能性があるからである。

第五にListの更新方法を統一するなど、Listっぽいものの扱いに注意すること。第六にRecyclerViewを積極的に使うこと。要素の挿入や内容の変更が非常に大変になってしまったからだという。

中里氏は最後に、今後はRxJava2に移行を予定しており、またKotlin化も進めたいと語った。

大規模アプリケーションを支える設計とは?

続いて登壇したのは、Yahoo!JAPANアプリのプロジェクトマネージャーであり開発チームリーダーとしてメンバーをけん引している牧竜也氏。

セッションタイトルは「大規模アプリケーションを支える設計」。Yahoo!JAPANアプリで設計を見直すプロジェクトについて紹介した。

アプリ開発の初期パターンとしてよく活用されているのが、Smart UI Pattern。これはビジネスロジックをUIに実装するパターン。一般的にアンチパターンとして認知されており、シンプルな機能やスピード重視では採用されがちだが、「大規模なアプリケーションだと破綻する」と牧氏は言う。

ActivityやFragmentにビジネスロジックが集中し、肥大化するからだ。

そこで破綻しにくいアプリケーションを実現するために、ビジネスロジックをUIから切り離すことにした。

こうすることで、ActivityやFragmentが肥大化せず、ビジネスロジックのユニットテストが書きやすくなる。さらにUI・ビジネスロジックの変更がお互いに影響し合わず独立して行えるようになるからだ。

「ただ現実はそう簡単にはいかない」と牧氏は続ける。UtilやHelper、Managerなどの責務が不明瞭なクラスが量産され、課題が解決しなかった。

明確な設計指針が必要だと考え、採用したのはエリック・エヴァンスのドメイン駆動設計で紹介されているLayard Architecture。

アプリケーションをプレゼンテーション層(情報の表示やユーザー入力の解釈)、アプリケーション層(アプリケーションの要件を実現)、ドメイン層(ビジネスロジックを実現)、インフラストラクチャー層(上位層を支える基盤技術)の4層に分離。上位層は下位層にのみ依存する。

例えば「アプリケーション層はドメイン層とインフラストラクチャー層は参照できるが、上位のプレゼンテーション層は参照できない。

こうすることでレイヤーやクラスが肥大化しにくく、ビジネスロジックのテストが書きやすくなる。加えてレイヤー間で変更が影響しにくく、変更に強くなる。

また、四つの基本的なルールを採用し、チーム内で共通認識を構築。
レイヤーをモジュールで表現し、依存関係を守る
レイヤー間の結合をinterfaceで疎にする
複雑な要件をObservableで吸収する
ドメインモデルの汚染を腐敗防止層で守る

さらに、具体的な設計の例も紹介。

例えばニュースの一覧をAPIから取得して表示するという設計では、「図の様なフローにしました」と説明。

そのほかにも、「APIに負荷がかかるのでアプリでキャッシュする」「SDKから広告を取得して表示」「広告と記事の並び順をクライアント側で決める」などの具体例を紹介した。

最後に牧氏は「今回紹介したのは大規模アプリケーションでも破綻しにくい設計の一例です。解決したい問題に見合った設計を考える必要があります」と語り、セッションを締めた。

Android Thingsで勤怠連絡ボタンを作り、勤怠連絡を簡単に

3番目に登壇したのは、3月末までIoTサービス「myThings」を担当していた松田優貴氏。セッションタイトルは「Android Thingsで勤怠連絡ボタンを作ってみた」

松田氏が今回披露した勤怠連絡ボタンは、例えば「体調が悪く午前中は休む」というような勤怠連絡をPCやスマホで入力することなく、ボタンをポチッと押すだけで完了するツール。

ヤフーでは勤怠連絡をメールで行うことが多いのと、他社ではSlackを利用した勤怠連絡もあるらしいので、Yahoo!メールとSlackを利用することに。そして、せっかくやるなら世の中の風潮に合わせてサーバーレス、クラウドネィティブで実現することを考えた。

その中で「最初はmyThingsアプリ(WebサービスやIoTデバイスが持つ機能を自分で組み合わせて便利に使うことができるアプリ)のみで実現できると思った」と語る。

しかしアプリでは、スマホを起動させる手間に加え、日付を動的に入れることができない。

そこで、ボタンを押すと勝手に連絡が行くようにするため、Hackeyデバイスでできないか検討。

Webhookの機能を利用して、Webscript.ioに飛ばし、myThings Developersプラットフォームを活用して勤怠報告をするというアーキテクチャを考えた。

このアーキテクチャの最大の課題は、URLがバレてしまうと誰でも好きなように勤怠連絡が送れてしまうこと。さらにAmazon Dashボタンを試してみましたが、課題があったという。

次にRaspberry Pi3×SORACOM×AWS IoTを試していたところ、Android Thingsが発表になった。

そして今年、米サンフランシスコで開催された「Google Cloud Next’17」に参加したところ、IoTのセッションではAndroid Thingsが取り上げられており、試してみることに。まずはRaspberry Pi3にAndroid Thingsを入れ、公式ページを参考にしながらセットしていった。

そしてRaspberry Pi3、Android Things、Android Studioを使い、公式ページのLEDチカチカ(Lチカ)サンプルで試した。

Android Studioでは、アプリ開発同様、logcatでログを見られ、モニターをつないでおけば、アプリの画面も表示でき、通常のアプリと同じ感覚でIoTアプリケーションが作れることがわかった。

勤怠連絡ボタンのアーキテクトは図の通り。

「Android Thingsを使う良さは、Android Studioで容易に開発ができること。またGoogleが提供するライブラリを使えるのも良さ。さらにGCP(Pub/Sub、Dataflow、Functionなど)との新和性があるので、クラウド連携がしやすいところもうれしいですね」(松田氏)。

Android Thingsで勤怠連絡ボタンを作る方法の詳細については、松田氏がQiitaにまとめているので、関心のある方はチェックしてみよう。

Yahoo! JAPANアプリのデータベース処理をいかに改善したか

4番目に登壇したのは、昨年10月に中途入社し、現在Yahoo! JAPANアプリの開発を担当している森脇聖太氏。

セッションタイトルは「Yahoo! JAPANアプリのデータベース処理改善」。リリース済みのアプリのデータベース処理をどうやって安全にモダンな環境に移行したかについて話した。

Yahoo! JAPANアプリのAndroid版がリリースされたのは2011年10月。

「リリースから5年以上も経つと、継続的なメンテナンスをしていても、どうしても技術的負債がたまってしまいます。今回はその中でもデータベース周りの負債の解消に取り組むことになりました」(森脇氏)

改修前のデータベース処理の構成は次の通り。
SQLiteOpenHelper
ContentProvider
CursorLoader

それを
SQLBrite
SQLDelight
AutoValue
RxJava

などのOSSを用いた構成に改修した。

データベース周りのOSSを導入するにあたって、当初候補に挙がったのは、SQLBriteのほか、Realm、Orma、requeryなど。その中でSQLBriteを選んだ理由として、既存のSQLiteOpenHelperをラップする形で運用できるため、データベースのマイグレーションの必要がなく、他OSSと比べて導入コストが低いことが決め手となったという。

また「SQLDelightと併用することで、Javaの記述とSQLの記述を分離することができ、メンテナンス性が向上しました」と森脇氏。

SQLBrite+SQLDelightを導入して良かった点を次のように明かす。
少ないコストでモダンな開発環境に対応できる
データベースのマイグレーションが不要となるので、既存ユーザーのデータ損失リスクを限りなくゼロにできる
SQLとJavaの記述を分離することで、可読性が向上

一方、つらかった点もある。それはSQLBriteがRxJava2に未対応であること(4月現在)、日本ではRealmやOrmaの知名度が圧倒的に高いため、チーム内への布教活動がかなり必要になることだ。

「既存アプリのデータベース改修は大変。世の中にはORMがいっぱいだが、SQLiteOpenHelperを使っているなら、SQLBrite+SQLDelightという選択肢もありだと思います」(森脇氏)

不具合で学んだ[最適」への道

5番目に登壇したのは、12年に新卒で入社して以来、昨年の7月までずっとYahoo!ニュースアプリを担当してきた矢端智光氏。セッションタイトルは「ニュースアプリで起きた不具合から学んだ最適への一歩」。


ニュースアプリで起きた不具合から学んだ 最適への一歩 from Yahoo!デベロッパーネットワーク

Yahoo!ニュースアプリ Android Things版1.0.0をリリースされたのは13年11月20日。「3周年が過ぎたので、最適について考えてみました。中でも、最適をおざなりにしてきたのは開発者に対してでした」と矢端氏は語る。

Yahoo!ニュースアプリの歴史はまだ短いため、プロダクション優先やユーザー優先で開発されてきたこと。そして業務委託やオフショア開発など、開発体制が定期的に変化していたことがその理由だと振り返った。

開発の大半に関わってきたなかで、次のような反省があると明かす。

それは直したバグをプルリクエストするだけで、事例としてまとめて整理していなかったこと。そのため、類似の事象が発生した時に過去の資料を探すという無駄な時間がかかってしまっていたこと。これらのことに開発から離れて気付いたという。

開発者に対して最適にするため、まず行ったのはバグの事例を振り返ることだった。そのためにVolleyとの別れを決断。かゆいところに手が届くように刷新したので、手がかかりすぎようになり刷新が必要になったからだ。

例えばレスポンスヘッダーのキーが大文字小文字関係なく取得できるようにしたり、特定機種やOSで発生したりする意図せぬエラーをハンドリングするなど、つぎはぎしていた項目も刷新した。

実際に「一覧画面のFragmentに機能を追加したらエラーとなった」というバグ事例を紹介。この原因は、ViewPager上の二つの画面が「自分を更新する」メソッドをonResumeのタイミングで同時に呼んだこと。それを解決するため、「自分を更新する」メソッドが複数回呼ばれた場合に、一度だけ実行されるように修正することに。

だが、この解決方法を実装すると、フラグが氾濫し、コードが冗長になってしまう。そこでHandlerで実行するRunnableを制御する実装を行うことで解決を図った。

ただし「処理をずらすので、書き方次第では実行されるまでの間に、参照している値やメソッドの返り値に変更が発生する可能性があることは念頭においておきましょう」とのこと。

最後に「バグは恥ずかしいものかもしれないが、誰にも聞けないというふうにしないこと。周りのできる人も手を差し伸べてあげてください。そして不具合に対するナレッジを共有することで最適への一歩を踏み出してください」と呼びかけた。

タブブラウザSDKを作った話

最後のセッションは、Yahoo! JAPANアプリを担当している小林俊氏による「タブブラウザSDKを作った話」。


タブブラウザSDKを作った話 #yjcamp from Yahoo!デベロッパーネットワーク

ちなみにタブブラウザSDKとは、WebView管理やタブ管理ができ、CoordinatorLayout対応、URLスキーマハンドリング、ページ内検索、標準的な振る舞いを提供してくれるSDK。セッションでは3桁を実現させるタブ管理、WebViewとCoordinatorLayoutの実装方法を中心に説明が行われた。

ブラウザ機能をSDK化することで、ブラウザ周りのシステム改修を各アプリでする必要がない。3桁を実現させるタブ管理では、タブとタブの持つWebViewをそれぞれ独立して管理するのが特徴。上限を超えたWebViewは、最もアクセス時刻の古いものから破棄されるようになっている。

破棄されたWebViewの保存はWebViewが提供するメソッドをそのまま利用し、Bundleを通してファイルへの保存し、再度タブが開かれた時に、ファイルからBundleへ読み込みWebViewのメソッドで復元させる。

WebViewとCoordinatorLayoutの対応をする場合は、地図操作、カルーセル、ピンチイン・アウトなど、横スクロールした時に縦スクロールが発生することによるWebViewの移動や、サイズ変更による操作の阻害への対応について紹介した。

タブがカルーセルタイプの場合、横スクロールする時に縦スクロールが発生することによって、 WebViewの移動やサイズ変更による操作の阻害が起こることがある。

地図操作の場合は、WebViewサイズいっぱいで 操作させるページで動かないようにサイトのコンテンツサイズ(高さ)と WebViewのサイズを比較しながら対応する。

最後に、「WebViewにNestedScrollChildを実装」「ウェブサイトの作りへの考慮が必要」とまとめた。

セッションの後は懇親会を開催。懇親会には登壇者のほかにも、ヤフー社員が参加しており、参加者たちは思い思いに情報交換にいそしんでいた。

ヤフーではさまざまな技術に関する勉強会やイベントを開催している。エンジニア向けイベント開催情報はヤフーのエンジニア向けオウンドメディア「linotice」をチェックしてみよう。

カテゴリー : デジタル・IT タグ :
CodeIQ MAGAZINEの記事一覧をみる ▶
  • 誤字を発見した方はこちらからご連絡ください。
  • ガジェット通信編集部への情報提供はこちらから
  • 記事内の筆者見解は明示のない限りガジェット通信を代表するものではありません。