UIアーキテクチャの開発


それで、以前、私は私のバックエンドアプリケーションがどのようにアーチテクトであるかについて長さで議論しました.あなたがまだそれを読んでいないならば、私は強くあなたが継続する前にすると提案します.
だからもう一度私のフロントエンドはhexaganoalアーキテクチャに基づいています.私が以前に説明したパターンと非常によく似ています.
我々がフロントエンドについて話すとき、我々は常に構成要素に集中します、そして、これはもちろん重要ですしかし、それはまた、あなたのアプリケーションの非公開の側面を組織化することについて考えるのも重要です.私はよくコンポーネント内のフェッチ要求を行う人々を参照してください.これは、一緒に投げるし、押し出すのが速いかもしれません、しかし、プロジェクトが成長するにつれて、あなたはデータをフェッチしているか、副作用を引き起こしているあなたのコードのどこを見つけるために、絶対的な雑用になります.

全体構成
src
│
└───ui
|
└───application
|   └───feature
|       |   useUsecaseHook.ts
|
└───core
|   |   feature.ts
|
└───infrastructure
|   └───feature
|       |   method.ts
|
└───domain
|   |   feature.ts
最も明白な違いは、API層は明白な理由のためにUI層で置き換えられました.すぐにUI層の内容に戻ります.

アプリケーション
もう1つの違いは、アプリケーション層が実際に今ちょうど反応フックのコレクションであるということです.反応のアプリケーションのいくつかの理由で、これは多くの意味を作る.あなたのusecasesのすべては、フックと州に結びつくつもりです.このアプローチの唯一の問題は、アプリケーションの層が反応するように結合されているので、反応コンテキストの外でusecaseのいずれかにアクセスすることができませんでした.しかし、私はこれは小さなアーキテクチャの価格を便宜のために支払うことを決めた(私はほぼ間違いなく、アプリケーションの層の反応の外側を使用することはありません).

コア/インフラ/ドメイン
彼らは文字通りバックエンドのアプリの同じ領域と同じですので、私はこれらの詳細にはあまり行きません.
TL博士:コアは抽象的なインターフェイスです、インフラストラクチャはそれらのインターフェース(副作用をするものと「外の世界に連絡します」)の実装です、そして、ドメインは純粋なビジネスロジックです.

UI
それでは、UI層で何が起こっている?それは異常なことではないが、実際には原子設計に類似した、かなり一般的なパターンに従う.
ui
└───elements
|   |   ButtonComponent
|
└───modules
|   └───feature
|       |   CompositeComponent
|
└───pages
|   └───feature
|       | FeaturePageComponent
|
└───app
    | AppComponent

元素
要素は、アプリケーションロジックや知識がない小さな自己完結型のコンポーネントです.ボタン、グリッド、入力などのようなもの.
私は多分ここでルールに2つの例外がありますImage 部分を取るコンポーネントsrc と私のアプリケーションの設定に基づいて完全なURLを計算します.とUpload サーバーにファイルをアップロードし、結果のURLを返すように内部的に処理する入力要素.私はこれらのdumberを作成しなければならないとスタックの残りの部分に関連付けられていますか?はい.そうですか.たぶん最終的に👀

モジュール
モジュールはelements それはページの一部を構成します.たとえば、検索ページがある場合は、検索入力領域のモジュール、リスト領域のモジュール、および個々のリスト項目のモジュールがあります.モジュールは他のモジュールから構成することもできる.
モジュールはドメイン知識を持つことができます.
ここで注意する重要な部分は、モジュールがすべて「ダム」であるということです.モジュールはデータを取得したり、データを送信しない、それはクッキーを読むことはありません、それはアプリケーション層を使用しません.何か「スマート」は親ページによってされます.
これを複雑にすると、あるモジュールがあるスマートなものに依存する別のモジュールをレンダリングすることがあります.
function Overview({ item, onAddToBasket, onViewMoreInfo }) {
  return (
    <ProductItem
      item={item}
      onAddToBasket={onAddToBasket}
      onViewMoreInfo={onViewMoreInfo}
    />
  );
}

function ProductItem({ item, onAddToBasket, onViewMoreInfo }) {
  return (
    <div>
      <span>{item.name}</span>
      <ProductActions
        item={item}
        onAddToBasket={onAddToBasket}
        onViewMoreInfo={onViewMoreInfo}
      />
    </div>
  );
}

function ProductActions({ item, onAddToBasket, onViewMoreInfo }) {
  return (
    <div>
      <Button onClick={onAddToBasket}>Add to basket</Button>
      <Button onClick={onViewMoreInfo}>More info</Button>
    </div>
  );
}
我々が提供したいならばonAddToBasket ProductActionコンポーネントへのProp、我々はすべての方法の小道具を渡す必要があります.プロップドリルは反応の開発の欲求不満と退屈な部分です.これは、我々はしばしばスマート/dumbの構造をバイパスし、スマートロジックを内側に貼り付ける理由ですProductActions 代わりに、しかし、これはあなたのスマートな動作がどこから来るのトラックを失うとしてより多くの問題が発生します.
私の解決法は実際に要素を小道具として渡すためです.
function Overview({ item, children }) {
  return (
    <ProductItem item={item}>
      {children}
    </ProductItem>
  );
}

function ProductItem({ item, children }) {
  return (
    <div>
      <span>{item.name}</span>
      {children}
    </div>
  );
}

function ProductActions({ item, onAddToBasket, onViewMoreInfo }) {
  return (
    <div>
      <Button onClick={onAddToBasket}>Add to basket</Button>
      <Button onClick={onViewMoreInfo}>More info</Button>
    </div>
  );
}
スマートレベル(すなわちページ)では、次のようにします.
<Overview item={item}>
  <ProductActions
    item={item}
    onAddToBasket={handleAddToBasket}
    onViewMoreInfo={handleViewMoreInfo}
  />
</Overview>
あなたが複数の構成要素を構成するとき、これはより複雑になります、しかし、私はそれがモジュール層の深さに埋められるProp穴またはスマート構成の山よりよいと思います.

ページ
ページはそれが錫の上で言うものです.そして、それは全部のページまたは見解の構成です.ページは3つの目的を提供します:彼らはまとまった全体に複数のモジュールを入れました;データを取得したり変異したりするためのアプリケーション層との相互作用を扱うそして、アプリケーションのルーティングを調整します.
// A single page, composing the view from multiple modules
function ProductPage() {
  const item = useFetchItem();
  const addToBasket = useAddToBasket();
  const viewMore = useViewMore();

  return (
    <Overview item={item}>
      <ProductActions
        item={item}
        onAddToBasket={addToBasket}
        onViewMoreInfo={viewMore}
      />
    </Overview>
  );
}

// A Page that stitches together other pages with routing
function ProductPages() {
  return (
    <Route path="/product/:id">
      <ProductPage/>
    </Route>
  );
}
そこにある.バックエンドのように-六角形のアーキテクチャ、懸念の分離、依存性の注入は、コードベースの基礎を形成する.完璧?いいえ、維持し、従うのは簡単ですか?そう思う.みんなのためですか.たぶんない!