VIDEO BRAINのRedux設計

はじめまして、10月にフロントエンドエンジニアとして入社した松井と申します。 最近通勤時間にAmazon Audibleで読書ならぬ聴書をする様になりインプット量が大幅に増えました。歩きながらでも本が読める(聞ける)のでお勧めです。

さて弊社の事業の一つにVIDEO BRAINというAI自動動画編集クラウドがあります。

video-b.com

フロントエンドはReact+ReduxのSPAで開発されており、私はOPEN8入社前はNuxt.jsを使っていて、Reactはこれが初でした。Nuxt.jsと共通点も多いですが、異なる点も多く、特にディレクトリ構成がいまいち理解できていませんでした。

f:id:open8tech:20191221130754j:plain

しかし、先日フォント一括変更機能を実装した時に、主要となるディレクトリのComponent, Container, Moduleのファイルをゼロから作成、連携させたおかげでその理解が一気に深まりました。

今回はその振り返りも兼ねて記事にまとめようと思います。

はじめに

一般的にReduxを用いたアプリケーションのディレクトリ構成には、Redux-Way Ducks Re-ducksの3種類がありますので、まずはそれぞれを簡単に解説したいと思います。

1.Redux-way

Reduxの登場人物(Components, Containers, Actions, Reducers, Types)ごとにディレクトリを分け、その中ではComponentごとにファイルを分類するパターン。

src/
  ├ components/
  |    └ componentName.js
  ├ containers/
  |    └ componentName.js
  ├ actions/
  |    └ componentName.js
  ├ reducers/
  |    └ componentName.js
  └ types/
       └ componentName.js

このパターンの欠点はStateを書き換える為に必要なActionType、Actions、Reducerが分散されていて、それぞれを呼ぶ為にimportしないといけなかったので、閲覧性が悪く管理がしにくいという点です。

その悩みを解決する為に生まれたのがDucksパターン。

2.Ducks

ActionType、Actions、Reducerは密結合してるもの同士なので、1つのファイルで構成し、Moduleとして定義するパターン。

これにより簡潔で見通しが良くなります。Erik Rasmussen氏が考案しました。

f:id:open8tech:20191221131806j:plain

小規模開発においてはDucksパターンのシンプルなディレクトリ構成がマッチすると思われますが、中・大規模開発の場合ActionType、Actions、Reducerを1つのファイルにまとめると、ファイルが肥大していき、閲覧性が悪くなってメンテナンスもしにくくなります。そこで生まれたのがRe-ducksパターン。

3.Re-ducks

DucksパターンにおけるActionType、Actions、Reducerを1つのファイルにまとめるのではなく、Component単位の1つのフォルダにまとめるというパターン。 Alex Moldovan氏がDucksの拡張版として考案しました。

src/
  ├ components/
  |    └ componentName.js
  ├ containers/
  |    └ componentName.js
  └ duck/
       └ componentName/
            ├ index.js
            ├ recucers.js
            ├ actions.js
            ├ types.js
            ├ tests.js
            ├ operations.js
            └ selectors.js

VIDEO BRAINで採用しているディレクトリ構成

さて、肝心のVIDEO BRAINではどのパターンを採用してるかと言いますと、DucksとRe-ducksそれぞれのいい部分を組み合わせています。

  • ActionType、Actions、Reducerを1つのファイルにまとめModuleとして定義するDucksパターン
  • Component単位の1フォルダにまとめ、Operationsというディレクトリ内にAPI通信の処理を切り出すRe-ducksパターン
src/
  ├ components/
  |    └ componentName/
  |         └ index.js
  ├ containers/
  |    └ componentNameContainer/
  |         └ index.js
  └ modules/
       └ componentName/
            ├ index.js
            └ operations/
               └ index.js

このディレクトリ構成のおかげで、処理は分散され過ぎず、まとまり過ぎず良いバランスを維持できていると思いました。

今回、新機能実装の際に、一番最初にした作業は、このディレクトリ構成の理解で、それから詳細な実装プランを立てコードを書いていきました。

その処理の流れを図にまとめるとこんな感じです。(*APIリクエストを含めるパターンです。)

f:id:open8tech:20191224110717p:plain

たかだかディレクトリ構成と思いますが、Re-ducks考案者のAlex Moldovan氏は自身の記事でその重要性を語っています。

Someone once said that naming things is one of the hardest jobs in computer science. I couldn’t agree more. But structuring folders and organizing files is a close second.

訳)命名規則がコンピューターサイエンスで最も大変な仕事の一つだと昔誰かが言っていました。 全くもって賛成ですが、ディレクトリの構成やファイルの整理もそれに匹敵すると思います。

引用元:Scaling your Redux App with ducks Alex Moldovan

中・大規模開発では膨大な量のディレクトリとファイルが存在していて、それをどう構成するかが管理、拡張のしやすさを向上する為に重要だし、その構成の意図を理解する事はコードを書く事と同じくらい重要だと思います。

アプリケーションは最初にリリースした時から日々拡張をしていくものです。それを容易に安全にできるようなディレクトリ構成で設計する事の重要性をAlex Moldovan氏も繰り返し語っていました。

なぜDuck(アヒル)なのか??

最後に余談ですが、なぜDuck(アヒル)と呼ぶのか?と疑問に思われた方も多いと思います。 あくまでも個人的な見解ですが、英語でget one’s ducks in a row(整理する、準備を整える)という表現があります。 アヒルの子供達は親の後ろを綺麗に一列になってついていく習性が語源なのですが、これが由来かなと思います。

f:id:open8tech:20191221131844j:plain

React+Reduxの膨大なファイル群をアヒルの子供達の様に一列に並べて整理するというコンセプトで、更にReduxのduxともかけて命名したのかもしれませんね。

おわりに

これからもどんどん新しい機能を実装していきVIDEO BRAINがお客様に喜んで頂けるプロダクトへ成長させていく一端を担う者として頑張っていきたいと思います。

また今後更にReactとReduxに触れていく中で、得られた知見を共有させて頂けたらと思います。