読んでいて、かー自分もここ10年ぐらい同じような内省をし続けていたではないかと深く共感したので、その過程で身に付けたやり方を書くことにしました。目的プログラミング技術を学習する目的を決めます。僕の場合はソフトウェアエンジニアとしての市場価値を上げる(他のエンジニアから尊敬されたい)とか素晴しいアプリケーションを作れるようになりたい(エンジニア以外からも尊敬されたい)というものがあります。人によってはこれが「GAFAMNに入り渡米してメジャーデビュー」「OSSで一発当てる」「とにかくお金を稼いでアーリーリタイヤ」など様々かと思うので各自考えてください。テーマ目的が決ったら次は学習するテーマを決めます。僕の場合は「○○エンジニア」と呼称されている領域ごとに「この分野で先進的なネタは何だろう」というのをリサーチします。テックニュースやGitHubトレンド、口コミ、求人情報などから探します。それを視覚化します(箇条書きでもなんでもいいです)、僕はMarkdownで下書きして、マインドマップにしました。大テーマである「○○エンジニア」の部分は人によって違うはずです。僕は素晴しいアプリケーションを作れるようになりたいので適切な技術を選定できるように分野を広めに保っているのだと想います。「Netflixで英語学習するツール」を実現したい時、ブラウザ上で動くNetflixのサイトにデータと機能を組み込んで連携させるのが一番良い方法だな、と思ついたとします(実際にそういうツールが存在します)。これにはウェブアプリーケションが動作する仕組みとブラウザ拡張についてのフロントエンド開発の知識が必要になってきます。ところがiOSアプリの開発スキルだけあってもこのアイデアを実現できたりはしませんし、そもそも方法を知らないと思い付かないかもしれません。逆にネイティブアプリでしか実現できないことが手持ちの知識の中にないとそれによって作るものが制限されてしまうこともあるかと思います。枝は少ない方が好ましいと考えています。枝を減らすコツは「別の技術で同じものを作れる」状況をなくすことです。例としてはRubyでもPythonでもWebサーバーは作れますが、SwiftでないとiOSアプリは作れないので、増やすべきはSwiftです。ここに出てくる各固有名詞の製品自体を作りたい人はもっとCSの基礎技術を拾うべきでしょうし、数学、デザインや語学、データサイエンス関連も含める人もいるかもしれません。先進的なネタの基準ソフトウェアエンジニアとしての市場価値を上げるという目的があるので、「先進的なネタ」というのは今現在の業界で起っていることで次の時間軸にあるものを選びます。Railsを使ってWebサービスを作っている企業があり「今後はマイクロサービス化しGo言語に移行したい」という動きがあるとします。それを見据えた時に学習のネタとなるのはマイクロサービスだったりGo言語だったります。無事これらの技術を習得する頃に、世の中に「マイクロサービス化してGo言語に移行したプロジェクト」の総数が増えていれば、需要も上っていてエンジニアとしての市場価値も増すので投資のリターンを得てやったねというわけです。大テーマである「○○エンジニア」の部分は数が多ぎ過ぎなので、どれを優先させるべきかというのを考えます。業務でやる分野だが自分の担当ではない普段の業務でやっていることの順で優先付けします。これは「適切な技術を選定できるように分野を広めに保つ」という考えからまんべんなくステ振りできる方法として考えました。「それぞれの分野の理解が浅くなってしまうのでは?」という器用貧乏症候群については、こう考えます普段の業務では深い理解を求め学習フェースでは広い理解を探索するこうすることで効率よくハードスキルのT字の延せるのだと考えています。いかがでしたか?そもそも私はどの技術的なトピックが将来発展するのかという予測は不可能だと思っています。現実の世界では常に変化し続ける環境の要因が複雑に絡みあっているからです。ビジョンを持って、常に変化し続ける環境に適応する(あとは運)。いうやり方がしょうにあっているのだとソフトウェアエンジニア人生で学びました。FunctionsをGoで書く。Suiteをフル活用してTDDで開発しよう」でした。Functionsでトリガーとなる処理を記述します。Functionsが活用されています。この開発→デプロイサイクルをお手軽に行ってくれるのがfirebase-toolsというnpmモジュールです。Functionsが自動で登録されます。Functionsのモジュールが増えてゆく過程で以下の問題が発生しました。Functionsがどのように動作しているのかを理解して、最終的にfirebase-toolsで構成していたFunctionのビルドを徐々にマイクロなモジュールに分割していくことにしました。関数名という組合せでFunctionを管理しています。特定のリソースAに発生したイベントαにアップロードしてビルド済みのプログラムから指定の関数を実行します。Functionsのリソースが登録されます*2。試しにコンソールからFirestoreのドキュメントを作成してみます実行されドキュメントが更新されました。Firebaseで実装してみることにします。内部で先程のgcloudコマンド同様のリソースができるわけです。Functionsへ直接デプロイすることができたので、次にFunctionをGo言語で実装してCPUメモリあたりの実行速度の高速化を図ります。ボトルネックがI/Oではない典型的なデータ処理のFunctionはこれだけでスループットが向上が期待できます。Clientの準備をします。ランタイムにより指定されているインスタンス毎の初期化処理で、Node.js版でいうグローバル変数にセットアップ済みの値を入れておく方法を似ています。nil}Function本体の処理です。あたるユーティリティがないためドキュメントパスの解決などを自分で実装する必要があります。}}動作確認をGoのユニットテストとして記述できます。写真のリサイズFunctionをGoで実装してみるFunctionのイメージ*3ユーザーがアプリケーションから写真を登録したらシステムで必要なサイズの画像を自動で生成するようなFunctionをGoに置き換えてみます。SDKの初期化時にクレデンシャルを含むJSONファイルのパスを指定するのではなく、環境変数から読み込むようにします(confも同じ形式にできるのですが、秘密情報を含まないためコードで指定しています)。`json:"profile_image_url"`}ドキュメントの構造体をこのように定義しました。いうキーに画像がアップロードされたURLが保存されます。nil}Function本体です。リサイズしてアップロードします(別途Storageへの追加をトリガーにしてUserドキュメントにパスをセットします)検証してみたところNode.js版での公式ドキュメントでの解説にあるようなImageMagickのconvertコマンドを外部で実行するような方法*4と比べて、ファイルに書き出しがない部分がうまく効いて大量のリサイズが一度の実行でできそうでした(リサイズ処理の品質に差がでるかもしれないので別途評価が必要です)。自動的にクラウド環境でビルドが走るようです。あるすべてのファイルが対象になり1つのFunctionのリソースへアップロードされていました(GCPコンソールからアップロード済みファイルが取得できるので確認できます)。Firebaseユーザーの間でFunctionの高速化テクニックとして環境変数から探索して、Node.jsの依存モジュールの動的読み込み制御する方法が知られています。*5これらの方法と比べてアーキテクチャ的に改善する可能性はあるなと思いつつも、まだ安定性やアーキテクチャの評価中なので詳しくは比較できていない状態です。ビルド+デプロイツールの改善firebase-toolsを使わくなることで、複数のFunctionの依存を管理するための方法や開発やデプロイを楽にする方法を別途用意しなければいけません。Functionを分割して複数の依存を管理するパッケージができたことで、ソースコードはmonorepoの状態になります。)のようなツールが機能する環境になるかもしれません。firebase-toolsを使った環境は並行して維持できるので、段階的に移行して検討するつもりです。FunctionsはGoランタイムの他にはPythonランタイムもあり、そちらでも同様にトリガーFunctionが書けるので何か活用法があるかもしれません。APIが公開されていることも多く、SDK対応言語以外でもクライアントを自作して拡張することができます。Runに移すことができそうです。gRPC)サーバー間通信でシステムを拡張の目的でも利用できそうです。Dataflowを使ったバッチ処理。FirestoreをBigQueryにエクスポートして分析し、その結果をシステムに反映させるなどを私たちも既に行っています。まとめこのようにFirebaseはGCPの既存の仕組みを使い易くラップしたものなので、必要に応じてGCPのリソースを活用して最適化することができます。Qiita明日の担当はVexus2さんです。FunctionsをGoで書く。FirebaseのためのマイクロサービスアーキテクチャTweet広告を非表示にするもっと読むコメントを書く2019-04-25いい感じにiOSアプリ開発プロジェクトを立ち上げる方法を考えるpxhere.com*1ここ数年、新規に開発するモバイルアプリのリードになる機会が何回かあり。開発方針を記述していたのだけど、いつも似たような内容になり公共性がありそうなのでそのままブログにした。普段から「今回はアーキテクチャは何を採用しましょうか?」みたいな段階から議論がはじまるのを避けた方が建設的だと思っているので、その思想が反映されている。我が社はこれからゼロからモバイルアプリを使ったサービスを提供するところであり、人手は少ないが開発初期段階から技術に投資する意気込みはあり、いずれはサービスの大ヒット、組織の大規模化を見据えて段階的に成長するアーキテクチャをバーンとやっていきたい。事業領域は例えば決済サービスやビジネス系のモバイルアプリを想定している。ふつうの〇〇プログラミングというシリーズの良書があったり、Railsコミュニティなどでコンテキストとして利用されていたりする便利なイディオム。*2僕の解釈では問題に対して多くの開発者が共通認識で選択する解決手法を採用すること。それによって環境要因や個人の嗜好によって偏りができるのを防ぐことができる。したいのかというと、先の見えない開発なので技術的に凝ったことや挑戦に労力を使うよりプロダクトのUXに大きく寄与する部分に注力するため。技術的な挑戦がUXに直接的に関わる時は別。個人やチームの成長のための技術的投資は基本的にサイドプロジェクトでやることにしてる。プロダクトの特性上、モバイルのアプリケーションの表面上でできる体験より。バックエンドのビジネスシステムの信頼性や運用にかかる効率化が価値となると考える。Nativeを使わない開発対象が素朴なUIを持つツールである。ドラゴンも出てこないしアイドルのライブ配信もないユーザーがKyashやメルカリみたいなものを期待するとギャップが生じガッカリさせてしまうアップデート・保守面のコストが許容できないPMF検証フェーズであり、クロスプラットフォーム提供の旨みがない。強い人は勝手にやってくれ)経験上FRPや宣言的View+データバイディングをがんばりはじめると、受け入れる複雑さがコードの保守性や品質向上にペイしないため非同期処理の問題解決のためだけに採用されるケースもある。将来のSwiftでasync/await世代の方法論が出てきた時のために、サードパーティ依存な部分を減らしたい小さく使う方法はあるのかもしれない。RxCocoaデータバインディングだけ抜き。Storyboardを利用。Feature単位でファイルを切る多人数開発ではないのでコンフリクトのリスクが低い標準コンポーネントを使って、デザイナ作業が不要である程度楽に開発が進む単体テストは書く状態管理フレームワークを検討するぐらい複雑なら必須!TDDはがんばらずに、脳内でシュミレートして開発を促進させそうな部分だけ書く(自己判断)CIサーバーの運用とかがんばらずに最初は手元で実行できればいい一方デプロイ自動化は今後何百回もやることがわかり切っているので最初からやるモック化とかも考えずにE2Eになる部分がでてしまってもよい(むしろ設計に役立つ)ドメイン/プレゼンテーション分離の設計を意識するため(あとからまとめてリファクタリングするのは難しい)迷っていることサーバーサイドとのデータやりとり受信のみ。