「スタートアップだからテストを書かない」は正しいか

スタートアップのCTOクラスの人がたまにそういうことを言っているのを聞くことがあります。もしくは「スピード優先だからテストを書かない」等です。

それは真ではなく、言ってしまえば、未熟だからテストを書「け」ない、のではないでしょうか。ただ、スタートアップという言葉に未熟であるという意味が含まれているのであれば「スタートアップだからテストを書かない」という問は真になるかも知れません。スタートアップは得てして未熟なものだし、それでも良いからです。

テストを書かないというジャッジをするのは構いません。でもそれは、スタートアップだからでもスピード優先だからでもない。自分達が未熟だからで、そこには向き合うべきだと考えます。状況のせいにするのではなく、徹底的に自分ごと化する。それがスタートアップに求められる姿勢です。少なくとも技術のトップが自分たちの技術力に向き合わないのはまずいでしょう。

「スタートアップだから」という発言はよく聞かれますし、私も使ってしまうことはありますが、基本的にはダサい物言いだと言えます。

テストコードは書いたほうが速い

実は、テストコードが書けるスキルがある場合、ある程度のサイズのサービスを作る上ではテストを書いたほうが開発速度は速くなります。

また、うまくテストコードが書ければ変化にも強くなります。サービスは複雑になる宿命があり、ある変更がどこに影響が及ぶかは完全に把握しきれるものではありません。そんなときにテストコードはあなたの身を守ってくれるのです。バグによってサービスが停止してしまうリスクを減らし、安心して素早く機能追加や機能の変更をおこなえるのです。サービスは作って終わりでありません。素早く進化させていくためにもテストコードは必要なのです。

本番に出してからバグに気づいてあたふたするよりも、テストコードで気づいたほうが早く、顧客へのダメージも少なくなります。動作確認のためにテストコードを書いてみましょう。動作確認の為に手元で動かすようなことをしている場合、それをテストコードにしてしまえばいいのです。よく言われる格言に「時間がないからテストコードが書けないのではない。テストコードを書かないから時間がなくなるのだ」というものがあります。

変化に強いことの重要性

現代においてサービスは変更させ続ける必要があります。何故ならば世界も以前にもまして高速に変化し続けているからです。世界の変化に合わせてサービスを変化させつづけないと生き残れません。一番わかり易い例としてはサービス規模で、1000人の顧客に最適なシステムと、100万人に最適なシステムは大きく異なります。また、料金計算が関わるようなシステムで、消費税率の変更に追随できなかったらサービスを終了せざるを得ません。もちろん顧客のニーズも刻一刻と変わります。

そして、意外に思うかも知れませんが、サービスの変更頻度が多いほど、逆にシステムは安定することが明らかになっています。現代において、数多くのメジャーサービスは見た目はさほど変わらないかも知れませんが、裏側では一日に何度もシステムを変更(Deploy)しています。「動いているシステムは触るな」は過去の言葉になりました。

自転車のメタファー

テストコードを書けるかどうかは自転車に乗れるかどうかに似ています。覚えていないかも知れませんが、皆さんは自転車に乗れるようになるまで苦労をしたはずです。しかし、一度自転車に乗れるようになってからは、足で走るよりもずっと速い速度で移動できるようになりました。そして、一度身につけてしまえば、全然難しいものではなくなります。

テストを書かないほうが速いように思えてしまうのは、それは自転車に乗れない人が自転車に乗ったときの景色を知らず、そこに想像が及んでいないようなものだと言えます。

もちろん、テストコードは銀の弾丸ではなく、バグを完全になくせる手法ではありません。コードの品質を上げる手段であって、QAなどを完全に無くせるものではない、ということは留意する必要があります。

テストを書けないとコードを書いてはいけないのか

さて、ここまで書いてきたことは、散々色々なところで既に聞いたり目にしてきたことでしょう。聞き飽きたお説教にも感じているかも知れません。

では、テストコードが書けないと、サービスを作ってはいけないのでしょうか。

もちろんそんなことはありません。次のゴールが近くにあるときに、自転車を乗れるようになるまで練習するよりも、今走っていったほうが速いではないか、というのは間違いなく正しい。

良く見かける漫画ベルセルクの主人公ガッツの「何十年も修行して達人になるのを待ってから戦場に出るつもりか?」「だったら、今手持ちのコマでやりくりするしかねェだろ」というセリフは圧倒的に正しいのです。

ソフトウェア開発は初期投資が少なく始められ、多くの人に開かれているという良い特徴があります。どんな業界であれ、参入障壁が高く前提のコンテキストを多く要求する分野は新しい血が入りにくくなり、先細ります。ソフトウェア開発は今後も多くの人に開かれているべきで、参入障壁を高くすべきではありません。

だから「テストコードが書けないとサービスを作るべきではない」というような意見があっても無視して作り出してしまいましょう。結局走り出したやつが偉いのです。そして、有力な事業のアイデアがあってコードも完璧に書ける、そんな人はいません(たまにいます)。できる範囲で進めていくしか無いのです。だから、私のこんなエントリーも「知ったことか」と一蹴してくれてかまいません。未熟なコードでも勝てることがある。そこに痛快さがあるのです。

ただし、己の未熟さを認め、手持ちのコマを増やす努力をしたほうが成功率は上がるはずです。テストコードもその一つです。

テストを書かなくても良いとき

テストを書かなくてもいいときもあります。書き捨てやプロトタイプなど捨てる前提で作る場合や、テストを書かなくてもいいほど単純なものである場合です。単純なものとは、捨ててすぐに作り直せるくらいのもの、とも言えます。そういう意味でDisposableである、ということが一つの指標となるでしょう。

しかし、捨てるつもりだったものが捨てられず、単純なつもりだったものが複雑化してしまうことは、残念なほどによく起こります。テストを書かなくて良いかどうかを見極めるためには、実はテストを書けるのと同じくらいのスキルが必要かも知れません。

テスト書きすぎ問題

逆にテスト書きすぎ問題、というのもあります。教条主義に陥ってしまったり、テストを書くことが目的化しすぎて過剰になっている、そういうことも起き得ます。

ただ、テストを書くのが好きなエンジニア、というのはいます。テストコードについて考えるのが好きで、テストコードを書くのが目的になっているくらいの人です。テストコードについてのプラクティスを周りに教えてくれたりもします。

そういう人は貴重な存在で大事にすべきです。時にはやりすぎに感じるかも知れませんが、彼らの自主性に任せ、良い結果を期待すると良いでしょう。

とは言え、変化の足かせになるようなテストを書いてしまっているのであれば明らかにやりすぎです。よく言われることですが、例えば、UIのボタンの位置を少し動かしただけで、大量のテストがコケて修正に時間がかかる、プライベートメソッドのテストがリファクタリングの妨げになる、と言った状況は嬉しくないでしょう。

また、エンジニアが「身を守る」ためにガチガチにテストコードを書いてしまうケースもあります。その結果、ちょっとした変更でもリードタイムが嵩んで、変化を阻害する状況が発生します。これは理不尽で唐突な仕様変更を立て続けに行なっていないか、その結果、本番でエンバグした場合に、エンジニアだけを責めていないか、など、コミュニケーションを見直す必要があるでしょう。

結局、テストコードを書くことがペイするか、サービスのためになっているか、という観点を忘れてはいけません。ただ、この辺りは、テストを書けるようになってから心配すればいい話です。テストコードが過剰であるよりも不足を恐れたほうが良いということです。

あるサービスの初期コードはひどかったし、テストコードなんて無かったと聞いたけど

あのスタートアップの創業期のコードはひどかった、当然テストコードなんて当然無かった、という話は多く聞かれます。半ば神話や武勇伝のようになっているものもあります。昔のFacebookに関するエピソードが書かれた、Evan Priestley氏のエントリーなど私は大好きです。社内のWikiに「関数は使うな。遅い」と書かれていた、という下りは最高です。

There was a "PHP Best Practices" wiki which basically said "don't use functions, they're slow" (the intent here was good, but the message was not clear).

しかし、だから自分たちもテストコードを書かなくて良い、という話ではありません。

多くのスタートアップは創業期に凄腕のエンジニアを雇えるわけではありません。むしろアイデアを考えだした人と、その周辺にいた人で作り始めることが多いでしょう。その上で、彼らなりに良いコードを書こうと努力したけど結果として拙いコードになってしまった、ということでしょう。意図して質を落とそうとしたわけでは決して無いはずです。

技術の進化と業界の当たり前水準の向上

それに、時代は変わり、Web開発関連の技術や業界も進化しました。ノウハウも共有されて良い意味で枯れてきました。それこそ大昔はソースコード管理すらおぼつかない会社が多かったのですが、今やどこも当たり前のようにGitHubを使っています。

テストコードも格段に書きやすくなりました。近年の新しい言語、フレームワークやライブラリは標準でテストが書きやすいように設計され、そのためのユーティリティも整備されています。また、CI/CDサービスがSaaSで誰でもすぐに使いやすい形で提供されているなんて10年前には考えられなかったことです。モニタリングも同様です。

CI/CDを整えることはリリースの安定性とサイクルの高速化に繋がります。また、リリース後のサービスの健全性を測るためにモニタリングも欠かせません。最近よく聞かれるようになったオブザーバビリティは自分たちの本番システムに対する特有の継続的テスト項目とも言えるでしょう。

それらを整備してトライアンドエラーの速度を上げ、改善サイクルを回していくことが昔に比べて劇的にやりやすくなりました。その分、その水準が当たり前となり、現代のサービス運営では当然のように求められるようになっています。

コードやサービスの品質や健全性に投資しないで、サービスが成功する確率は昔に比べて低くなっていると言えるでしょう。

サービスを立ち上げられる特殊能力

しかし、上記のFacebookは、上記のエピソードの2007年時点で既に十分に成功していたSNSだったはずですが、それでもなおひどいコードだらけだったというのは、すごく良い話だと思います。ひどいコードだったかも知れないが、それでもちゃんと立ち上がった。もちろん、昔の話で牧歌的な時代だったというのもあるとは思います。

やはり0→1のコードを書くのが得意なエンジニアというのはいます。そういうエンジニアが書くコードには質の違いがあります。迷わずコードを書き進めた、一筆書きのような勢いを感じられます。そういう勢いは立ち上げ段階では本当に大切です。私にはそういうコードは書けませんが、それもあって、そういうコードを読み解くのは好物だったりします。

そういう質の違いもあって、0→1のエンジニアが書くコードはメンテナンス性が乏しい、などと言われることがあります。実際そういったコードを書く人もいるのでしょう。しかし、私は運良くそういったコードに余り苦しめられたと感じたことはありません。本当にレベルの高い、業界を代表するエンジニアのコードを業務で読ませてもらえたからでしょう。例えば、Natureの初代CTOのmashさん、二代目CTOのtypesterさん、はてなCTOのmotemenさんなどです。

もちろん、彼等の書いたコードには、自分の流儀とは違う最初は読み解けないコードもありましたが、それらを読み解けるようになったことは自分の糧にもなりました。また、そういった立ち上げに成功したコードを引き継いで、整備し拡大する1→10くらいのフェーズが私の得意分野となりました。つまりキャリアにも結びついているので感謝しています。

mashさんは「あまりテストを書きたくない」とは言うものの、必要最低限のテストは書いてましたし、むしろそこを最低限にとどめる勘所に優れていると感じます。また、テストを楽に書くための仕組みを作ってモジュール化するところなどは、いかにもハッカーらしい振る舞いと言えます。

本当にひどい初期コードを引き継いで苦しめられた人というのはいるのでしょう。その苦しみに共感できる経験をしてこなかったわけではありますが、私としては何にせよ自分が得意ではない0→1の仕事をした人をリスペクトしたいと思っています。

そういう特性のある人は常識を打ち破る力を持っています。先程私はテストコードを書くことは自転車に乗るようなものだ、と書きました。つまり、自転車に乗れなくても、マラソンランナーより速く走り、自転車以上の速度を出せれば問題ないのです。djbを見よ。ソフトウェアはそれくらい「てこ」を効かせられるものですし、そういう常識を打ち破る新しい異能をこれからも見てみたいとも思います。

とは言え常人に真似できるものではないので、多くの場合は普通に地道にやるのが良いでしょう。

コードを減らすこととノーコード

ここまで読んできて、コードを増やすとテストを書いたりメンテナンスしたりしないといけないのだからコードは少ないに越したことはない、ということに気づいたかも知れません。それは真理です。同じ価値を同じコストで提供できるのであればコードは少ない方が良いのです。

だからこそ近年は自分たちのコアとなる部分のコード以外はクラウドやSaaSを活用することが当たり前になってきました。

ペーパープロトタイピングなどもそうですが、コードを書かないでトライアルアンドエラーを回せるのであればそれに越したことはありませんし、その方法を模索するのは良いプラクティスです。

そしてノーコード、ローコードがやってきました。人間は欲深い生き物なので、コードを書かないでサービスを作りたいと考えるのは自然なことです。プログラミング言語やさらにはテストコードみたいなめんどくさいスキルを事前に身につける必要がなく、前提知識少なく始められる点で、これらのツールは間違いなく優れています。

VisiCalcを起源とする表計算ソフトが最も優れたノーコードツールである、という状況が40年続いています。流石にそろそろ次のフェーズに移りたいところですし、その流れがきています。人間は欲深い生き物ですし、そして、願ったことは大体成し遂げてきました。

しかし、ノーコードもまた銀の弾丸ではありません。ノーコードツールを現状積極的に使っているわけではないので想像になりますが、ノーコード活用においてもイテレーションの回し方が重要になるでしょう。結局ノーコードであれローコードであれ、変化に強い必要があり、システム開発と同様の難しさを抱えることになります。

つまり、システムを世界の変化に合わせて進化させていきつつも、既存の顧客の体験を損ねるようなバグを生まないようにする安定させる必要があるのです。

そのためのアプローチとしてQAの重要性が増すでしょう。QAの高速化や自動化が以前にも増して求められるようになるのではないでしょうか。

また、ノーコード・ローコードで作ったシステムがある程度複雑化してきたら、設定(コード)を吐き出して、その後はコード管理するアプローチも考えられるでしょう。最初はノーコードツールのGUIで素早くサービスを立ち上げて、しばらくしたらコード化するというわけです。

ちなみにノーコードがもっと成熟して普及したとしても、コードを書く仕事は減らないでしょう。世界はまだまだソフトウェア化される必要がありますし、人間が思いつく雑多でノイズまみれのアイデアを完全にコード無しで解決できるようになるのはまだまだ先になるはずです。

コードの力が世界にはまだ必要です。

質とスピード

かなり脱線しましたが、テストコードの話でした。上のFacebookのエントリ内でも書かれてますし、twadaさんのそのものズバリの「質とスピード」という発表も有名になりましたが、結局、質とスピードは両立してしまうことが知られるようになりました。

チームのレベルに質とスピードが依存する。短期的には質とスピードでトレードオフにはなるが、そこは余あまり調整が効かないし、そこで無理に調整しようとすると、質を落とし続けるスパイラルにはまってしまう。結局、地道にチームのレベルを上げていくことが大事だということです。

手持ちの札で最善を尽くしつつも、持ち札を増やす努力も怠らないようにしたいものです。なまくらで戦って勝てるならそれに越したこともないですが、木こりの寓話の通り、ちゃんとノコギリを研ぐ時間を作った方が良いでしょう。もちろん必要以上にピカピカに研ぐ必要は無いとも思いますが。

しかし、このエントリー結構時間を使って書いたのですが、改めてtwadaさんのスライドを見ると「全部書いてあるな…」という気持ちになっています。

ここまでお読み頂きありがとうございました。

採用情報

ということで、私の所属しているNature株式会社ではエンジニアを募集しています。

バックエンドに関してはテストコードはそれなりに書かれていると思いますが、今後はコードの肥大や、チームの人数が増えてきた場合のコード分割等が課題になりそうです。

また、組込み開発のテストを充実させる活動も社内ではしています。

興味があれば、採用応募してくださると嬉しいです。まずはカジュアルに話を聞いてみたいということであれば、Twitter @songmu まで気軽にDMしてください。お待ちしています!

https://nature.global/careers/