2016の11日目の記事です。Readerについて書きました。https://jasperapp.io/https://github.com/jasperapp/jasper今回はそのJasperの開発初期、リリース期、運用期での出来事を時系列でまとめました。技術的な話はあまり多くありません。どちらかというと僕自身の備忘録としてJasperの開発史をまとめたものになっており、すごく長い記事になっています。開発初期2016年2月から2016年5月ごろの開発時の話です。requestを投げたりします。Requestの通知メールやサイト上での通知が大量に流れてきます。それらを処理するのがすごくすごく大変でこれをなんとかしたいなとずっと思っていました。そこで、GitHubのIssueを効率的に処理できるデスクトップアプリケーションを作ろうと思いコンセプトを考え始めました。APIを組み合わせていい感じに通知を受け取るというのを考えていました。これらのAPIではちょっと汎用性が足らないなと気づきました。Requestを中心に仕事をしていると、各自それぞれが自分なりの仕事のスタイルやユースケースを持っています。自分がメンションされたもの、チームメンションされたもの、特定のリポジトリ、特定のOrganization、特定の単語が入っているものなどなど。各自はこれらのユースケースを組み合わせて仕事をしているので、アプリでそれらを解決できる必要があります。わかりやすい操作(=わかりやすい概念)で使える必要もあります。ここで、ちょっと煮詰まってしまったのですが、あるときGitHubのIssue検索APIが超強力だということに気づきました。先程あげた様々なユースケースに対応できるだけの十分な検索機能を持っています。そこで、ユーザが「自分がみたいIssueの条件を自由に設定する」と、内部的には「Issue検索APIをポーリング」するというアイデアを思いつきました。この概念を「自分が興味のあるIssueが流れてくる」と捉え、「Stream」と呼ぶことにしました。以下のようなStreamを作ることになります。requestその後ElectronやIssue検索APIの技術的な検証をし、このコンセプトを実現できることを確認しました。コンセプトを考え始めてからここまでたしか1ヶ月くらいだったと思います。初期の実装は土日の二日間でいっきに作り上げました。コード行数にして700行程度です。翌日の月曜から会社で使い始めました。これだけ短時間で作れたのも僕がNode.jsやブラウザ上でのJSの使い方、HTMLやCSSになれており、それをそのままElectron上で活かすことができたからです。いってもまだまだ荒削りで、アクセストークンやStreamの設定画面はなくて直接アプリに組み込む必要がありましたし、デザインも全然されていない本当にミニマム実装というものでした。一刻も早く実践で使うことによって改善点を得たいというのがあり、結果としてこれは大成功でした。この初期実装で作ったコードは今もJasperのコアなコードとして使われています。issueクライアント、ドックフーディング始めたらどんどん改善点がでてきた。完成まで道のりは長そうやな。2016年3月22日フィードバックループ初期実装から少しして、知り合いのエンジニアやデザイナーにテストに参加してもらうようになりました。この頃は設定画面もなくて、僕が個別にアプリに設定を書き込んで配布したり、生の設定ファイルを直接編集してもらうなどで対応していました。その後、ユーザ自身で設定できるようにUIを作り込んだり、フィードバックをもらい改善や機能追加を行っていきました。このフィードバックループを20回ほど、期間にして2ヶ月くらい行っていました。issueクライアント、温かみのある手作業でユーザ毎の設定をして、アプリを配布してたけど、そろそろ何とかしないと。自作issueクライアントの社内テストにサービス開発、デザイナー、ディレクター、インフラから参加してくれている。この人達のユースケースを満たせたら、だいたいOKな気がする。2016年3月28日はぁ、自分で作ったissueクライアント便利すぎる。issueの見落としはなくなったし、メンバーが関わったissue・関連するチームのissue・気になるワードが入ってるissueもチェックできる。tracker)のおかげでGHEからのメールはもうもったくみなくなった。メンションやら関連するissueは全く見落とさなくなったし、見落としてるかもしれないと言う不安が一切なくなって、気持ちが楽になった。tracker、まだ一般公開にはちょっとかかるけど、自分で使うにはかなり満足してる。今までJSでIssueのフィルターを実装していて、2000件に1000msecもかかってた。それをSQLiteでやれるようにデータ構造変えたところ、50msecぐらいになった。技術的に面白かったことフィードバックループを回してる中で面白かった技術的な話を少し紹介したいと思います。SQLiteJasperではデータのストレージにSQLiteを使っています。installしたものをElectronでもそのまま使えていました。ある時から急に専用にビルドし直さないといけなくなり、少し苦労した覚えがあります。言うと当時はelectron-rebuildが僕の手元ではうまく動かずモジュールをビルドすることができませんでした。僕自身ネイティブモジュールの経験もなかったため、対応方法もよくわかりませんでした。探し回ったり試行錯誤したあげく、node-gypで自分でビルドしなおすことで解決できました。--module_path=../lib/binding/electron-v1.4-linux-x64async/awaitJasperではSQLiteの読み書き、GitHubのAPI呼び出し、ポーリング、などで非常にたくさんの非同期処理を実装する必要がありました。ここですごく役に立ったのがES2017に入る予定のasync/awaitという言語組み込みの非同期処理機構です。一言で言うと非同期処理を同期的に書くことができるすごく便利なものです。Jasperではこのasync/awaitをがっつり使っており、アプリ全体で全350メソッドのうち120メソッドでasync/awaitが使われています。一定間隔で処理をするポーリングのようなものはasync/awaitを使ってこのように書くことができます。doFinish();}Photon僕はデザイン(ビジュアル)の力は殆ど無いので、いい感じの見た目をお手軽に作るためにPhotonというElectronようのUIツールキットを使っています。Photonを使えばMacのようなUIを簡単に作ることができます。ターゲットがElectronだけの単一プラットフォームなので、Flexboxでレイアウトを組まれているのもモダンで良いです。あとは組み込みのアイコンフォントも数は多くないのですが、使い勝手が良いものが揃っており便利です。当初Windows対応はあまり考えていなかったのですが、テストに参加してくれた人が自力でWindows対応をしてくれました。いうのもElectronはもともとマルチプラットフォーム対応をしているので、Jasperから必要な部分を取り出し、Windows用のElectronバイナリに載せ替えれば動くからです。ネイティブモジュールを使っているところは各プラットフォームごとにビルドする必要がありそこがやや面倒ではあります。この方はその部分も自力で解決してWindows環境でテストしてくださいました。いう経緯もあり、これは僕自身でちゃんと対応しておいたほうが良いなと思い直し、Windows版も作ることになりました。後にLinux版も作りました。いっても、コードはほぼ変更する必要がなくて、ファイルパスの扱いとネイティブモジュールのビルドだけ手を加えただけです。Electronがマルチプラットフォーム対応しているの本当に便利で最高です。リリース期2016年5月から2016年6月のリリース作業中の話です。Store(以下MASと言います)の両方にリリースすることにしていました。Gumroadは審査があるわけではないので簡単に登録できるのですが、MASの方はAppleによる審査があります。その審査にJasperが通らずリリースすることができない状態が1ヶ月近く続きました。リジェクトされたのはJasperの実装に問題があったからではなく、Electron自体にいくつかの問題があったためです。v0.35からv0.36でChromeのバージョンがあがり、MAS用のサンドボックスビルドでElectronがクラッシュするようになってしまいました。この問題により、審査どころかサブミットさえできませんでした。2週間ほどしてcom.apple.security.temporary-exception.sbplという権限をアプリに付与することでクラッシュする問題は解決されました。Entitlementsこれでようやく審査に出せると思ったのですが、今度は審査でリジェクトされてしまいました。理由はクラッシュする問題で付与したcom.apple.security.temporary-exception.sbplの設定値が適切ではないということでした。古いバージョンのElectronではこの権限が不要だったので使用しているElectronを古いバージョンにダウングレードしたりもしたのですが、動作が不安定になるのであきらめました。リジェクトされてから3週間後、Electron側での対応がすすみcom.apple.security.temporary-exception.sbplがそもそも不要になり、この問題は解決されました。APIようやくこれでMASでリリースできると思ったのですが、今度はElectronのChromeがMacのnon-publicを使っているということでリジェクトされてしまいました。こちらは問題が発覚してからすぐにElectron側で対応してもらえました。#212このようにJasper自体の実装ではなくElectron側の問題によるMASにリリースできずにつらい思いをしていました。最後の方はちょっと心がおれかけて、MASでのリリースは諦めようかと思っていました。ちなみに、MASでリリースする場合はサンドボックス環境でアプリを動かすために、アプリが必要とする権限を明示的に設定する必要があります。ネットワーク使用権限、アドレス帳へのアクセス権限などです。詳しくは以下のURLを参照してください。Entitlementsアイコン作成アプリのアイコンを同僚のtransit_kixさんにお願いして作ってもらいました。最初にアイコンのラフアイデアを手書きで10個くらい作っていただきました。そこから気に入ったものを選ばせていただいて、ブラッシュアップしていくという流れになりました。このラフアイデアを見せてもらったときに驚いたのが、transit_kixさんの思うJasperのイメージと僕の思うイメージがすごく近かったことです。transit_kixさんにもJasperのプロトタイプを業務で使ってもらっていたというのもあると思うのですが、すごい汲み取り力だなーと感動しました。それとブラッシュアップのときにもすごいと思ったことがあります。それは「僕の要望を最大限くみとりつつ、バリエーションをいくつも提案してくれたこと」「transit_kixさん自身の意見の押しつけみたいなのは一切なかったこと」です。後者は、絶対に本職のtransit_kixさんのほうがセンスは良いので、多分言いたいことをぐっと我慢してくれたんだろうなーと思います。勝手な想像ですが、僕がアイコンを気に入るというのを重要事項におきつつ、デザイン的にも良くなるようにというバランスを取りつつ作ってくれたのかなと思います。プロという感じで尊敬しています。2016年5月9日Electronのサイトに掲載ElectronのサイトにはElectronで作ったアプリを紹介するページがあります。requestを送ると中の人がレビューをしてくれて、問題なければマージして載せてくれます。僕の場合はちょっとアプリの説明に問題があったので、指摘が入りましたがそれ以外は特に問題なくマージされました。#352Electronでアプリを作った際はここに掲載するのを絶対におすすめします。ここから結構な数がJasperのサイトへ流入しているので、アプリのよい宣伝になると思います。運用期期2016年6月からしばらくJasperの開発は休んでいました。私生活が少し忙しくなったり、ESDocの開発をしていたためです。ここでは開発を再開した2016年10月から現在に至る話です。Store(以下MASと言います)で販売をしていました。2016年10月末ごろにMASから撤退しました。これは幾つか理由があります。https://itunes.apple.com/jp/app/electron-apis/id1119345146?mt=12MASではクーポンコードやベータアプリの配布ができないことクーポンコードはイベントなどで配れるとマーケティング上すごく便利ですベータアプリは開発段階の機能についてユーザからフィードバックをもらえるため非常に有益ですこのようにMASには様々な制限や不便な点があるので、MASでアプリを配布する場合は十分に検討したほうがよいと思います。有料アプリ、Electron(非ネイティブ)アプリ、マルチプラットフォームアプリを開発している場合には。ライセンス販売への変更MASから移行と同時に、それまでは「有料バイナリアプリを販売する」という形をとっていたのを「ライセンスキーを販売する」という形に変更しました。具体的にはGumroadのライセンス機能を使って、ライセンスキーを販売し、アプリに登録してもらうというものです。ライセンスキーの販売にしたかというと、有料バイナリを販売している状態では自動アップデート機能を提供することが難しいからです。いうのも、自動アップデート機能はネット上から最新のアプリをダウンロードしてくる形になるので、有料バイナリをネット上のパブリックなスペースに置く必要があるからです。有料バイナリ自体に認証機構を持たせて有料バイナリからしかダウンロードできないようにするという方法もあります。運用を極力楽にしたいのでできればやりたくありません。ライセンス販売にするとフリートライアル版と有料版のバイナリを同じにできるので運用が楽になるのと、フリートライアルから有料版へのアプリの更新をしなくてよくなります。Gumroadのライセンス機能はシンプルで簡単にアプリに組み込むことができるので、有料アプリを開発する場合に検討してみると良いと思います。その手軽さゆえにハックされやすい形になっています。Electron自体が簡単にアプリの中身を見れるものなので、そういうことを気にしなければならない場合、Electron自体が選択肢から外れるとは思いますが。1つ注意点として、有料バイナリ販売からライセンスキー販売にする場合、ユーザに移行作業をしてもらう必要があります。MAS版のアプリを使っていたユーザには大きな負担をかけることになり、非常に申し訳なかったなと思っています。今後有料アプリを販売される方は、どのような形で販売するかしっかり事前に検討したほうが良いと思います。ちなみにJasperでの移行手順はここに書いてある方法をとりました。GumroadのダウンMASを撤退し、Gumroadに統一して平和な日々を送っていました。NodeFest2016での発表を控え資料の作成などをしていたときです、急にGumroadがサイトごと落ちてしまいました。GumroadのライセンスAPIも落ちてしまい、Jasperのライセンス認証が失敗するようになりました。GumroadのTwitterアカウントでも特に反応がなくて、「このままGumroad無くなるとかないよな!?」とビクビクしていました。その後、2~3日Gumroadが不安定な状態が続きましたが、なんとか復旧しました。この期間は非常に辛く不安だったのを覚えています。gumroad落ちてる・・・。Jasperのライセンス認証が失敗する・・・。