Why are BusinessEntities and BusinessLogic separate projects?

Topics: July and December Releases Forum
Jan 30, 2007 at 3:57 PM
What is the thinking behind separating the BusinessEntities and BusinessLogic projects? I've always had all of this stuff combined in one project (the entity objects know how to load, save, validate themselves, etc.).

What kind of stuff do you recommend putting in each layer? Is the business entity just an object that holds values? Or can it validate, load, and save itself? Does a business entity know how to load up another type of business entity or is that something that the business logic layer can only do?

I'm sure there's some good reason that you guys split the two out, I'm just wondering why you did it.
Jan 30, 2007 at 8:17 PM
As with all architecture topics, there's not one correct way of thinking about things - but hopefully there is some method to our madness here :-)

The key concept in this decision was separation of concerns. This is a good practice as it makes code more readable and allows you to evolve one concern with minimal impact of the other. For example, the description of what data constitutes a Customer has no bearing on how that customer should be saved to the database. While combining everything into one class may seem efficient, it may lead to maintenance problems if you decide you need to change your data access strategy (say from ADO.NET to LINQ or NHibernate).

Validation is probably less clear cut - while the validation logic is techically a different concern, it only acts on the data in the entity (as opposed to external systems such as databases) so the risks of coupling the code are much lower. Still even if you are putting validation logic in the same assemblies as the entities, separating the concerns as much as possible <shamelessPlug>such as by using the Validation Application Block in EntLib 3.0</shamelessPlug> will still make your code more readable and maintainable.

Hope this helps
Jan 30, 2007 at 8:33 PM
I was not directly involved in the design (just implementation) so take my thoughts with a grain of salt.
Consider that the WSSF approach gives you basically prescriptive guidance on how you can structure your web services in an enterprise wide scale so your design requirements may vary according the kind/scale of your project. Regarding your question about the business layer partition in entities and rules, you may consider separate projects in order to provide reusability of entities (they may represent both state and behavior, save/load) across different services and therefore used by different business rules that may also be reused across services (recall my first statement above regarding scoping/scale of projects). In a typical scenario, the business rules will make use of entities and perform the required operations with them (other than simple persistence that may be handled by each entity on its own).

Jan 31, 2007 at 8:24 AM
The separation of entity and logic is a classic Microsoft TLSA guideline, and is rather contrary to general object oriented thinking (object=data+behavior) and to 'domain objects' in Domain Driven Design. I think this was caused by simplifying things by making the entity objects also act as data transfer objects (DTO). Developers do not want to "waste" time implementing data transformation/mapper logic, so they ingore the difference between service internal data and service external data. Luckily, the WSSF team has separated the data contracts (DTO) from the business entities.

The separating of behavior and data is what Martin Fowler and Eric Evans calls the anemic domain model anti-pattern: http://www.martinfowler.com/bliki/AnemicDomainModel.html

Making your entities real OO domain objects does not prevent you from using EL3 to validate the rules; just ensure that you specify the business rules in the domain object and leave it to the validator app block to contain the generic validation logic and interpret the rules. We have used a 'broken rules' run-time in our projects; with the business rules in the domain objects and the rule-interpreter in a separate, reusable component.

Do not scatter your domain object code all over your layers, it just makes the code harder to understand, test and maintain.

Separating how entity objects are stored to/read from the repository into an own data access layer is best practice, don't make your domain objects depend on a specific data storage technology.