23

For example, if I'm using some MVC-like architecture, which folder structure should I use:

domain1/
    controller
    model
    view
domain2/
    controller
    model
    view

Or:

controllers/
    domain1
    domain2
models/
    domain1
    domain2
views/
    domain1
    domain2

I deliberately left out file extensions to keep this question language-agnostic.

Personally, I'd prefer to separate by business domain (gut feeling), but I see that most/many frameworks separate by technical domain. Why whould I choose one over the other?

1
  • 2
    frameworks are targeted at developers, not at business users. Developers are expected to be more comfortable with technically-oriented approach and frameworks take that into account - that may be the reason for what you observe
    – gnat
    Commented Oct 18, 2012 at 8:12

6 Answers 6

17

I think this depends on specific project.

For example, if the different business domains are totally independent of each other, then I'd organize by business domain.

But if there is shared code between the business domains, or rather, the business domains are different variants of the same code base, then it seems more logical to organize by technical domain. And if you use any sort of Object Oriented language, then you can probably subclass your generic controllers, models, etc in your business-specific files to make them thinner.

There is also a (golden) mid-way between the two - strip out shared code into it's own domain and use that in other domains. This gives you your gut feeling-powered layout, but allows shared code between business domains.

Domain1              # This domain changes bits of standard MVC code
  controllers
  models
  views
Domain2              # this domain only modifies views, all else is standard
  views
Shared               # Here is the better part of code base
  controllers
  models
  views

PS. I think that most frameworks organize by technical domain just because they tend to expect that you mix different business domains into single project only if you have shared code and otherwise would create separate projects.

EDIT:

For example, suppose there is a web app that handles a company's warehouse. In generic form this might apply to many companies, but each of them might have some specifics that aren't met and forbids them to buy in. E.g one of them has deployed tablets to the forklifts and needs special View for them while yet another wants to organize items into three levels instead of the default of two.

You could of course fork the project for each of these companies. But if the framework/language allows, you could use subclassing or plugins etc to customize bits and pieces of the generic project to every customer's needs and organize them in the Business Domain layouts.

E.g if generic project exports to JSON only the Item itself, Domain1 can subclass the controller and make it export also recent delivery problems.

And if you later find that Domain1 has a component that is also valid for Domain2, you can extract generic version of it to Shared.

As you said, many frameworks organize by technical domain and that is what I have used for now, just because my FW of choice makes this easier. But with a little (or a lot) of elbow-grease, I think I could rewrite the include paths to support Business Domain layout too.

2
  • I think the idea is great, but I fail to imagine a practical example. Could you give a simple yet enlightening one? Commented Oct 18, 2012 at 16:12
  • @FlorianMargaine - I'll give you a real world example. Real Estate websites. At my last job we sold several real estate websites to many customers. We had a centralized database for all 50+ customers. Each back-end admin used a shared set of modules. Each customer facing side used unique images and navigation. Each search and drill down pages used shared modules except in cases where a customer wanted one-off features. For those one-offs we split out the code and gave them their own module. (Drawback: Upgrades had to be done in the common moduels and duplicated in the the one-off modules) Commented Nov 22, 2012 at 13:17
11

I think it's enlightening to ask, "what am I more likely to add on a regular basis, more domains or more technical divisions?" Then whatever the answer is, put that at the top level.

In most cases your technical architecture will solidify faster than your domain. That means you should organize by domain first, then by architectural component. The reason is that when something in a domain changes, you may have to add or change multiple technical components in that domain, but hopefully that's localized and doesn't spill over much into other domains.

If you changed your GUI framework, then that means your changes will spill across the whole application, but then again, you rarely change your GUI framework, but you're always changing your domain logic.

Keep things together if they're likely to change at the same time.

3
  • Best advice, but I don't see how to predict which kind of domains I'm going to add the most. Commented Oct 18, 2012 at 18:05
  • The last sentence nails it. Commented Oct 18, 2012 at 20:05
  • @FlorianMargaine - I don't think the "kind" of domain matters. If you add domains more than you add new technical "things" then group everything by domain first. Commented Oct 18, 2012 at 20:06
3

There is another alternative and that is moving the seperate parts in plugins. CakePHP does that for example. It will allow you to generate complete MVC parts which are re-usable which you can sort by any logic you want.

Your main application will just use them and link to them.

Basically your question is also about cohesion and coupling. You want the separate parts to work as independently as possible. That way you get testable and re-usable code.

Taking that into consideration: If you split up by domain how would you re-use parts of your application? For example take a webshop: a request comes in for /orders/view/1 so you need to show order nr. 1. Goes to /orders/controllers/order_controller If you seperated domain by products and orders you would already need parts of the other "domain".

There you can start interfacing things but likely things are in most business just too cohesive. If you take the technical approach. For example you could have a plugin handling orders. You put in Product objects to it from your central application. That way you can test the plugin easily, just create some Product object with a name and price and send it in.

The plugin will do exactly what it needs to do. It will depend on it's input and not on other "parts/domains/areas".

1
  • Good idea. It's essentially top-down of my answer. I put Shared code at the top and basically plugged in Domain specifics. You put Domain at the top and plug in Shared code. I think both are equally good approaches regarding de-coupling and testability.
    – Laas
    Commented Oct 19, 2012 at 7:30
2

Microsoft ASP.Net MVC 3 has the concept of "Areas". When you introduce "Areas" into your MVC project, they break it up like:

area1/
   models
   views
   controllers
area2/
   models
   views
   controllers

I found this to be quite natural. An area is a "large chunk" of a project, and working in a self-contained unit just made a lot of sense.

We used namespaces to match, FWIW.

3
  • 2
    Thank you for your contribution, but how does that answer my question? (Comparing both solutions) Commented Oct 18, 2012 at 8:19
  • @FlorianMargaine: I am illustrating how Microsoft did it, with the (possibly flawed) assumption that they put a lot of engineering effort into picking the more sensible way. Hope it gives some input.
    – gahooa
    Commented Oct 24, 2012 at 19:28
  • Ok, but that's the business oriented way I showed in my question... Commented Oct 25, 2012 at 6:08
1

From my personal experience with a web shop consisting of 300 000 lines of code, I would always go for organizing by business domain. This way, you can not only get a quick overview of all relevant classes when you work on one functional area, in Java you can also make use of the package visibility.

Some details for those who are interested: When the project was started 5 years ago, the developers created the following package structure:

com
  example
    web
      struts
        action
        form
      shared
      functionality1
      functionality2

Each shop function such as shopping cart, product search etc. consists of several actions, each with its own form class (structure mandated by the MVC framework). What we ended up with are over 200 classes in the action package, each one completely separated from their associated form class. What's worse is that actions don't implement too much logic, but call function-specific services which reside in yet another package.

I suggested and convinced the team that we should switch to organizing packages by business domain. The reasoning is simple: if you really want to see a list of all actions, you can simply open the type hierarchy view of any decent IDE. However, what the IDE cannot do is infer the business domain a class belongs to. Furthermore, that approach allows you to make only those classes public which are needed by several functionalities, keeping the rest on package visibility.

0

I agree that many frameworks separate by technical domain and so I often start this way when using a new framework. However, I consistently settle on using business domain as the primary level of folder organization.

Personally, I think it's much easier to keep my Foo Controller and Foo Repository or whatever together than going back and forth between the Controller's folder and the Repository's folder as often I need to work on both when adding features around Foo. In larger projects this is even more important as the distance between technical folders can be great and become a noticeable waste of time while developing.

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.