Code Monkey home page Code Monkey logo

frontend-clean-architecture's Issues

Isn't it redundant to store data in the domain and in the storage at the same time?

Why not transfer the data storage/retrieval functionality to the storage? The functionality for checking referral data integrity could also be taken out there.

This question applies in particular to state managers - is it worth duplicating their functionality in domain? After all, state managers are very closely related to the domain and therefore must be aware of referral integrity and other constraints in the data schema.

Is the domain level independent of the UI layer?

First of all, thanks for the interesting example, Alex.

But... I'd like to ask one question.

I've seen many attempts to implement clean architecture when working on web interfaces, but actually, I face the same problem every time.

The specific of the web development is that we want to update UI pointwise, instead of re-rendering the whole page. And usually, we use tools that allow us to do it effectively. I mean React, Redux, and MobX are the tools that allow us to do local UI updates, right? But we pay for that by using the API provided by these tools.

Let me clarify what I mean on the example of your application.

Why do you create a new cart object with a new product array here instead of mutating this? It's because React forces you to do this, isn't it? If you don't create a new copy, React will not re-render your Cart component. But it means that the logic inside the domain layer depends on the UI layer. If you decide to replace React with VueJS, or for example if you decide just to add MobX to your React application, approaches in the domain namespace will not work anymore or at least, they will not work effectively.

That's why from my point of view, clean architecture actually is not as perfect for the front-end apps as on paper.

What do you think about this?

Improve UI

Hey pal. Great work done, I really love your code structure. I just want to contribute by improving the UI

Nextjs version

It will be awesome if we have frontend-clean-architecture for Next.js what do you think 😆

Does the application layer depend on the adapter layer?

import { useAuth } from "../services/authAdapter";
import { useUserStorage } from "../services/storageAdapter";

The above application layer authenticate code depends on the adapter layer's authAdatper and storageAdapter.

I noticed that you mentioned this place in your blog post:

In a canonical implementation, the use case function would be located outside the hook, and the services would be passed to the use case via the last argument or via a DI:

type Dependencies = {
  notifier?: NotificationService;
  payment?: PaymentService;
  orderStorage?: OrderStorageService;
};

async function orderProducts(
  user: User,
  cart: Cart,
  dependencies: Dependencies = defaultDependencies,
) {
  const { notifier, payment, orderStorage } = dependencies;
  // ...
}

The hook would then become an adapter:

function useOrderProducts() {
  const notifier = useNotifier();
  const payment = usePayment();
  const orderStorage = useOrdersStorage();

  return (user: User, cart: Cart) =>
    orderProducts(user, cart, {
      notifier,
      payment,
      orderStorage,
  });
}

If I understand correctly, the second piece of code will be placed in a file somewhere in the services or adapters folder, which if that is the case does meet the requirement that the application layer does not depend on the adapter layer.

The problem is that almost all use cases will have dependencies, which leads to the fact that all use cases under application will have an adapter in the adapter layer just to inject dependencies for that use case.

Question about dependencies between domains and external libraries.

First of all, I wanted to thank you for the high-quality content; I have been learning a lot from you.

It's just a question of how I could improve, if necessary, on domain layer dependencies. In the case of creating an order, I have the part where I want to use some external library for the creation date or something similar, in this case, could I pass it as a parameter and have the use case provide me with this information? How could I do it?

And the other question is regarding dependencies between domains. In this case, could I also receive them as parameters, and the use case would give me this information?

image

Observation: I am Brazilian, and I used Google Translate for translation. I apologize if it is not clear.

Scaling this to the practical level - replacing store with big external state management library.

Hello, I see that implementation of storage is realized in useContext. Which is fine, that is just an implementation and nothing more.

But I am concerned that bringing some big external library like redux-toolkit would actually change architecture of your code a little bit, by changing your domain interfaces for storage.

How ?
Well redux brings actions, reducers, dispatching, and middlewares for async communication. And currently I can't see how can you completely separate all of this from your domain logic, and hide it behind your interfaces.

Also even if you manage to do it somehow ( like I did somehow.. somehow I mean it changed my domain interfaces but I managed to hide it again) it is still going to be against what is redux-toolkit paradigm, and you will end up with single reducer that sets whole slice.. I am not sure if that's okay?

Here is what I managed to do and all my concerns in one place : https://stackoverflow.com/questions/71649550/clean-architecture-react

I hope you will find the time to answer this.
Thanks for your time.

React Query implementation

Hello Alex, first off I would like to thank you for the detailed article and for sharing this with the community, I've played a bit with this architecture and now I want to implement it in a real world project, which is why I'm raising this issue, since I'm planning to use React Query as my server state management library and I can't figure out how or rather couldn't settle on a solution...

Since react query already handles state management and async calls I feel like it has two types of adapters in one (storage service and api service), i saw how you suggested to implement redux toolkit in one of the previous issues, but this one is different since i don't see how we can decouple react-query from the business logic here... unless we use the library directly with the UI layer (react) ? since it's a react specific library anyways unlike redux, but it must interact with the Application layer ofc for the reasons sepcified earlier... this where i'm being stuck now, since if there is a way to implement React query with the Clean Architecture, I think it would be a very solid combination.

Only potential solution I have now is to wrap each react query function (useQuery, useMutation etc...) in a hook and use it as an adapter somehow that implements a service and then use that in the application layer...

Thank you in advance.

How to define Domain in practice?

Close to the database table (API) design? Close to the UI model design? Or should it be designed close to the business alone?

If it is close to the back-end API, it may be inconsistent with the data model needed for most front-end scenarios.

If it is close to the front-end UI model, it will become inconsistent when requirements change or when there are multiple clients.

If you design it completely by yourself according to the business requirements, first of all, the design cost and difficulty will go up, and there may be a small amount of the above two problems, i.e., it needs to be adapted to both the back-end API and the front-end UI model.

Isn't it superfluous to export functions in adapters instead of constants?

import { NotificationService } from "../application/ports";

export function useNotifier(): NotificationService {
  return {
    notify: (message: string) => window.alert(message),
  };
}

vs

import { NotificationService } from "../application/ports";

export const notifier: NotificationService = { 
  notify: (message: string) => window.alert(message) 
}

Calling functions that return a new service object each time leads to an overhead during code execution and also generates a bunch of garbage for GC. This is practically nothing - for the client, but if such code is used in SSR, this is already a problem

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.