Kururu - テスト管理ツールをなぜ作ったのか【前編】

自分が実はテスト管理ツールを作っているというと、多くの人の反応は「そうなんだふーん」というリアクションが多い。もちろん、個人開発をしている人の多くがこういう反応をされる。
正直こういう反応は慣れていてとくに問題があるわけではないが、エンジニアであっても9割方の人はそもそもテスト管理ツール自体を知らないケースが多い。例えば、OSSで言うとTestLinkが有名ですよと説明してもあまりピンと来てない人が多い。*1テスト管理ツールを知っているのはSIer出身の方が多くWeb系の知らないこと人が多い印象を持っている。なので今回は何故自分がテスト管理ツールを作ろうとした動機を書いていく。長くなってしまったので前編となる。

サブスクリプションモデルの浸透

いきなりテスト管理ツールの重要性を書いてもピンとこないので背景にあるビジネス的な面から説明していく。

まず、サブスクリプションモデルの浸透*2について。サブスクリプションモデルの代表的な業界でSaaS業界を挙げると、国内では15%・海外では20%の成長率となっている。またtoCの分野でも最近ZOZOが有料会員を打ち出したりしてSaaSの枠にとらわれない代表的なモデルになっている。エンジニア・デザイナーでわかりやすい例でいうとAdobeも何年か前に買い切りからサブスクリプションモデルに移行している。今後も非常に市場規模が大きいライドシェア市場においてもサブスクリプションモデルが採用されるため、より今後もサブスクリプションモデルの浸透は増していく。

サブスクリプションモデルのビジネスインパクトについてはこの記事の趣旨と違うので省くが、開発面においてもサブスクリプションモデルの影響は受ける形となったと自分は考えている。

サブスクリプションモデルが開発にどういう影響を与えたかと言うと、アジャイルとの相性が非常に良い。というよりもサブスクリプションモデルを継続するのにはアジャイルでないと継続するのは不可能でさえ思う。
サブスクリプションモデルでもっとも重要なのは継続的な改善である。売り切りではないため継続的にユーザーの行動・要望を分析しサービスの改善に活かないとユーザーは別のサービスに乗り換えや解約に繋がってしまう。この継続的な改善がないとサブスクリプションモデルは、それただの月額制ですよね?となってしまうのでここの違いはきっちり認識する必要がある。
そして継続的な改善を実施するにはウォーターフォールでは対応出来ないのだ。顧客の要望を迅速に取り入れるには要件をしっかり定義している時間がない。70%ぐらいの確度でリリースしていく方がメリットが大きい。*3

後編の記事ではアジャイルテスト管理ツールの関係性について解説していく。

*1:これは別に悪いことでは全然ない

*2:https://boxil.jp/mag/a4946/

*3:余談になるが、エンジニア同士でウォーターフォールアジャイルによるプロジェクト管理の論争が巻き起こるがこういうビジネス観点が抜けているケースが多い。また、新規開発・大規模なシステム更新というプロジェクトではウォーターフォールで実施した方が経験的に失敗しにくかった。

TypeScriptとevent.persist()

備忘録

ReactとTypescriptの組み合わせで、event.persist()を型付けをしたい場合。
以下のように書けばコンパイルが通った。

const handleChange = (event: React.SyntheticEvent<EventTarget>) => {
    event.persist();
    ~~~
};

取り急ぎ細かい理由はわからんが。。 理由はこれかな?

簡単に説明すると、eventオブジェクトはReactによってSyntheticEventオブジェクトとしてラップされていて、パフォーマンスのために使いまわしてますよ。

参照先:

stackoverflow.com

2018年の振り返りと2019年に向けて

2018年についての振り返り

Kururuのリリース

Kururu - テスト管理ツール

非常に時間がかかった。。結局、前年作っていたのはやめて再度企画も含めてやり直しをした。再度実装したことで遅くなっと指摘されることもあったが初回リリースまでは自分のエゴ(納得感)で進めることを優先した。結果的にはモチベーションが上がったので良かったと思う。詳しくは個人開発を支えるメンタルという記事でも書いている。 勿論、まだまだ足りていない機能は多く満足はしていないが、リリースによりマイルストーンを刻むことが出来た。
今後は大型機能の追加をいくつか予定している。

技術的な観点

2017年に引き続き技術力は向上した。主に向上したところは以下の点。

クライアントサイドは2017年の末から本格的に取り組み始めて、2018年においてはついにバックエンドよりもフロントエンドの方が書いたコード量は多かったと思う。これには理由があって、iOSの開発を業務委託の仕事で携われたことが一つ挙げられる。今年の目標の一つにモバイルアプリの開発に携わるというのがあったのだが無事目標は達成できた。特にRxSwiftなどの関数型に影響を受けたライブラリをがっつり経験出来たのは十分な成果である。もしiOS開発が今後発生したとしてもアレルギーがなく開発が出来る。
もう1点はKururuの開発でSPA(React)を使用して、むしろお腹いっぱいというほど書いたことである。もともと、業務委託先でも書いていたのだがKururuの個人開発でも沢山書いてたので十分すぎるぐらいである。 前年度にはVue.jsも書いていた。

関数型言語への取り組みも2017年の末からJavaScriptの勉強を通して大きく理解が進み、今年度はKururuのバックエンドでElixirを使用してみた。Elixirについては別記事でも書いたが非常に書きやすく、生産力も含めて今一番好きな言語である。恐らく、特に理由がない限りは個人開発においてはElixirを中心に書いていくと思う。また、完全な個人的な趣味でHaskellを通してモナドを学び、Rx系のObservableの理解の役に立った。

他にもCIについても知見が貯まったが代表的なのは上記の2つ。もともと、正社員の時は純粋なバックエンドエンジニアだったのに大分スキルセットが変わった。ただ、改めて正社員の時はレガシーな環境でモダンな技術に触れることは少なかったがドメイン駆動・クラス設計・プロジェクト管理などの基礎的な技術に力を入れてよかったと感じる。スキルのキャッチアップ、及び実務の仕事では基礎技術をやっていたことが大きく為になった。
お金に繋がりやすい技術もやるが、すぐにはお金にならない基礎的な技術もやっていくことに意義を体験から学んだ1年間だった。

2019年について

ビジネスで成果を出す

今年度はついにKururuをリリースすることが出来た。これを運用・改良していき売上を上げるところまで持っていきたい。勿論、かなり難しい挑戦になるが業務委託以外の売上を出すことは大きな経験となるはず。
まだ目玉となる機能の実装が終わっておらず、売上を立てられる機能の実装も終わっていないので、直近では大型機能追加作業がメインになる。ここについては業務委託の仕事をお休みして集中的に取り組んでいくことにした。直ぐに売上を目指すという方向性もあったが、これだけ小さなサービスの場合は圧倒的なクオリティが重要だと今の段階では感じている。

マーケティング活動を直ぐに力を入れない理由として以下の2点から判断した。

  • プロダクト・マーケット・フィットを確認しきれていない
  • 元々専門ではないマーケティングでは費用対効果が薄い

プロダクト・マーケット・フィットをまだ確認出来ていない状態でグロース施策を打つことは逆に費用対効果が悪いと判断した。売上がしっかり立つまではプロダクトのクオリティを上げることに力を注ぎたい。また、元々専門ではないマーケティングは費用対効果も薄いと感じた。


勿論、Kururuに力を注ぐことにリスクもあるがコツコツ準備はしてきたので当面生活で困ることはない。ただ、来年の景気についてどうも不景気になりそうなので柔軟に生活面の資金については対応はしていく。

技術面

最新の技術面のキャッチアップはフリーランスの2年間を通じて随分挽回できた。よって2019年はビジネス面を優先はさせる。
その上であえて技術な取り組みをするのであれば、去年土台を築いたiOSの開発を今年も継続出来たらと考えている。過去にAndroidの開発をしたこともあったが、すっかり忘れてしまい勿体無かったので折角のiOSの開発経験は残したい。本当は最初はビックデータ関連の技術をキャッチアップしていく予定を考えていたが、フロントエンドの開発と両立することと、独学で勉強することは難しいので今年は保留する。

ただ、長期的に考えるとビックデータ関連の技術はインターネットと同じくらい世の中にインパクトを与えるので隙間時間で学習はする。

まとめ

ビジネス面を頑張るというのは長期的な投資という意味もあるが、改めて全力で走るという意味がある。来月で30歳という節目において自分の経験したことの無い未知の領域に対して挑戦したいというのが本音である。今までエンジニアという専門性で守られていた部分があるので、来年は少しエンジニアの武器を手放して自分の力を試していきたい。

終わり。

サーバサイドの人間がiPhoneアプリ開発に入門した

今回は普段Web側で開発している私がiPhoneアプリ開発を経験した内容を書いていきたいと思います。

iPhoneについて知る

元々、AndroidユーザーということもあってiPhone自体の固有の動きが知識が不足してました。細かいことを言うとここをタップするとこういう動きになるよねという知見が少ないので困ったりしました。なので出来るだけ開発する前からiPhoneを使った方がギャップが少なくなります。

Swiftについて

Swift自体の言語の感想としてはクセが少なく素直な良い言語だなという印象を受けました。言語仕様としてここが書きづらいというのも少なかったです。
たぶんほとんど人が鬼門になるのはOptionalの使い方です。慣れといえば慣れで解決できるのですが、ScalaJavaにもOptionalは導入されているので自分の場合概念自体はすぐに理解できました。意外と苦戦したのが?の使い方で色々と使い方があったのでそこは混乱しました。
ただ、Optionalは頻繁に出現するのでここをきっちり理解しないと中々開発効率は上がらないと思います。また、SwiftにはHaskellのdo記法やScalaのfor式に相当する糖衣構文がないので入れ子になったOptionalをunwrapするのは少々手間取ります。 またバージョンアップが激しい言語なので、Swiftのバージョンアップをするとこのライブラリが動かないというのはよくありました。

デザインについて

一番苦戦したのがデザインです。Auto layoutの仕組みは今まで経験してこなかったので難しかったです。特に凝ったデザインだと複雑な組み方をして対応していることがありました。ここが一番経験者と入門者でのレベルがつきやすい箇所だと思います。

設計について

iPhoneアプリの設計についてMVVMやClean Architectureなど様々な設計方法があります。その中で私はReactorkitを使った開発をしました。RxSwiftを使ったFluxスタイルの設計になります。個人的にReduxを使ったことがあったので、このアーキテクチャの考え方はすぐに理解出来ました。RxSwiftも以前RxJsを使ったことがあったので大きく躓くことはなかったです。ただ、Subjectの使い方を今いち理解していなかったのでそこは理解出来るようになりました。

まとめ

全体的に既にフロントエンドを担当したことがある人ならアプリも理解しやすいです。
私の場合さらにRx系の経験もあったので躓きが少なかったです。さらに今まで直感的に理解していたWebアプリよりもネイティブアプリの方が時間がかかる理由も理解できました。WebでいうとフルスタックのSPAを作っている状態であり、考えることが明らかにシンプルなWebアプリよりも多いです。もし今後ネイティブアプリを作るのであれば、作る必要性を吟味してから開発はした方が良いです。

GraphQLのメリット・デメリット

最近GraphQLを扱うことが多かったのでその印象をまとめておこうかと思います。 現在、2018年10月の印象なのでここで上げたデメリットは今後解消されるかもしれないので悪しからず。

メリット

エンドポイントをいちいち設定しないで済む

扱ってみて最大のメリットだと感じたのが、RESTと違いエンドポイントが一つしか無い点です。そんなもんかと思うかもしれませんがGraphQLを使ってみていかにエンドポイントを新しく作るのが面倒だったのか痛感しました。
通常エンドポイントを作るには以下の作業が必要です。

  • URL設計
  • エンドポイントの共有
  • クライアント側の修正
  • サーバ側の修正

これらの点をGraphQLならサーバ側が新しくスキーマを定義して上げれば済むので、後は勝手にクライアント側が利用するだけとなります。

GraphiQLサーバが便利

だいたいどの言語のGraphQLを扱う仕組みでもGraphiQLサーバが実装されています。GraphiQLサーバではクエリをチェック出来るのでドキュメント代わりになれます。なのでAPI仕様書をいちいち作らなくても非常に便利で後はクライアント側がそこを参照さえすればいいので、タスクが疎結合になります。

型が定義されている

RESTもちゃんとやれば別に問題ないのですが結構神経を使うのでそこはGraphQLだと事前に定義するので便利でした。

デメリット

Apollo Clientが枯れていない

GraphQLを扱うとするとだいたいみんなApolloにたどり着くのですが、正直まだ枯れていないです。というよりGraphQL自体が枯れていないのでベストプラクティスがまだ発見されていないというのが正確だと思います。私はiOSではApolloを使いましたが開発途上だなというは感じました(Swiftとのバージョンの組み合わせなど)。
また、JavaScriptではReactとReduxで併用しようとしましたがと共存させかたがよくわかなかったのでApolloは見送って以下のミニマムなライブラリを使用しました。問題は全然無かったです。

github.com

見送った別の理由で言うとApolloapollo-link-stateという新しい概念を提唱しているのですが現段階では流石に運用事例がほとんど無かったので見送ったのも理由です。万が一今後伸びてくるのであればその時に乗り換えればいいかと判断しました。

情報が英語

日本語の情報は非常に少なくだいたいは入門レベルなのできっかけにはなるけど全てカバー出来るわけではありませんでした。そのため英語の公式ドキュメントに頼ることになります。ただ英語ドキュメントでも使い方は載っているけど、困った時にどういう風に解決したかという情報はネット上には少なかったです

まとめ

GraphQLを導入した方がいいのどうなのという意見でいうには、新規開発ならぜひ採用してRESTを置き換えるなら無理して導入しなくていいんじゃねというのが感想です。教育コストが云々の話もありますが一人がちゃんと勉強して横展開すればそこまでコストもかからないというのが印象です。

金額計算の設計に挑む

cassetteの延澤です。 今回はみんなが大好きなお金、、の設計について書いていきます。

きっかけ

皆さんは金額を扱うアプリケーションを構築したことがありますか?
私は何だかんだ最近までお金を扱うアプリケーションを構築したことがあまりありませんでした。理由とすると金額を扱うシステムは専門の部署・人が行うことが多かったので既に構築されていることが多かったです。しかし、最近になって開発することになって少し知見が貯まったので折角なのでを書いておきます。

お金を扱う難しさ

一番難しいと感じたのは後方互換を残すことです。例えば、過去にユーザーに領収書・請求書を発行した場合、将来のシステム改修で過去の金額がズレることは避けなければいけません。また、決算においても売上・消費税の計算がズレるのはよろしくありません。
しかし、ユーザーの要望を満たすために決済手段は増えるし、様々な割引きプラン設定が金額計算をどんどん難しくさせます。そして気づいた時にに決済・会計ロジックはかなり複雑となり工数の増加を引き起こします。そして、最終的にズレる金額と対する早急な調査作業。。書いてて疲れてしまいました。

お金を不変として扱う

例えば、売上を1000円計上する場合はDBのカラムに格納します。そして、税率も同時に保存しておくと良いです。

売上 税率
1000 8

単純に定数として税率を設定していた場合、いつからその税率が適用されたのかが分かりにくくなるからです。それを回避するために同時に適用した税率も保存しておくことで後の計算をしやすくなります。また、全ての計算した金額も入れておきます。

税抜き 税率 税込み 割引金額 最終価格 手数料率 作成日時
1000 8 1080 500 580 20 2018-09-01 15:00:00

以上のように割引金額の計算ロジックや手数料率の計算は変更の入りやすい箇所でもあるので、その時の適用された金額や料率も格納しておきます。そして金額を表示する際はプログラムでごちゃごちゃ計算せずに素直にDBのカラムに保存してある金額を表示するほうがシンプルで楽です。 なので金額計算においてはdryで書くのではなく、毎回計算した値をDBに持っておくことで後で計算ロジックが変わっても過去のデータの考慮が少ないです。 *1

あと、金額計算を確認できる機能を管理画面に設置していると運用も楽になります。 また細かいことを言うと売上をいつ計上するのかという日付も会計上重要ですがここでは割愛します。

まとめ

販売管理システムは経験の差が出やすい箇所だなと感じました。
最新技術のキャッチアップは若手が有利ですが、こういう複雑で重要なビジネスロジックを構築できることはシニアエンジニアの強みでもあります。

*1:因みに割引金額が適用されるのが税抜き前に適用するのか税込みに適用するのか絶対に確認しておきましょう。

プログラムの効率的な読み方

casstteの延澤です。
今回はプログラムの読みかたについて書いていきます。

まず既存のシステムに新規の機能を追加する時に、

「あなたはどのファイルから開きますか?」

この質問について答えていくのが今回のブログの内容になります。

何故読み方が大事なのか

出来るエンジニアは平凡なエンジニアに比べて100倍生産力が違うと言われています。自分は出来るエンジニアは読むのが速いため設計・実装の時間に十分な時間が取れるから生産力が違うという意味で解釈しています。
逆に考えると読む時間が遅いと設計・実装の時間が足りず、考慮漏れなどを起こし二度手間を発生させる確率が高くなることに繋がります。 ともかくエンジニアの作業はコードを書いているイメージが先行しますが実は他人のコードやドキュメントを読んでいる時間がほとんどです。

また、学生時代はプログラミングが得意だった人も就職してみると当初思ったほど最初に仕事が出来ないことがあります。これは圧倒的に他人のコードを読む時間が不足しているのも理由の一つです。
なので当たり前すぎて軽視されがちな読みかたについて書きます。

読むためのコツ

0. サービスのコア機能を確認する

これは作業に当たる前に絶対にやるべき作業です。あなたが今回担当するサービスのコア機能については実際に使ってみることです。ここで言うコア機能とはそれがなくなったらそもそもサービスとして提供出来ない機能のことです。
大体のサービスは幹となるコア機能と補完する機能群であるためコア機能さえつかめれば一気に全体の把握が楽になります。問題はコア機能はロジックが複雑なためコードを理解するのが大変なことです。最悪、直接触らないのであれば概要が分かっていれば大丈夫です。
さらに言うとこのサービスは誰にどのような価値を届けるのかを意識しておくことです。登場人物や価値を理解していると読むスピードが大幅に違ってきます。

1. 現在の動きを確認する

今回改修する箇所の動きを確認しましょう。その際におすすめなのは現在どのようにデータが変わるのかこの時点で理解しておくことです。
また、新規機能追加の場合ではどのような流れで新規機能が使われるのかを意識しておきます。

2. 用語を確認する

プログラムでは特定の機能について特定の単語で表していますのでしっかり意味を確認しておきましょう。特にあなたが新人であるならば積極的に発言して確認することです。
しかし、特定の単語が別の意味で使われていたり、特定の機能が複数の単語で使われていたりするケースは注意が必要です。こういう場合は予めバグが紛れそうだなと考えて注意しておきます。

3. ライブラリのドキュメントを確認する

今どきのサービスでFrameworkやライブラリを一切使っていない現場は少ないでしょう。もしあなたがそのFrameworkやライブラリについて使用するのが初めてであるならばしっかりと公式ドキュメントを読んでおきましょう。勘所としてはこのライブラリが何を解決するのかと哲学も理解しておきましょう。ここを意識していないと間違った使い方をするため技術負債を増やします。

4. コードジャンプ機能を使う

これは賛否が分かれるところですが、コードを追っていくならコードジャンプ機能はあった方が楽です。私はIntelliJ IDEAの有料版を使っています。
その他にもMacであればDashというAPI Document Browserと連携させてさらに効率化させています。

Dash for macOS - API Documentation Browser, Snippet Manager - Kapeli

5. 設計について理解する

レイヤードアーキテクチャ、Clean Architectureなど全体の設計に関わるものから、Design Patternを通したクラス関係については理解しておくと読みやすいです。この辺がキレイに作られているサービスは必要な読む箇所と影響範囲も分かるので理解が早くなります。ただ、現実問題としてここがしっかりとキレイに作られているケースは何だかんだ稀です。。

6. 頭を整理する

コードをずっと読んでいると頭がこんがらがってくることもあります。その結果何度も同じコードを読んでしまいループします。
そこでおすすめなのが途中でメモを書いたり図に起こしてしまうことです。特にオススメなのが図です。下手な図でいいのでコードや仕様の関係性を書いてみると案外スッキリします。私はよくホワイトボードにシーケンス図やベン図を書いて理解しています。

まとめ

上記の中で個人的に一番重要なのは「0. サービスのコア機能を確認する」です。コードの読むのが遅い人はそもそもサービスの理解が深くないケースが多いです。全体像を把握していないのに詳細なソースコードを読んでも中々頭に入ってこないです。
全体像を理解した上でコードが実際にそうなっているのか確認してみると理解しやすいです。そうやって考えるとこの記事の一番上にあった「あなたはどのファイルから開きますか?」という質問に対しては、まずいきなりファイルを開かないが正解になります。
昨今、入社試験などでアルゴリズムの問題を出すことが多いですが、個人的にはプログラムの読解をさせた方が実務の能力を図るのに適していると考えてます。読解させた上で仕様を読み取れるのか、設計が良いのか悪いのか議論した方が試験内容としては面白いと感じます。