0

Abstract

I'm trying to figure out a solid, scalable, clean and practical architecture for react projects.
As a a playground I have a project with two Screen and a JSON server.
When I try to apply a clean, one-directed architecture, I end up with a very complex Structure.

(Here, a Screen stands for *a site, that is shown to the user if they open a URL)

Output on Screen

enter image description here

  • Screen 1 contains component A (input/output of database information) and B (output of database information). It also shows a sidebar (that's supposed to be shown on all screens).
  • Screen 2 contains the same component A with exactly the same features and component C (output of database information), and of course the sidebar.

Architecture

  • Screen1 and Screen2 are implemented as Page1 and Page2.
  • A Page combines the website template (sidebar, top bar) and a corresponding view. (Think of it as the application window of a word processor software)
  • A view is the content I want to show to the user without the sidebar and top bar (think of it as the editing area in a word processor software)
  • Component A: Props contain information and a callback method (e.g. how to submit information).
  • Component B/C: Props contain information only.

I eventually end up with the inverted pyramid architecture below.
Explanation from top to bottom:

  • There are business components A,B,C (like InputForm or StatusPanel). These consist of smaller general purpose components like submit button or input field.
  • Each view uses the components it should show on screen
  • Each component requires props (data and possibly callbacks).
    • Component A is used in view 1 and view 2; To stay DRY, a generalized class/function is necessary to create the props: PropsCreatorA.
    • As stated above, I'm ultimately searching for an architecture to a much bigger project with more screens, so I added PropsCreatorB and PropsCreatorC to emphasize how complex this gets, quickly.
  • A database adapter is created once in the router and used throughout all pages (pages possibly rely on interfaces). enter image description here

Problems

  • Is this actually a good architecture?
  • This feels like there's going to be a lot of overhead (many files, many folders for managing) just for showing two pages on screen.
  • The PropsCreators might contain callback functions making use of navigation (useNavigate) - for example to move to a new screen after the input form in CompA was filled out. I.e. they need to know the pages. How would I incooperate that?

1 Answer 1

3

Note: I'm intentionally ignoring your mentions of database adapters in your React codebase. This is not a great idea, but that's a whole different topic in and of itself.

Component A is used in view 1 and view 2; To stay DRY, a generalized class/function is necessary to create the props: PropsCreatorA

If anything here is too complex, I suspect it's this adherence to DRY.

DRY is not an absolute. By that I mean that it's easy to overapply it, and doing so leads to an additional abstracting, which increases complexity. To summarize my point:

Just because two things look the same does not mean that they are the same.

Take the example of a Person and Dog class, both of which have a string Name property. Should we now abstract this into a reusable NamedObject base class from which Person and Dog derive?

Well, it depends. If a change to one does not necessarily lead to a change in the other, e.g. just a Person will be refactored to have a first and last name, and a Dog does not follow suit; then they should've not been implemented reusably to begin with.

More often than not, the reusability buck stops with components. Anything above is related to the page/view and tends to live its own life for its own reasons. Each page is designed individually, and the reusable parts are already formed into components.
The only thing that remains are therefore parts that should not be reused, and therefore trying to inject reusability in them is leading to needless complexity.

To make the design consistent, there's also a PropsCreatorB and PropsCreatorC

Am I to understand from this that you didn't need these classes, but created them regardless just to conform to what some other class needed? If so, that's further compounding the initial issue.

Screen1 and Screen2 are implemented by view1 and view2.

Why? What is the additional layer adding of value? I suspect this is an extension of already juggling your prop creators.

In your image, you outright state that the Page's template only consists of the view. So what's the purpose of separately defining a page and a view?

I'm no React dev. If there is a technical necessity to have both a page and a view; then you'll obviously need to do so. But in such a case, this complexity should not be counted against Clean Architecture itself.


Taking the above observations into account, this cuts out a huge chunk of your complexity:

enter image description here


I think the crux of the issue is here:

I only have two screens/views (see below) with data from a json server; but when I try to make it a clean architecture I end up with a very complex Structure.

You're using a nuke to kill two spiders. Or, maybe a bit closer to the topic, you're trying to model an industrial warehouse's policies and operations when you're a guy managing two boxes. Your solution is disproportionately complex to your original problem.

Architectures like Clean Architecture are there to help massive codebases deal with a truckload's worth of components and keep them in line so that they remain change-friendly and to avoid that you end up painting yourself in a corner later on when a small changes has to be spread through the extended codebase.
With it comes a whole lot of additional abstraction and broad strokes rule setting that makes sense when you need to wrangle many different implementations that are alike.

Two screens in a frontend app are nowhere near the kind of size you need to justify Clean Architecture.

That doesn't mean you're not allowed to use it. For example as a matter of learning to use Clean Architecture, it's perfectly fine to try and apply it to a scaled down codebase.
However, you shouldn't then judge the complexity that Clean Architecture brings with it relative to your tiny codebase. The benefits only become apparent when your codebase reaches enterprise grade.

3
  • Thank you very much for your involvement! "So what's the purpose of separately defining a page and a view" --> A Page adds the general UI elements like side bar and top bar to the view and is ultimately the entity shown to the user or used for routing ( = it has a URL). The view is the content the user clicked on. (My explanation was very misleading here :/ , going to edit the question). (2) "You're using a nuke to kill two spiders" (Also misleading explanation): The two screens were just for illustration. I'm trying to figure out a solid, scalable architecture (going to edit the question)
    – DarkTrick
    Commented Jul 18, 2022 at 14:22
  • "I'm intentionally ignoring your mentions of database adapters" > I'd really like to hear more about this. Any links? Related question: softwareengineering.stackexchange.com/q/439861/345246
    – DarkTrick
    Commented Jul 18, 2022 at 14:34
  • "However, you shouldn't then judge the complexity that Clean Architecture brings with it relative to your tiny codebase." --> You're saying I shouldn't be worried about (much?) more complexity clean architecture brings, because that's just it's nature? (asking to make sure my understanding is correct.)
    – DarkTrick
    Commented Jul 18, 2022 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.