Sanma Salted

半人前エンジニアによるチラシの裏

スピードとスピード感

今日は普段仕事をする上で意識していることを一つ書こうと思います。

日々仕事をしていると「スピード感を持って進めていく」「ベンチャーならではのスピード感があります」などの言葉をよく目にします。

私はこの「スピード感」という言葉をあまり使わないようにしています。

スピード感はあくまで体感で感じるものであり、実態としての「スピード」とは違うものであると考えているからです。

そして我々が追求するべきものはアウトプットとしての「スピード」であり、「スピード感」それ自体はあまり意味のないものです。

しかし多くの場面においてこの「スピード」と「スピード感」は混同されており、 結果として「スピード感はあるけどスピードはない」という状況に陥ってしまいがちです。

この「スピード感」の罠にハマらないようにどうすればいいのか、自分の思考の整理を込めてまとめていこうと思います。

スピードとスピード感の違い

冒頭に書いたように、私は「スピード」と「スピード感」を明確に区別しています。

「スピード」については改めて説明する必要がないと思いますが、日本語にすると「速度」です。 何かをする上での実体として客観的に計測可能な時間、という事もできるかもしれません。

一方「スピード感」とはなんでしょうか。 身も蓋もない乱暴な言い方をしてしまえば、「なんか忙しくやってる感」のようなものだと言えるでしょう。

ここで重要なことは、体感として感じる「スピード感」は結果としての「スピード」とは必ずしも一致しない、という点です。 これがこの記事の大前提です。

スピード感はあるけどスピードがないとはどういうことか

では「スピード感」と「スピード」が一致しないとはどういう状況でしょうか。

例えばあなたがプログラマで、何か新しいサービスを開発しているとしましょう。

「xxな人に向けた新サービスを作る!リリースは6ヶ月後!タイトなスケジュールだけどみんなで乗りきろう!」

そんな経営者の掛け声のもと、みんなと一緒に毎日深夜まで残業、土日も仕事をしてなんとかスケジュール通りにシステムを完成させます。

さあ後は発売を待つだけだ、と思った矢先にこんなことを言われます。

「これさ、xxさんに実際に見せてみたんだけど、メインだと思ってたあの機能まったく必要ないって。あと○○が出来ないと使い物にならないらしいから作り直して、めんごめんご」

なんということでしょう。求められたものを必死に作りきったと思ったら、それは顧客に求められたものではなかったのです。

しかしベンチャースピリット溢れるあなたはこんなことではめげません。 3ヶ月の開発期間延長という方針のもと、あなたは圧倒的な速度で不要な物を削り、足りなかった機能を実装します。

さあ今度こそ、と思ったら次はこうきました 「あ、そういえば決済のこと忘れてたわ。コンプラの関係で社外のシステムと連携する必要があるらしいから、自前で作った決済機能消して連携機能入れてね」

またこれか、そう、またこれなんです。 しかしあなたは負けません。複雑な決済機能をわずか1ヶ月で作り上げ、無事にリリースすることができました。

この10ヶ月、あなたは見事に常に全力疾走で走り抜けました。経営者からは 「圧倒的なスピート感を持って成し遂げてくれた。君は我が社のスターだ!!」 と褒めちぎられます。会社としてもプロジェクトは大成功だったと祝賀ムード一色です。

これは色々なところでよくみられる光景ではないでしょうか。

しかしここで一旦立ち止まって考えてほしいのです。 本当にこのプロジェクト、10ヶ月必要でしたか?

振り返って見てください。 まず第一に、想定している顧客がいるにもかかわらず、その顧客が必要としている機能を作らず、逆に必要のない機能を作っています。 その次に決済システムも同様です。法的な理由で外部と連携する必要があることに気がつかず、最初に自前で独自のものを作り込んでしまっています。

これが最初から顧客に適切な調査を行っていたらどうだったでしょうか? 決済に関する法的リスクを開発前に検証していたらどうだったでしょうか?

もちろん全てを事前に予期することはできないにせよ、多くの無駄な作業を防ぐことはできたはずです。 そうすればもしかしたら当初の予定通り6ヶ月できちんと開発を終えられていたかもしれません。

つまりこの例では「10ヶ月間スピード感を持って怒涛の勢いで仕事をしたが、結果として6ヶ月分のアウトプットしか出せなかった」ということができます。

これが「スピード感」の罠です。

スピード感を持って全力で走り抜けた本人は当然達成感に満ち溢れますし、その様子を見ていた周囲もその成果を疑うことはしません。 しかし、実際には遠回りを重ねた結果、本来できたはずの期間より遥かに遅いアウトプットになってしまっているのです。

この罠の怖いところは、当事者たちは自分たちは圧倒的な速度で仕事を成し遂げたと思い込んでしまうことです。

上記の例はちょっと極端かもしれませんが、よくよく振り返るとこういうことはあらゆる場面で日常的に起こり得るのです。

スピードを持って走るためには

では「スピード感はあるけどスピードはない」を防ぐためにどうすればいいのでしょうか?

これはとてもシンプルなことで、私は「走り始める前に一旦立ち止まる」ことに尽きる、と考えています。

とにかく早く早くと思うと、まずは走り始めることが大切だと思ってしまいがちですが、それは間違いです。

闇雲に走り始めたとしても、走り始めた方向が間違っていたらむしろ目的地とは遠ざかってしまうからです。

見知らぬ土地で目的地に急がなければいけないと考えてください。

大体の方向だけでいきなり全力疾走をするのが本当に最善策でしょうか?

一旦スマホを取り出してgoogleマップを開いて最短ルートを調べた方が、結果として早く到着できるのではないでしょうか?

方向の定まらない、あるいは方向を間違えた全力疾走はただの暴走です。 全力で走れば走るほど目的地から離れていってしまうのです。

昔の偉い人も「急がば回れ」と言っていますね。

繰り返しになりますが、私たちが大切にしなくてはいけないのは「スピード」です。「スピード感」ではありません。

本当にスピードを持ってアウトプットを生み出すためには、一見止まっているように見える時間も大切なのです。

自分一人のことならまだしも、チームを預かるリーダーであるなら尚のことそうだと思います。 自分自身、リーダーのようなことをやらせてもらうようになってからこのことを強く意識するようになりました。

もちろんまだまだ自分が完璧にできているとは思いませんが、「スピード感」で満足しないように気を付けたいと思います。

ちなみに「そもそもスピードより大切なものがある」というのは当然そういう状況もあると思いますので、 あくまでスピードが求められる場面で自己満足に陥らないようにという趣旨の記事だとご理解いただければ。

ReactのHooksでコンポーネントとReduxの橋渡しをするようにした

こんばんは。今日はReactについて書いていきます。

今担当しているブロダクトではフロントエンドをTypescript + React + Reduxで開発しています。 新規の開発だったので、コンポーネントに関してはReact公式が推奨するようにClass ComponentではなくFunctional Component + hooks で統一しています。

その中でCustom Hooksを使ってみたら個人的にとてもスッキリしたので、何が良かったかについて書いていきます

hooks / custom hooksとは何か

そもそもhooksとは何かを書こうかと思いましたが、今さら私が書くまでもなく良質な解説記事がたくさんあるのでそちらを参照していただければ。 公式を見てもらうのが一番早くてわかりやすいかなと思います。

reactjs.org

hooksを使ってコンポーネントはhooksにのみ依存、reduxへの直接の依存を避けるようにした

この記事のメインの内容になりますが 今回、コンポーネントからReduxへの直接の依存を排してコンポーネントは独自に定義したCustom Hooksにのみ依存させるという方法を試してみました。

実装のイメージとしては以下のような感じです。

export function useUserList(): User[] | null {
    // useSelectorなどreduxからデータを取得する
}

export function UserList() {
    const users = useUserList();
    
    return (
        // render....
    );
}

従来であれば下記のように、コンポーネント内で直接reduxのstateにアクセスしていたと思います。

export function UserList() {
    const users = useSelector((state) => state.user.list);
    
    return (
        // render....
    );
}

コンポーネントが直接reduxを触ることの問題点

上記の例だけだとあまり記述量が変わらないように見えます。 が、実際には多くのケースでuseEffectuseDispatchを用いてreduxのアクションを呼び出す処理が入るなどし、 コンポーネントがreduxに密に直接依存してしまっていました。

この状態の何が好ましくないかというと

という点が挙げられます。

まずは"コンポーネントの責務が大きくなりすぎる"という点です。 そもそもコンポーネントはあくまでViewであり、アプリケーションが持っている何かしらの「状態」とユーザーとの間のインターフェイスであることがその責務のはずです。 言い換えるなら、「状態」に見た目を与えてユーザーに見せ、またユーザーによる「状態」を変えるための操作を受け付けるのがその役割です。

上記の例のようにコンポーネントが直接reduxを触ってしまうと、それに加えて「アプリケーション内の状態を操作し、その変更を受け取る」という責務を併せ持つことになってしまいます。

これ自体は(単一責任原則に反していることに目をつぶれば)大きな問題ではないのかもしれませんが、次の"「状態」の「実装の詳細」に依存してしまっている"という点が加わると話が変わります。

上記の例で言えば、本来コンポーネントUser[]が欲しいだけであり、それがどこにどのように格納されているのか、あるいはどのような手段で取得されるのかは関心外であるはずです。

しかしコンポーネントが直接reduxを呼び出す場合、それがreduxのストアの特定の構造の中に配置されており、reduxのactionを通して取得されることを知らなくてはいけません。

これはすなわち、本来コンポーネントUser[]を取得できる何か(抽象)だけに依存すればいいはずなのに、そのための手段(実装の詳細)に依存してしまうことを意味します。

こうなると何が問題になるかといえば、変更に対して弱くなってしまうことです。

例えばストアの構造が変わる場合や、あるいはreduxそのものを廃したいこともあるかもしれません、そうなった際に変更の影響範囲はとても広くなってしまいますし、 そうすると変更のコストはどんどんと膨れていってしまいます。

reduxへのアクセスをhookに切り出す

そこでこれらの状態管理に関する責務をhookとして完全に切り出してしまうことで、上記のような問題を回避することができます。

コンポーネントUser[]を渡してくれるhooksにのみ依存していれば、そのための実装はhookの中だけに閉じ込めておけます。 そうなるとストアの実態がreduxであることを知っているのはhookのみになり、ストアに関する変更はhookのみに影響することになります。

また、コードの上でも状態管理のための長々とした記述をhookを呼び出すために1行に収めることができ、全体の可読性も向上します。

それとこれは余談になりますが、上記のようにコンポーネントとreduxの間にhookを挟むことでコンポーネントユニットテストもとても書きやすくなります。 redux周りのことを全て忘れてhookをモックで差し替えるだけで良くなるので。

まとめ

上記のようにコンポーネントとhookで明確に責務を分けることで、見通しが良くメンテナンス性の高いコードを書くことができました。 このやり方がベストかどうかはわかりませんが、hooksはこれまでコンポーネントが全て持ってしまっていた複数の関心をうまく分離するために非常に有用なツールであるといえそうです。

他にも有用な活用方法がないか、引き続き研究してみたいと思います。

このブログについて

はじめまして。fisherman08と申します。

職業はWEBアプリケーションエンジニアで、最近はサーバーサイドはKotlin、フロントはTypescript + Reactなどを主に使っています。

色々と新しいことを覚えるのは好きなタイプなのですが、筆不精で一向にアウトプットが増えないのでブログを始めてみることにしました。 始めてみるといいつつ実はこのブログを動かすのは3回目で、過去2回は三日坊主で終わったという経緯があります。。。 (ちなみに当時書いたいくつかの記事は一旦消しました)

なので今回は長く続けるために、プログラミングに限らず思ったことや趣味のことを思うままに書いて行こうかと思っています。 じつはQiitaもごく稀に書いていたりします。 fisherman08 - Qiita

Qiitaとの使い分けは悩んでおりますが、ちょっとしたtips的な記事はQiita、考察やポエムはこのブログ、という使い分けで行こうかと思います。

とある方に「ブログは誰かのためにやると続かない、自分のためと割り切れば意外と続く」といわれたので、 そのスタンスで行ってみたいと思います。