スタートアップの技術選定

CureApp では JavaScript をメインの言語に据えて開発しています。なぜ JavaScript なのかきちんと考えて選択しているのですが、 @shinout がこの話題に触れたのが 9 ヶ月前で現在とは状況が変わっていること、あまり公にする機会がないことなどから、もう一度ここで書いてみます。

http://cureapp-dev.hatenablog.com/entry/2016/03/31/160039

CureApp はまだ創業 2 年ちょっとのスタートアップです。そういったリソースが少ない前提でどんな言語を選ぶと迅速に目的を達成できるか、という話題となります。

言語として
----------

### 標準化されているか ?

標準化によって言語仕様に大きな変更が入ることも少なくなるため、リソースが少なくてもキャッチアップしやすくなるということでこの点は重要です。処理系によって重要なところでの差異が生じないため処理系ごとの対応に追われることも比較的少ないのかなと考えています。

ISO で標準化されているプログラミング言語のうち、現在でも汎用的に使われているものをあげると次になるかと思います。

- C
- C#
- C++
- ECMAScript ( JavaScript )
- Ruby

### 習得の容易さ

できるだけ習得が容易なものを選んだほうが迅速な目的の達成が可能になります。習得が難しいとチームメンバー感のスキル差が開きやすくなり、チーム間で同じ語彙を使って話すことが難しくなるなどの弊害が出るからです。

上にあげた言語のうちメモリー管理をプログラマーが意識する必要があるものは C と C++ となります。メモリー管理が必要なプロダクト・場面は確かにあるのですが、まだ必要に迫られることはないと考えています。

### 周辺ツール

C# はとてもよい言語だと思っているのですが、 IDE が前提なのでメンバーの学習が頭打ちになりやすいことがちょっとした懸念です。 IDE は開発効率がそれなりに高くなる反面、そのサポートに慣れてしまうと乗り換えることが難しくなってしまったり、同様のことを自力でできなくなってしまいます。

### 手に入る情報

Ruby も JavaScript も日本語の情報を入手しやすいため、習得に苦はないと考えています。標準化や最先端の動向は英語となりますが、習得とはまた別の側面なので影響は少ないです。


開発要員の確保
--------------

開発要員を確保するにあたって、次の要素が大きいと考えています。

- 必要な知識・スキルが組織で統一されていること
- 必要としている知識・スキルが世の中で広く使用されていること

知識・スキルが統一されていると多くの方に疑問・質問できるため、迅速に問題を解消しやすくなります。同時に、チームビルディングするにあたって考慮すべき事柄が減ることもメリットです。

http://qiita.com/janus_wel/items/a5d62534f487ba2c02eb

また、世の中で広く使われているものを選ぶことで採用にあたって大きなアドバンテージを得ることができます。日本では大体次のものから選ぶ形になるでしょうか…。

- Java
- C
- JavaScript
- Ruby
- C#


マルチプラットフォーム対応
--------------------------

CureApp はビジョンとして「アプリで病気を治療する未来を創造する」を掲げています。そのため、モバイルアプリへの対応は必須です。さらに管理ツールとして Web アプリケーションや各種 OS のデスクトップアプリへの対応があります。

現在のところこれらの要求を満たせる言語は JavaScript しかありません。やはりブラウザー上で動く言語が JavaScript のみということが非常に選択肢の幅を狭めています。

- Web
    - Node.js
    - React.js
- iOS
    - React Native
- Android
    - React Native
- Desktop
    - Electron

React が使えることも JavaScript の魅力のひとつで、 Learn once, write anywhere という思想のため、同じメンバーがすべてのプラットフォームに対応可能です。

チーム開発にあたって
--------------------

いままで書いてきたことを総合して JavaScript を選択しています。ただし、 JavaScript そのままではチーム開発は非常に心もとないということも確かです。そのために次のような工夫をしています。

### ツールの活用

JavaScript には型が存在しないため、論理的な誤りを見つけにくいという側面があります。そこで型チェックをする `flow` と契約による設計を実現するための `assert` を使って早めに誤りを見つけ出すということを心がけています。

http://qiita.com/janus_wel/items/da1fcfc8d50969135b31

さらに ESLint による静的解析をあわせることで、ケアレスミスを防いでいます。

### DDD

設計方法として DDD を採用しています。複雑な業務知識を閉じこめてマルチプラットフォーム対応を加速させるためということが第一義ですが、設計手法を統一し、チーム内で意思疎通をはかりやすくするという側面もあります。

http://qiita.com/janus_wel/items/2661ccad4a97e68a284b

### サブプロジェクト化

あるていどプロジェクトが大きくなってきたり、マルチプラットフォーム対応しようとするとひとつのプロジェクトでは管理しきれず、サブプロジェクト化してそれを連携させていく形になります。

ちょっと前までは private github repository から直接落としてきたり、 private npm repository を使用するという選択肢だったのですが、これらの方法では複数のサブプロジェクトにまたがる変更が非常に大変というデメリットがあります。

- http://qiita.com/shinout/items/c6f12d69e68b312d62fa
- https://www.npmjs.com/features
- https://github.com/rlidwka/sinopia

そこで、現在ひとつの git repository に関連するサブプロジェクトを集約する monorepo という管理形態へシフトできるかを実際に運用しながら試しています。

https://github.com/lerna/lerna
https://github.com/januswel/lerna-sample

調査した結果、 monorepo によって前述のデメリットが解消できることがわかりました。また、各サブプロジェクトで使用していたツールバージョンが異なっていたこと、 npm scripts の命名に一貫性がなかったことなどがひとつに集約されたことで解消され、とても快適になりました。

といったようにメリットだらけなのですが、すべてのサブプロジェクトのテストを通そうとすると非常に多くの時間がかかってしまうことが現在わかっているデメリットです。これについては普段実行すべきテストをタグによって切り分けたり、テストの並列数をあげるという対応でなんとかなると考えています。

また、一点注意が必要になりそうな点として、 yarn が lerna を取り込むかもしれないというハナシがあります。

https://github.com/yarnpkg/yarn/issues/946#issuecomment-264597575

ただ、これが実現しても monorepo のメリットは変わらないため、いまのうちに見極めておくのがよいかもしれません。


まとめ
------

JavaScript を選択した理由について書いてみました。もちろん 1 年後にどうなっているかはわかりません。また状況が変わってプラットフォームごとに最適な選択肢を選んでいるかもしれませんし、このままかもしれません。が、きちんと考えた上で選択していくでしょう。

一点断っておくと、 JavaScript 以外を学べないという環境ではありません。英語を学ぶことで日本語がより深く理解できるように、最低でも 2 言語以上に触れるべきと考えていますので、むしろ JavaScript 以外を学習することを強く推奨しています。実際に React Native の開発では Objective-C や Java に触れる機会がありますし、今後本格化しそうな WebAssembly への準備として C/C++ の学習も大歓迎です。チームには Elm を追いかけている方もいらっしゃいます。

明日は最終日、 @shinout の記事です !!