11

I am designing a new application that deals with a lot of business logic.

To avoid the usual entanglement between different application layers that often sneaks into such systems over time, I want to implement clean separation of concerns right from the start. Broadly speaking I want to separate:

  • presentation layer
  • business logic layer
  • data storage and persistence layer

The question I am struggling with most is how to actually implement behavior at the edges cleanly, especially between the business and the data layer. I have seen too many applications where the data layer hands ORM objects to the core layer, effectively tightly coupling the business logic to the ORM.

Should I convert ORM objects to some serialized format (JSON?) and then deserialize that in the business layer into a data structure internal to that layer? Isn't that a lot of overhead?

How do you cleanly implement separation of concerns for medium sized applications? Any advice?

B.M.
  • 111
  • 5
  • 3
    What is ORM objects? An ORM typically maps data to domain objects which are not tightly coupled to the data access layer, so there should be no problem in passing these to the business layer. Of course the ORM infrastructure itself should not be passed to the business layer. – JacquesB Mar 15 '17 at 15:40
  • I see a lot of ORMs auto-generating classes that map the database schema 1:1, e.g. `article.getId()`, `article.getTimestamp()` etc. These mappings seem to more often than not be specific to the ORM used. – B.M. Mar 15 '17 at 15:47
  • You should probably switch ORM. Which ORM are you using? – JacquesB Mar 15 '17 at 15:55
  • Not decided on an ORM for this project yet, but I've worked with a few: SQLAlchemy, SQLObject, Django ORM, Propel, ... – B.M. Mar 15 '17 at 16:44
  • OK, I don't know a lot about Python ORM's but at least SQLAlchemy claims it can map to arbitrary objects, i.e. the domain objects will not have a dependency on the ORM. – JacquesB Mar 15 '17 at 16:57
  • 1
    You find detailed suggestions about this in Uncle Bob's description of a [Clean Architecture](https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html). The paragraphs "crossing boundaries" and "What data crosses the boundaries" are exactly dealing with your problem. – Doc Brown Mar 15 '17 at 19:43
  • JaquesB: mapping to non-ORM-specific objects is certainly good advice. Doc Brown: I'll check it out, thanks! – B.M. Mar 15 '17 at 21:55

2 Answers2

6

There is always something of a logical coupling between the business logic and database. Your efforts should be focused on preventing a physical coupling.

For example, take the very basic business rule that each user must have a unique user ID. You can try to enforce that rule in the business layer, but there will always be some scenario where multiple users may try the same user ID at the same time, and the only place where you can check for uniqueness and reserve a user ID in an atomic way is in the database.

Now, the business layer should not need to know the name of the table or the column, or even that users are stored in a database (they could, for example, be stored in Active Directory instead, for an intranet application). Only the data access layer should know that. But to spend a ton of effort disconnecting the schema from the business rules is probably wasted effort.

John Wu
  • 26,032
  • 10
  • 63
  • 84
4

Make sure your Business Model objects are in thier own library which does not reference any ORM or database clients.

Use the Repository pattern and only reference interfaces to the repositories in your main code.

Have a completely separate concrete repository library specific to the datalayer which references the interface library, the business models library and the database client.

Ewan
  • 70,664
  • 5
  • 76
  • 161