サナギわさわさ.json

サナギさんとキルミーベイベーとプログラミングが好きです

スタートアップでの経験から読み解く「エンジニアリング組織論への招待 - 第1章 - 」

お久しぶりです。前職を辞めて株式会社GlobeeのCTOになってから約10ヶ月が経ちますが、本当に色々な事がありました。 前職でエンジニアをやっていた時に私が解いていた課題は

  • 大規模データ収集基盤を低コストで安定運用するためのアーキテクチャ設計
  • 大規模データ分析を可能にするHadoop基盤構築

など純粋に技術的なものが殆どであり、プライベートでの勉強もそちらに寄っていました。
(↓その時に書いた記事)

qiita.com

しかし現職で解かなければいけない課題は

  • より多くの人に使われるサービスにするためにはどうすれば良いのか
  • 同じ予算でより開発スピードを上げるためにはどうすれば良いのか

など曖昧なものが多く、私個人の技術力だけで解決することが難しいものばかりです。

ですので最近は純粋な技術力というよりも、エンジニアリングの力をビジネスに効果的に反映させるための力が欲しいと感じています。

そんなこんなで先日「エンジニアリング組織論への招待~不確実性に向き合う思考と組織のリファクタリング」を読みましたので、ここ10ヶ月の実体験と絡めて感想を書きます。

blog.shibayu36.org

エンジニアリング = 不確実性の削減

  • エンジニアリングは日本では工学と訳される。理学が物理学や化学のように自然の原理を説明していく学問であるのに対して、工学はそれらに依拠しながら何か役に立つもの実現していく学問である。

  • 何かを実現するというのは、曖昧な要求を明確な何かに変えることを意味する。すなわち、曖昧さを減らし、具体性・明確さを増やす行為がエンジニアリングと言える。

本書のエンジニアリングに対する定義は私がエンジニアリングに対してずっと抱いていたイメージとかなりの部分で一致していました。

ただ私は、エンジニアリングを「技術を用いて」不確実性を削減するものだと矮小化して捉えていました。 エンジニアリングという行為は不確実性の削減が本質であり、技術的な部分は本来そのための手段の一つに過ぎません。

少し具体的な例を挙げます。 私はGlobeeにジョインした当初、「ビジネスサイドが出したアイデアを最高の品質でできるだけ早く世に出す事」が自分の役割であると考えていました。

そのため、開発に割く時間をできるだけ長くする事を重要視し、自分がビジネスサイドに深く関わる事を嫌う傾向にありました。 しかし、スタートアップではアイデア自体の不確実性が非常に高いため、まず削減すべきはアイデア自体の不確実性です。

スタートアップのエンジニアはある程度の時間をビジネスサイドに割く事で、結果的にプロダクトの質も上がるのではないかと思います。

マイクロマネジメント型の組織は弱い

  • 企業においては、社員全員の力を活用するために、誰かに指示をしてその誰かも他の人に指示をするという指示の連鎖が必要になる。そのため、上位に行けば行くほど指示は曖昧になっていく。

  • 具体的で細かい指示を出さないと動けないマイクロマネジメント型の組織では、指示する側の知的能力がそのまま組織の知的能力になってしまうため、抽象化された自由度のある指示でも動ける自己組織化された組織よりも弱い。

弊社の開発体制は今の所マイクロマネジメント型の組織寄りになってしまっており、ここは課題の一つです。 ここに関しては後日また詳しく書こうと思います。

論理的思考の盲点

  • 論理的思考とはすなわち演繹的思考のことであり、前提であるルールと事象から結論を導く思考方式である。

    • ルール:人間は皆死ぬ
    • 事象:私は人間である
    • 結論:私は死ぬ
  • これが成り立つためには、以下の2つの前提が必要である。

    • ルールと事象を正しく認知できること
    • 正しく演繹できること
  • 事実を正しく認知するためには、自分の認知がいつ、どのように歪むのかを知る必要がある。

  • 論理的に考えるためには、自分が非論理的に考えてしまう瞬間を知る事が必要である。論理的思考力と言うのは、「感情的になる瞬間を知り、その影響を少なくできる」能力でもあると言える。

  • 学力テストは通常1人で論理的な思考を用いて行うが、仕事は立場の違う複数人で行うため、コミュニケーションの失敗が論理的思考力を制限してしまう。どんな時に自分は論理的でなくなり、人は論理的でなくなる可能性があるのかという事を知った上で問題解決に臨むのが論理的思考の盲点を知るという考え方である。

スタートアップで働いていると、前職と比べて論理的でなくなる瞬間が多いように思います。

これは

  • 長時間労働による肉体的・精神的疲労
  • 会社のキャッシュが徐々に減っていく事による焦燥感

などの初期のスタートアップ特有の事情によるものが大きいです。後者に関しては割とどうしようも無いのですが、前者に関しては

  • 休む時はしっかり休む
  • 定期的に運動を行う

などである程度対処可能な気がします。

www.slideshare.net

また、自分が過去に感情的になってしまったタイミングを思い返すと以下のような共通点がある事に気付きました。

  • 議論を終えて早く開発を進めたいと思っている時
    • 作業中に声をかけられた時
    • 議論が長引いた時(特に夜)
  • 自分の意見をすぐに否定された時

この条件に当てはまるような時には、感情的になりやすいので注意するようにしています。また自分が感情的になりやすい瞬間については周囲にも共有しており、例えば作業中にイヤホンをしている時はできるだけ声をかけないようにしてもらっています。

経験主義と仮説思考

  • 仕事では、問題を解くのに必要な情報が目の前にないのであればそれを入手するために行動し、問題を明晰化する必要がある。

  • 情報を入手するために行動を起こしてその経過を観察し、そこから問題解決を行う考え方を経験主義と言い、限定された情報から全体像を想定し、それを確かめる事で少ない情報から問題解決に向かう思考様式を仮説思考と言う。

  • 今現在解くことができない難しい問題は、「何が分かれば分かるのか」を考え、それを確かめる事に変換する。

  • 経験主義は、単純に「やってみなければわからない」という論理ではなく、「知識」=「経験」を行動によって手に入れるということである。そのためには、「行動できる事は何か」と「行動の結果起きた事を観察できるか」という2点が重視される。

  • トム・デマルコは「観測できないものは制御できない」という名言を残した。これに習うならば、変化を観測できないものは間接的にすらコントロールできないという事になる。

  • 私たちは何か問題に出くわすと、「コントロールできないもの」を操作して「観測できないもの」を改善するという不可能な問題設定を行ってしまいがちである。「コントロールできるもの」を操作し、「観測できること」を通じてその結果を知識にするしかない。

  • PDCAサイクル「何が仮説なのか」と「それはどのようにしたら推論できるのか」の2つが揃っている必要がある。

スタートアップでは「やってみなければわからないからとりあえずやってみよう」という論理が強くなりがちですが、ここで忘れてはならないのは

  • どういった仮説を検証するためにやるのか
  • 行動の結果、仮説が正しかったのかを統計的に検証できるか

の2つです。この2つが揃っていないPDCAサイクルは回しても実際意味が無かったという事が多いです。最初の方は自分もこれを割とやってしまっていて、しかもPDCAサイクルを上手く回せているつもりだったので最悪でした。たまにまぐれで上手くいってしまうのもタチが悪いです。

これはグロースハックのプロセスにも通ずるものがある気がします。 詳しくは下記をご参照ください。

growiz.us

まとめ

とりあえず第1章を読んで考えた事をまとめました。第1章は個人での仕事にも使えるような内容が多いので、是非色々な人に読んで欲しいなと思います。

第2章はメンタリングの話、第3章以降はチームや組織の作り方の話になっていきますので、これに関しても後日記事にできればと思います。

なお、弊社では現在エンジニアを募集中です。この記事を読んでもし興味がおありでしたら是非オフィスに遊びに来て下さい!主にアプリエンジニア・Webエンジニアを募集しています。

急成長中の教育サービスで教育の仕組みを変えたいエンジニア大募集 - 株式会社Globeeのモバイルエンジニア中途・新卒・契約・委託の求人 - Wantedly

創業メンバーとして教育を一緒に変えていきたいデザイナー大募集 - 株式会社GlobeeのUI/UX デザイナー中途・インターンシップ・契約・委託の求人 - Wantedly

「快感回路」を読んだ

最近インプットが減っていて良くないと思ったので、色々な所で紹介されていた「快感回路」という本を読みました。

快感回路---なぜ気持ちいいのか なぜやめられないのか (河出文庫)

快感回路---なぜ気持ちいいのか なぜやめられないのか (河出文庫)

当初想定していたよりも大分科学的な内容で驚きましたが、内容自体は面白く、かなり楽しめました。明日すぐに仕事に使えるとかそういうタイプの本ではありませんが、こういう知識を取り入れておく事で、例えばサービスを成長させるための施策の質が上がったりするといいなあと思います。

以下、各章の感想と紹介です。

第1章 快感回路の発見

ラットの快感回路を用いた実験で、ラットが自分の脳を刺激するために1時間に7000回のペースでレバーを押し続けたというのはゾッとする。同様の実験を人に対して行った際の描写は更に衝撃的。

患者は、最も多いときには一日中、自分の健康も家族のことも気に掛けずに自分を刺激し続けた。(中略) ときには、装置を遠ざけてくれと家族に懇願し、取り上げられてしばらくすると必ず、返してくれと要求した。

個人的には、快感という現象がVTA(腹側被蓋野)のドーパミンニューロンの活性化によって科学的に説明できるというのが割と驚きで、人の心は科学的に解明できていないというのは固定観念が覆された。

また、私たちが生き続けるためには食べたり飲んだりセックスしたりといった経験を快いものとして感じる必要があり、快感回路がその仕組みの構築に寄与しているという話も面白い。(極めて原初的な線虫でも基礎的な快感回路を持っており、その回路を破壊すると食事をとらなくなるらしい)

第2章 やめられない薬

古代ローマにおけるアヘン、19世紀アイルランドにおけるエーテルなど、どんな時代においても人類は自らの脳の機能を変容させる手段を見つけ出し、統治者はその利用を規制してきたが、人間だけでなく、野生動物も精神的活性効果を持つ植物や菌類を習慣的に喜んで口にするというのは興味深い。 最も分かりやすい例は栄養にならないベニテングタケを食べて酔う家畜化されたトナカイらしい。こういう雑学を隙あらば繰り出していけるような人間になりたい。

また、向精神薬の中でも快感回路を活性化するものとしないものがあり、それによって依存症リスクの大きさが異なるという話は納得できた。摂取方法(脳のニューロンに到達するまでの早さ)・入手難易度・社会的な位置付けなどが依存症リスクを左右するという説明も面白く、タバコの方がコカインより依存症発生率が高いという事実への回答になっている。

また、一般的に依存症は心の弱さが原因と受け取られる事が多いように思うが、依存症リスク要因の40~60%が遺伝的なものと推定されているらしい。ただ依存症の発症は患者の責任ではないが、依存症からの回復は患者の責任と述べられており、これは良い言葉だと思う。

本筋とは少し外れるが、遺伝的なリスク調査は一卵性双生児と二卵性双生児の比較で行うというのは初めて知った。

第3章 もっと食べたい

快感回路は薬物や電極によって刺激することができるが、ものを食べるといった自然に快感を伴う行動によっても活性化する。コカインなどの脳内にドーパミンを溢れさせる薬物をラットに与えると、そのラットはあまり食べなくなり体重を減らすとの事。覚せい剤が「痩せる薬」と呼ばれる事があるのも嘘では無いようだ。

肥満には遺伝的な要素が多分にあり、肥満しやすいラットは食事時に得られるドーパミンの上昇が他のラットよりも小さく、そのために一定のドーパミンレベルを達成するためにより多くの量を食べようとするのではないかと考えられている。

この遺伝性の肥満モデルは人間にも適用でき、体重の軽重は80%遺伝的に決まるとされている。これは身長などの身体的特性の遺伝性と同様であり、心臓病や統合失調症などの遺伝性よりはるかに高い。

身長が遺伝的に決まるというのは感覚的に分かるが、体重が遺伝的に決まるというのがあまりしっくり来ない人も多いのでは無いだろうか。 依存症の箇所でも言われていたが、一般的に心の弱さが原因であると言われる事でも実は遺伝的要因が大きいというケースがあるようだ。逆にこれを知っておく事で、気持ち的にラクになる人は多いだろうという気がした。

また、我々は脂肪と糖が豊富なものを食べた時の方がドーパミンが多く放出されるようになっている。脂肪と糖は同時に取ると極端に依存性が高くなり、普通の餌で満腹になっているラットも甘い餌を与えれば更に食べるとの事。これは「デザートは別腹」という事象を説明している。ここはたぶん雑学ポイントですね。

第4章 性的な脳

一番面白い章だったが、ブログに書くような内容でも無い気がするのでざっくりと。

人間は性的に特殊な生物である。哺乳類の90%は乱婚であるが人間は単婚の傾向を持ち、オスも子育てに協力する。 人間の同性愛的行動・マスターベーションなどは他の動物に無い奇妙な点と考えられる傾向にあるが、これはボノボなどの多くの哺乳類でも確認されている。

人間の性を独特なものにしているのは、むしろ最も因習的で社会的に是認されている交尾行動のほうなのである。

繁殖行動は身体的活動だがその心理的側面、すなわち恋愛について考えるとどうだろうか。恋愛に見られる精神的・生理的側面の表現は強烈な快感・恋人に対する判断の歪みなどで、文化によらず似通っている。

強烈な快感はドーパミン作動性の快感回路の活動に対応しており、これはコカインやヘロインへの反応に似ている。恋人に対する判断の歪みは前頭前皮質の活動低下に対応しており、これは強迫性障害と似ている。

恋愛と性的興奮は脳の活動という観点で見ると、両者とも快感回路の活性化を伴うという類似点を持つ。しかし、前者は判断中枢の低下を伴うが後者は伴わないという点で決定的に異なる。

セックスにはオーガズムの快感の他に終わった後に持続する暖かい余韻があるが、これは脳下垂体から分泌するオキシトニンというホルモンが影響している。 オキシトニンは社会的絆全般にも関係しており、オキシトニンの鼻スプレーをした被験者はプラセボのスプレーをした被験者よりも初めて会った相手を信頼しやすいことが分かっている。これらの結果から、オキシトニンは境界性パーソナリティ障害などの社会的認知に障害のある人の治療方法としても有望視されている。

「人を信頼しやすくなる」といった抽象的な事象が、ホルモンによってある程度説明できてしまうことにまず驚いた。ホルモンバランスが崩れると感情が制御できなくなる、というのは聞いた事があったが、やはり感覚的には受け入れられていなかったようだ。

第5章 ギャンブル依存症

一番身近な話だったので、そういう意味では一番楽しく読めた章。

ギャンブルへの嗜好は初期成功体験で身につくという説が一般的だが、ギャンブル好きな人の多くは初期成功体験など持っておらず、これはおそらく不完全である。 最近サルやラットの実験から提案されている別のモデルは、脳はもともとある種の不確実性に快感を見出すようにできているというものだ。

青い光を表示し、2秒後にシロップが五分五分の確率で出るような実験をサルに対して行った際には、青い光が点灯してから消えるまでの所謂待ち時間の間にドーパミンニューロンの発火レベルが徐々に高まっていく様子が確認された。

ギャンブルにまつわる非合理的な考え方の一つとして、「ニアミス」「直接介入効果」に関するものがある。

ニアミスは一つの負けではなく惜しかった勝負として認識され、ギャンブルを続けさせる要因になる。そしてランダムな事象であっても、賭ける人自身が個人的な関わりを持つ方が賭ける金額が多く、そして長くギャンブルを続けるようになるという事が研究によって知られている。 自分で何かを操作した時のニアミスは、満足度は比較的低いがゲームを続けされる力は強いという点は興味深い。

ビデオゲームには自然的な報酬性など一切ないが、プレイした際には快感回路がある程度活性化するビデオゲームは極めて効果的な報酬スケジュールを持っている可能性が高い。ちょうどタバコと同じで、快感自体は短いが、立ち上がりが早く何度も繰り返されるという形だ。

ギャンブルへの嗜好は初期成功体験によって身につく、という説は僕も支持していたし、おそらくかなりの人が支持していたのではないだろうか。

第6章 悪徳ばかりが快感ではない

慈善・社会的評価・隣人との比較・情報そのものなど、抽象的観念でさえも快感に変えられるという点が説明されていた。 面白いのは人間だけでなくサルでも抽象概念から快感を得られるという話。

第7章 快感の未来

カーツワイルは脳ナノボットの導入が2020年代、脳の内容や能力のアップロードが2030年代という時間的予想をしている。

この予想は、私たちの生物学・神経生物学についての理解がテクノロジーに導かれて指数関数的に深まるという仮説に基づいて成り立っているのだが、これに筆者は疑問を呈している。

筆者曰く、確かに人類は何人かのヒトゲノムの塩基配列を解析したし、その作業スピードやコストは指数関数的に改善してきているが、これらは有用であるものの遺伝子についての理解を指数関数的に深めるものではなく、ヒトゲノムの塩基配列が解析された時にそれを見て人間が個性的になる理由や受精卵が赤ん坊になる過程を急に理解できたような人はいなかったとのこと。

丁度少し前にニュースで似たような内容(2030年代に脳が無機物に移植可能になる)を聞いた時に「マジか」と思ったのだが、人の理解自体がテクノロジーに導かれて指数関数的に深まるという前提だと聞いて納得した。

例えば20年前と比べてプロセッサーやメモリの性能は指数関数的に向上したが、それによって例えば配管の亀裂進展への理解が指数関数的に進んだかと言われればそんな事は無いと思う。仮にヒトゲノムの解析が進んだとして、それが即ちすぐに脳の内容や能力のアップロードに繋がるのかというとそんな事も無さそうな気がしてしまう。

遠い未来の快感を思い描こうとするとき、いちばん想像しにくいのは未来のテクノロジーではなく、テクノロジーを取り巻く社会的、法的、経済的システムだ。

上で引用した言葉はまさにその通りだなあと思う。未来を舞台とした作品を読む時は、そこで描かれるテクノロジーではなく社会的システムにワクワクする。未来では無いが最近だと「BEASTARS」とか面白いなあと思う。

長くなりましたが、面白い本なのでオススメです。今は仕事の時間を自由に決められるので、インプットの時間を定期的に取ろうと思います。 なお、この本は下記ブログで紹介されていたので手に取りました。いつもありがとうございます。

migi.hatenablog.com

iOS/Androidの同時開発を高速化する設計手法について

明けましておめでとうございます。今年もよろしくお願い致します。

弊社では現在abceed analyticsというアプリを開発していますが、iOS/Androidのアプリを両方作る際の開発工数を削減したいというのは人類共通の課題かと思います。

そこで今回は、弊社がアプリ開発を高速化するために採用している手法・技術スタックについて簡単に書きます。 なお、React Native / Xamarin / Cordova などのクロスプラットフォームフレームワークについては触れません。あくまでネイティブで開発する際の手法ですのでご了承ください。

前提となる考え方

弊社では、iOS/Androidで新機能を同時にリリースすることは行なっておりません。多くの場合先行してiOS版で新機能をリリースし、遅れてAndroid版をリリースしています。 同時リリースを行なっていない理由は主に2つあります。

1つ目の理由は、新機能はリリース後にユーザーの反応を分析して変更が加えられる可能性が高いからです。 ソフトウェア企業が陥りがちな問題として「5%問題」というものがあります。これは、サービスを多機能化しすぎて何がサービスの核なのかを見失ってしまう、というものです。

gigazine.net

アプリに新機能を追加する際は、実装する前にその機能がサービスの核を損なわないかを十分考えるようにしていますが、実際にリリースしてみないと分からない事もあります。時にはリリース後に新機能を撤回することもありますので、まず片方のOSでリリースし、価値が高いことが分かったらもう片方のOSでもリリースするという方法が良いと感じています。※絶対に必要な機能である事が明確な場合や、開発リソースが潤沢な場合は別です

2つ目の理由は、UseCase層から先のコードはかなりの部分をiOS/Android間で使いまわせるからです。 後述しますが、弊社ではiOS/Android共にClean Architectureを使った設計を行っています。この場合、ビジネスロジックがViewや外部インフラに依存しなくなるので、コピペ + 一手間ぐらいの感覚で使いまわせるようになります。

ほぼ同じ内容のコードを2人の人間が別々に作るというのは効率が悪く、1人が作った後に使い回す方が開発工数・バグの出にくさの両面で優れていると感じています。ここに関しては考え方が分かれるかと思いますので、是非ご意見ください。

言語

iOSではSwiftを、AndroidではKotlinを使用しています。 Kotlinを使うべきかどうかに関しては諸説あるかとは思いますが、コードをiOS/Android間で使い回す際のやりやすさを重視しました。特にOptionalが言語レベルでサポートされている事が非常に大きいです。

Swiftでよく使うif letNil Coalescing OperatorもKotlinなら簡単に移植する事ができます。optional chainingに至っては全く一緒の構文です。

//Swift
//if let
if let book = bookOptional {
    print(book.name)
}
//Nil Coalescing Operator and optional chaining
print(bookOptional?.name ?? "book is null")
//Kotlin
//if let
bookOptional?.let {
    print(it.name)
}
//Nil Coalescing Operator and optional chaining
print(bookOptional?.name ?: "book is null")

あとはimmutableの宣言をvalletのどちらかに揃えて欲しいと切に願っています。

設計手法

個人のブログでも何回か触れていますが、設計手法はiOS/Android共にClean Architectureを使っています。

kakakazuma.hatenablog.com

qiita.com

詳しい内容についてはここでは触れませんが、ロジックを層ごとに分け、層と層の間の依存関係を無くす事でコード全体の見通しが良くなります。

パッケージ構成は超ざっくりだとこんな感じです。domainパッケージに関してはiOS/Android間でほぼほぼ使いまわせます。通常のClean Architectureを少し簡略化しているのでご注意ください。

├ data
│ ├ network
│ └ repository
├ di
├ domain
│ ├ value
│ ├ entity
│ ├ model
│ └ usecase
├ presentation
├ service
├ utils

UseCase層クラスの切り方は、エンティティでざっくり切るのとユースケース別に細かく切るのと2つあると思いますが、後者の方が見通しが良くなって移植はしやすい気がしています。ただクラス数が増えすぎるのでここは好みかもしれません。

class UserCRUDUseCase @Inject constructor(val rep: UserRepository) {
    fun register() {
        //some process
    }
    
    fun update() {
        //some process
    }
    
    fun delete() {
        //some process
    }
}
class RegisterUserUseCase @Inject constructor(val rep: UserRepository) {
    fun execute() {
        //some process
    }
}

設計手法は色々あるので好きなものを使えば良いと思いますが、迷っているならGoogleが公開しているAndroid Architecture Blueprintsを参考にするのがオススメです。

github.com

ライブラリ

iOS/Androidで使っているライブラリについてです。できるだけOS間で使用感が変わらないようなものを選んでいます。

API

iOSではAPIKit + ObjectMapperを、Androidではretrofit2 + Moshiを使っています。

APIのアクセス情報はdata/networkに格納します。APIのレスポンスに関してはdomain/entityに格納していますが、data層に格納して変換をdomain層で噛ませた方が良いと思う時もあります。

iOS

class UserInfoRequest: BaseAPIRequestType {
    
    var path: String {
        return "user/info"
    }

    var method: HTTPMethod {
        return HTTPMethod.get
    }
    
    //Response
    typealias Response = UserInfoResponse
    
    var id_user:String
    init(id_user:String) {
        self.id_user = id_user
    }
    
    //Request Parameters
    func toDict() -> Dictionary<String, Any> {
        var dict = Dictionary<String, Any>()
        dict["id_user"] = id_user
        return dict
    }   
}

class UserInfoResponse: Mappable {
    var id_user:String?
    var name_user:String?
    
    required init?(map: Map) {
    }
    
    func mapping(map: Map) {
        id_user <- map["id_user"]
        name_user <- map["name_user"]
    }
}

Android

interface UserApi {

    @GET("user/info")
    fun info(@Query("id_user") id_user:String): Call<UserInfoResponse>

}

data class UserInfoResponse(val id_user:String, val name_user:String)

内部DB

内部DBはiOS/Android共にRealmを使っています。シンプルで使いやすいですが、スレッドをまたぐ時に注意が必要です。 AndroidではUseCase層を別スレッドで実行する事が多いので、都度View用のモデルに変換しています。ここに関して良い方法あれば是非教えてください。

DI

AndroidではDagger2を導入しています。AndroidはContextが必要な箇所が多いのですが、Contextを引き回しているとコードの見通しが悪くなるのでDIを導入する利点が大きい気がしています。

DIを使うと、例えばSharedPreferenceが以下のようにRepository層に渡せるので、個人的に書きやすいです。

@Module
class AppModule {

    @Provides
    @Singleton
    fun provideContext(application: Application): Context {
        return application
    }

    @Provides
    @Singleton
    @Named("default")
    fun provideDefaultSharedPreference(context: Context): SharedPreferences {
        return PreferenceManager.getDefaultSharedPreferences(context)
    }
}

@Module
internal class RepositoryModule {

    @Provides
    @Singleton
    fun provideUserRepository(@Named("default") ref: SharedPreferences): UserRepository {
        return UserRepository(ref)
    }
}

class UserRepository @Inject constructor(val ref: SharedPreferences) : UserDataSource {
}

iOSに関しては、良いライブラリを見つけられていないこともあり手動でのDIとなってしまっています。良い方法ありましたら誰か教えてください。

まとめ

弊社では、

  • まず片方のOSでリリースし、価値が高いことが分かったらもう片方のOSでもリリースする

  • Kotlinを採用し、Swiftからの移植コストを下げる

  • Clean Architectureを採用してビジネスロジックを簡単にiOS/Android間で使い回せるようにする

  • AndroidでDagger2を採用し、Repository層の設計がiOS/Androidで同じになるようにする

といった方法で開発の高速化を図っています。 まだまだ拙いところも多くありますので、もし本記事にご意見などありましたら教えていただければ幸いです!

なお、弊社では現在エンジニアを募集中です。この記事を読んでもし興味がおありでしたら是非オフィスに遊びに来て下さい! アプリエンジニア以外にもWebエンジニア、データ分析屋さんも歓迎しています。

www.wantedly.com