5

I have the following folder structure for my application

app
    core
    features
        feature1
            domain
                entities
                    entity1
                    entity2
                    entity3
                    entity4
                    entity5
                    entity6
            data
                models
                    model1
                    model2
                    model3
                    model4
                    model5
                    model6
            presentation
        feature2
            domain
                entities
                    entity1
                    entity2
                    entity3
                    entity4
                    entity5
                    entity6
            data
                models
                    model1
                    model2
                    model3
                    model4
                    model5
                    model6
            presentation

Model 1 to 6 for both features are exactly the same and more are coming as the application scales. This is becoming hard to maintain. Does clean architecture allow for sharing models and entities across the multiple features? Would that be done through the core folder?

anonymous-dev
  • 2,897
  • 9
  • 48
  • 112

3 Answers3

3

I'm assuming you're following the ResoCoder course. I did too. I used that design in our team for a few weeks before realizing there soon become problems with it (which ResoCoder himself realizes if you check the Github issues and responses for his repo):

  • Sharing between features doesn't work well.
  • It's hard to have functionality split between multiple features.
  • Not well organized with a lot of code.
  • Some more which I forget off the top of my head (He wrote some article on the failing of it somewhere).

Hence, for my team's app (getting quite complex now), we've adapted this which seems to work:

(ignore the 2 \core directories, that's by mistake. There's meant to be only 1)

enter image description here

Then, inside all of these top-level directories (excluding /core - that's specifically for things like API clients, routers, etc.), there's folders for each feature. Ex: authentication, settings, posting, etc.

Then, here's the important bit, in each of these feature-split directories (ex: /domain, /presentation, etc.) we have a sub-directory called /shared that resembles what each folder needs to look like, except it just contains functionality that's categorized as (example) domain or data. This stuff is then split between all features.

For example, if I have an app that allows users to post content, I'm going to create the post entity (using ResoCoder terminology) inside the /posts feature. Except, UH OH, I need to have it displayed inside the /feed feature as well! This is then a perfect case for /shared inside the general /domain directory.

Let me know if this helps, or if you have any further questions!

Matthew Trent
  • 2,611
  • 1
  • 17
  • 30
  • You have two core directories inside your project? can you provide sample of full directories? It's difficult for me with only text. What is inside the core directory? – fajar ainul Feb 09 '23 at 00:17
  • @fajarainul Typo! My bad, I just made note of it in the question :) – Matthew Trent Feb 09 '23 at 03:00
  • So what is inside core directories? actually I learned flutter with TDD by resocoder also and I have a question in my mind, where is the best place to put the Bearer token? On http client configuration? but not all request need it. On remote datasource? or pass from repository to datasource then pass again to http client? Please help me, thanks! – fajar ainul Feb 09 '23 at 06:54
  • @fajarainul Personally, I created an `HttpClient` class that stores all the token information in it. It has a method for API requests that allows you to add a bool for needing a token or not, what REST verb, body, headers, etc. This class is then injected via `get_it` (pub dependency for dependency injection) everywhere I need in the app. As to what I store in the `/core` directory, looking at my project here are some things: router, error message class that all other error message inherit from (for continuity), clients folder (http client and db client live there), custom animation curves – Matthew Trent Feb 09 '23 at 09:05
  • (Got length limited last comment)… network connection checkers, responsive design breakpoints, styles directory (theming and typography), generators (randomly generate splash screen text is one for example), rate limiters, and the biggest one is utils which has a ton of sub directories (number formatters, mediaquery shorthand’s, etc.), converters for objects (example: receiving keys from the backend that map to achievement objects, or keys that map to job descriptions and types, etc.), and many more. Hopefully this gives you an idea! Basically, everything that is quite universally-used. – Matthew Trent Feb 09 '23 at 09:08
  • 1
    So you set your token header inside http client (assumed get the token from local storage) based on the bool value? Ahh I see, I thought the ```core``` directory is feature(s) that can be accessed from all 'features'. I was wrong, so they should rest inside top-level directory right? (inside ```domain```, ```data```, and ```presentation```). The last, ```application``` is where the features are. I think I got the idea now. Thank you for your help! – fajar ainul Feb 09 '23 at 10:02
2

Yes you can and you maybe should not do it.

Yes, because the clean architecture doesn't make a statement about this. As long as the dependency rule is honored you are compliant in terms of the clean architecture.

But you maybe should not do it, because there are other principles and considerations you should take into account.

First, you should ask your self if it would be a violation of the single responsiblility principle. Sometimes things look the same but are not really douplicated code. It's more an accident that they look the same. The question is "Who is the change trigger?". Usually the features change for different reasons and thus the features use cases and entities change for different reasons. If so you should not share the models between them.

Second, from a DDD (domain driven design) perspective the features can be in different bounded contexts. In this case you can have two entities with the same name, but they have different meanings in the differnt context. Therefore, the models have different properties and different methods.

If you decide to share the modles you should take a close look at them in intervalls and scan the properties and methods. Are there properties and methods that are exclusively dedicated to one feature? If so you are maybe mixing concerns.

Finally if you are facing problems like "Uhh, we changed someting here and broke something there", you should rethink if the sharing of some code is a good way to go. Sharing of code always couples code, because all clients depend on the shared code. It's a trade off between duplication (maintenance costs) and dependencies. Principles like the SRP help you to make an educated guess.

René Link
  • 48,224
  • 13
  • 108
  • 140
  • 1
    In this case the models are game components. And are shared between 3 platforms where they need to be the same. A change trigger in one of this components should also be a change in the other platforms. They are game components that in all 3 platforms have the same context. So I would say in this case a shared folder would make sense. But thanks for the explanation, this really helped! – anonymous-dev Sep 29 '22 at 07:54
1

Does clean architecture allow for sharing models and entities across the multiple features?

I think DRY principles should be applied whether you use clean architecture or not.

As for the answer:

I think you could abstract your shared models and entities into separate modules or packages. If it's all dart code, I suggest choosing packages. You can place it inside the root project (Monorepo) or separate it to another repository, this way you could achieve modularity by abstracting the all layer of shared dependency (abstract class, interface, clients, or maybe repositories) out of the main application

There is a good video about this topic on Google I/O'19, it is about Android but you can get great insight and applied to general mobile development. I suggest you give it a try

TijaniRF
  • 160
  • 2
  • 13