Paul Gielens:ThoughtsService

another Endpoint to my thoughts

News

Syndication

Ads


Favorites

Projects

Organizing Domain Logic

In this article we compare the Microsoft Three-Layered Services Application [Microsoft TLSA] architecture against one by Domain Driven-Design architecture [Evans DDD] for organizing domain logic. For this purpose we use the Microsoft .NET Pet Shop 4 application as an example to explain the difference between these two approaches. It then gives some comments on what Microsoft has in store to better support the latter.

This article is aimed at developers and architects who are trying to find better ways to capture the abstraction of the domain in their designs. It will help you if you have some knowledge in building enterprise applications on the .NET platform.

Recently my thinking on the Three-Layered Services Application (MS-TLSA) in comparison to Domain-Driven Design (DDD) was triggered by the following remark:

The choice between MS-TLSA and DDD is a matter of taste.

Perhaps it is. What interests me in the MS-TLSA architecture is the heart of the software: the Business Layer. This is the layer which deals with the most significant complexity in the particular domain to which the application is targeted. Let’s see what the MS-TLSA has to say about this layer.

Large enterprise applications are often structured around the concepts of business processes and business components. These concepts are addressed through a number of components, entities, agents and interfaces in the business layer.

In the MS-TLSA architecture the Business Layer has been split up in Service Interfaces, Business Workflow, Business Components and Business Entities. We’ll focus on this architecture style and the separation of the Business Components and Business Entities for the remains of this article. First let’s take a look at the MS-TLSA definition for the Business Components part.

Business components are the software realization of business concepts. They are the primary units of design, implementation, deployment, maintenance, and management for the life cycle of the business application. Business components encapsulate the business logic, also called business rules. These rules constrain the behavior of a business concept to match the needs of a particular company. For example, the business rule that determines whether a given customer is approved for a line of credit may be encapsulated in the customer business component for small solutions. For larger solutions, it is likely that all credit-related business logic is encapsulated in a separate credit component.

Sounds solid, right? Let’s do the same for the Business Entities.

Business entities are data containers. They encapsulate and hide the details of specific data representation formats. For instance, a business entity may initially encapsulate a recordset obtained from a relational database. Later, that same business entity may be modified to wrap an XML document with minimal impact to the rest of the application.

Business and business workflow components can interact with independent business entity components or they can use a business entity to set their own state and then discard the business entity. Business entities are often used as Data Transfer Objects [Fowler PoEAA]. The data access components will often return business entities instead of database-specific structures. This helps significantly in isolating database-specific details to the data layer.

So in the MS-TLSA approach Business Components and Workflow Components interact with Business Entities (DTO’s [Fowler PoEAA]). This means that the data and behavior that uses it is scattered throughout the software. Let me remind you that one of the fundamental concepts of object-orientation is to build applications out of objects that have both behavior and data. The MS-TLA architecture also violates the object modeling principle of turning information about a real-world entity and the actions performed on it into responsibilities of the object representing the entity. “Good object think” [Nicola et al. SOM] says objects act rather than get acted on, and conduct their own business rather than hold data for functional processing. While qualifying this statement as an object modeling principle and not an absolute law violation, it is a clear warning sign. The Microsoft .NET Pet Shop 4 application (probably already well known to you) is designed to show the best practices for building enterprise, n-tier .NET 2.0 applications. The concrete .NET Pet Shop architecture has its roots in the MS-TLSA architecture which is why we will use it as an example to demonstrate a reference implementation of this style of Business Layer.

In the .NET Pet Shop application customers use the check out web form to place their order. The check out web form creates a new OrderInfo Business Entity and fetches the LineItem Business Entities from the customer’s shopping cart. Next it asks the Order Business Component to process ordering logic which involves processing the customer’s credit card information (step 1), storing the order (step 2), calculating stock quantities (step 3) and storing the actual stock quantity (step 4). Please note that for the sake of clarity I left out the asynchronous strategy for processing the customer’s order. The following diagram captures a small part of the .NET Pet Shop implementation. 

MS-TLSA .NET Pet Shop check out process

MS-TLSA .NET Pet Shop check out process

I hope you directly notice the TakeStock(LineItemInfo[] items) method on both the Inventory Business Component and Inventory Data Access.

public void TakeStock(LineItemInfo[] items) {

 

    // Reduce the stock level in the data store

    dal.TakeStock(items);

}

Taking a closer look reveals that the Inventory Business Component TakeStock(LineItemInfo[] items) method just forwards the call to the Inventory Data Access to reduce the actual quantity in stock for an order its line items. The actual inventory logic is executed by the Inventory Data Access.

private const string SQL_TAKE_INVENTORY = "UPDATE Inventory SET Qty = Qty - ";

For this code to work properly it also needs to relate each line item and customer order quantity (step 5) with the order.

MS-TLSA .NET Pet Shop check out process

MS-TLSA .NET Pet Shop check out process

I think that it’s safe to say that the .NET Pet Shop check out logic is not only scattered over the Business Components and Business Entities implementations but also across the layers. In my experience this type of application often ends up being quite a tangled web of routines without a clear structure.

What if we’d agreed on having a deep model focus and to use the Domain Model Pattern [Fowler PoEAA] for structuring the check out logic of the .NET Pet Shop application? In a nutshell, the Domain Model pattern is an architectural pattern. Its intention is to capture knowledge in an object model that incorporates both behavior and data. It shines when dealing with complex business logic by its ability to solve domain-related problems in a web of interconnected objects, where each object represents some meaningful concept of the domain. For inspiration in designing a good domain model we’ll use the techniques for applying domain driven design as described in [Nilsson ADDDP].

DDD .NET Pet Shop check out process

DDD .NET Pet Shop check out process

This model solves the same problems/features as we talked about in the MS-TLSA architecture based .NET Pet Shop application example. In this model we speak of an isolated domain model in that it makes the check out concept explicit (step 1). The customers place their order using the check out web form, nothing different here. As opposed to the MS-TLSA architecture based .NET Pet Shop application where state of the order lines was kept in the shopping cart, now the state lives inside the model. The customer and credit card concepts are made part of the model, which makes it natural to make the CreditCard Domain Object responsible for charging the customers credit card (step 2). Reducing the quantity in stock for a particular product (step 4) is the responsibility of the Product Domain Object. This opens up a whole lot of possibilities in which the model acts as an enabler for new opportunities. Taking stock could cause infringements on the margin of critical safety or be used for calculations to determine a realistic safety margin. We now have full control over the check out logic. The first try could look like this:

public void CheckOut()

{

    // Handle credit card logic

    customer.CreditCard.Charge(TotalAmount);

    // Insert the new order into the system

    repository.AddOrder(this);

    // Update the inventory stock

    foreach(OrderLine line in orderLines)

    {

        line.Product.TakeStock(line.Quantity);

    }

}

I think this design is more maintainable in the long run because of its increased clarity and an implementation that is more true to the abstraction of the domain. Remember when I said earlier that the choice between MS-TLSA and DDD is a matter of taste? We have now come to the conslusion that this statement is wrong. It is a matter of choice how to organize domain logic in your applications. For making the right choice you will need to understand both alternatives equally well. What I find appealing about the model focus is that the resulting model is a great tool for communication amongst the stakeholders. The better the communication is, the better the software will become, both in the short and the long run.

I tried the model approach many times over the years and found problems with it, especially related to the performance overhead with instantiation time in the COM world. Another well known problem is the impedance mismatch between the relational and object-oriented worlds. With .NET we now have a much better toolbox that supports object-orientation. The next version of ADO.NET will enable a higher-level abstraction of data-access programming by introducing an entity model that brings conceptual-level data access concepts directly into the code. It includes a layer (ADO.NET Entity Framework Object Services) that can expose database data as regular .NET objects. This object layer makes an ideal target for LINQ support, allowing developers to formulate queries against a database right from the programming language used to build the domain logic. LINQ provides the run-time infrastructure for translating queries into SQL for execution by the database and then translating the tabular results back into the domain objects. I find it exciting to see that Microsoft is working on great tooling to support DDD. Even today, we can go a pretty long way with the current tools.

[Nilsson ADDDP]
Nilsson, Jimmy. Applying Domain-Driven Design and Patterns with Examples in C# and .NET. Addison-Wesley, 2006.

[Evans DDD]
Evans, Eric. Domain-Driven Design: Tackling the Complexity in the Heart of Software. Addison-Wesley, 2004.

[Fowler PoEAA]
Fowler, Martin. Patterns of Enterprise Application Architecture. Addison-Wesley, 2003.

[Microsoft TLSA]
Three-Layered Services Application
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/ArcThreeLayeredSvcsApp.asp

Microsoft .NET Pet Shop 4.0
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/bdasamppet4X.asp

Microsoft .NET Pet Shop 4: Migrating an ASP.NET 1.1 Application to 2.0
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/bdasamppet4.asp

[Nicola et al. SOM]
Nicola, Jill, Mark Mayfield, and Mike Abney. Streamlined Object Modeling: Patterns, Rules, and Implementations. New Jersey: Prentice Hall, 2002.

Comments

Gabriel Lozano-Morán said:

Great post!

# August 8, 2006 4:39 PM

Steve said:

Thanks Paul - I'd like to see more of these types of articles.

I read through Jimmy's book last month and was really impressed.

Seeing more examples and approaches will help provide food for thought for those using the DDD.

# August 8, 2006 8:34 PM

Jonne said:

Nice clarification, it would indeed be nice to see some more practical examples. Ordered the Nilsson book right after I read your article.

# August 9, 2006 4:25 AM

TheServerSide.NET, HJ Meulekamp said:

TheServerSide.NET

Three-Layered Services Application v. DDD

Posted by: Jack Vaughan on August 10, 2006

Is it just style? Perhaps it is writes Paul Gielens.

# August 15, 2006 11:22 AM

Olivier Ausems said:

Nice post Paul!

Thanks.

# August 23, 2006 6:54 AM

Eric said:

But does it really work on complex object hierarchies?  I have not had the luxury of working with systems where you could count the number of entities and their attributes on both hands (Order, Customer, LineItem and Product).  I work in a world of entities, attributes and relationships that number in the low hundreds.  I'll admit to understanding complex object hierarchies and relationships in terms of Forms and Controls where everything is held in memory.  I've had a difficult time of justifying the reconstitution of an entire hierachy when only a portion of the data is need for the current operation (i.e. update the product quantity on hand).  The domain model pattern makes sense to me in simple examples, but in practical terms the transaction script pattern is much more efficient and straight-forward.  If you were somehow working in the database with object hierarchy and you weren't pulling it across process boundaries or machines, and the access was transparent, I would give it a second thought.  For reference, storage wise, I've used everything from COBOL to CACHE (with the current RDBMS somewhere in the middle).

Either way, great article.  I like the focus and the direction.  I hope to see more like it.  I've been following Jimmy's work for some time (ever since his first book -- a total 180 from his current book) and was probably one of the first to order and read it.  I was a bit disappointed.  It was interesting, but very simplified.  When I was finished, I was left with even more doubt than when I started it.  I think Martin's POEA was a much better book.  I've read bits and pieces of DDD, but to be honest... it's quite dry.

# August 27, 2006 1:18 AM

Eric said:

I guess what I'm trying to say, is that I rarely ever deal with an entire reconstruction of the object hierarchy.  My database model is complex and contains entities with many attributes and deeply nested relationships.  

The same aggregates (Jimmy's definition) are not always used.  In one use case, I may need a subset of the attributes and relationships.  In another case, I may need a completely different subset of attributes and no relationships.  It's hard to justify returning data that I don't need, and on the other hand I feel dirty about using partially allocated objects.  The "only the data you asked for" mantra of the resultset (Recordset, DataSet, map, dictionary, array, etc) seems like a much better fit.  

Once again, in a system, where everything was in memory and there was no contention for data (single user system), a large object hiearchy (assuming it was small enough not to bog down the available RAM) seems to make more sense.  But I'm primarily developing web based systems (separated from the database or application server) where more than one concurrent user is in session.

Finally, (I started reading this article as I was flossing my teeth and heading off to bed) I find that a lot of the examples given in books and reference applications (like Pet Shop) have very simple business logic and don't really illustrate much more than shipping data in and out of the database.  Most of the "business logic" layer of the Pet Shop example is just delegating the calls to the data access layer.  

My real feeling is that Microsoft will fail to make any significant impact with it's next version of ADO.NET.  At worst, it will be another ObjectSpaces.    

# August 27, 2006 1:32 AM

plavun said:

In response to Eric's comment, your work primary lies in session scope. In my experience, majority of types in this scope can be called presentation models and belong to different layer from core domain models.

I underline two problems of importance. First is how to ensure transactional aspects in core domain model. Second is how to map between core domain model and presentation model to minimize logic duplication.

Any ORM I know is using database for all of ACID properties (Genom-e probably less) following begin_tran, load, check_global_logic, change, store, check_constraints_logic, commit. In many cases it is slower then working entirely in database. On the other hand, any disconnected model must delegate to data acess layer to ensure serializability, like you observed in PetShop, or as I guess, in your work. In such case, you core domain logic is mixed with presentation logic, or duplicated.

# August 28, 2006 5:28 AM

vinothkumar said:

DDD has been there for a long time. I have worked on a project that uses a Domain Model thats developed 10 years back.. I dont know why every one speaks about it now suddenly...I think some one should compare  SOA Vs DDD ( i know both are quite different but still there is something to discuss)

what about applications like Business Intelligence where u need different Analysis services working around a common set of data .In that case seperating behavior from Objects is good.

But the point is what u said. Both approaches has one thing common --- The Domain Model. The TLSA also has a domain model . Only thing is Behavior is seperated out of the model.

But TSLA model is more like Human . We always keep data and behavior seperately.I keep the phone book in my Mobile . Dial it when required. its kind of service oriented.I can Easily add services.

User Data is there in the Database. I can add Email Services, Search Services, and more.if i use DDD, i have to add Operations required to support each service to the domain objects which might not be that simple.

Visitor is one of the powerful patterns . It seperates the new operations into visitor classes not puts in the object Model.

I think , the choice between DDD and the MSTLSA  can also be influenced by the type of application.

# September 5, 2006 7:49 AM

Paul Gielens:ThoughtsService said:

Frequentlydiscussions on the Domain-Driven Design list contain some real gems. So does a topic started

# September 10, 2006 6:26 AM

Paul Gielens:ThoughtsService said:

Why do I spend so much time with the ADO.NET vNext bits? Udi just reminded me whywith his post Web Service

# September 24, 2006 4:37 PM

Colin Jack said:

Eric, this is indeed an issue. Rocky Lhotka recommends just defining different classes for the different cases and its something I've experimented with:

http://tech.groups.yahoo.com/group/domaindrivendesign/message/4172

I'd say if you need different data/relationships/behavior then I might just create a different class.

I also think that Evans DDD is interesting because it deals with how to have a good domain model BUT avoid contention. Not something I've had to think of in the past but definitely something I'll deal with in the future.

I agree about Jimmy's book, I thought it was good but not great. Like you say I think its a bit oversimplified, it glossed over the really interesting bits which I thought was a pity. Anyway I'm really enjoying Evans DDD.

On the fact about having simplified examples, your right. However I think the advantage of a good domain model is you can then design as you'd like to. For example you'd want to bring in different states, validation rules, security etc etc. All very easy to do in an OO manner in a domain model.

# September 26, 2006 8:57 AM

Colin Jack said:

Oh and I meant to say that I still think Jimmy's book is good, I just felt it wasn't deep enough on the bits that are important.

Maybe someone needs to release a more detailed end to end DDD book, showing really practical examples and discussing (in detail) some of the issues that Jimmy's book only touches on (such as how to handle associations between aggregates when performance/contention are likely to be problems).

# September 26, 2006 9:25 AM

Santosh Benjamin said:

Well, I cant help feeling highly amused at the goings on in this particular area. No sooner had David...

# September 29, 2006 7:01 PM

p.gielens said:

Colin: Very interesting! How would you feel about discussing the posible content of a "more detailed and to end DDD book"? Hit the email link on this page.

# September 30, 2006 4:01 AM

Colin Jack said:

Hi Paul,

I've sent an e-mail which you hopefully got.

Ta,

Colin

# October 5, 2006 11:57 AM

John Mandia's Points of Interest said:

Sorry for the delay but it's been a busy couple of weeks (so this list of links will be longer than

# October 8, 2006 4:36 PM

Pablo M. Cibraro (aka Cibrax) said:

I have just finished reading the Jimmy Nilsson's book, "Applying Domain-Driven Design and Patterns",

# October 30, 2006 9:57 AM

Charles Sharp said:

"M&P is the first "(Domain) Model Driven System" completely operational."

"M&P allows the Direct Execution of the Specifications of Computer Applications without need of building Programs." 

You should see it at:

www.hdolder.com/PeBookRESEJECEN.htm

Regards

Charles

# January 9, 2007 2:05 PM

gongyifeng said:

从分层角度来看,现在三层架构:表现层、业务层和持久层,三个层次应该分割明显,职责分明:持久层职责持久化保存业务模型对象,业务层对持久层的调用只是帮助我们激活曾经委托其保管的对象,所以,不能因为持久层是保管者,我们就以其为核心围绕其编程,除了要求其归还模型对象外,还要求其做其做复杂的业务组合。上面是谈过分依赖持久层的一个现象,还有一个正好相反现象,持久层散发出来,开始挤占业务层,腐蚀业务层,整个业务层到处看见的是数据表的影子(包括数据表的字段),而不是业务对象。

# May 18, 2007 9:46 PM

fszfly said:

面向对象与领域建模

# June 2, 2007 6:10 AM

Alexandre said:

Hi,

1) Which objects would be responsible for saving the credit card charge and the products that had their quantities changed?

2) And which object would be responsible for doing it all in a transaction? The repository.addOrder() must be part of that transaction too.

Thanks

# June 6, 2007 3:28 PM

bluniu said:

有关领域驱动建模

# June 11, 2007 7:16 AM

dongliheng said:

第一阶段:围绕数据库的驱动的分析设计,新软件项目总是从设计数据库及其字段开始。这种围绕数据库分析设计的缺点非常明显:首先,不能迅速有效全面认识反映需求,世界不只是由简单的关系数据组成,而且 使用关系数据来反映现实需求,不符合人类自然思维(OO才是),是一种扭曲的分析方法,特别对于初学者,他们接受数据库分析方法的难度反而可能会大于OO分析方法,现在很多职业学校和社会培训,基础课程从数据库开始,从某种程度上,是历史倒退, 严重阻碍中国软件发展的进程。

# July 4, 2007 6:46 AM

Paul Gielens:ThoughtsService said:

My latest article "The Foundation of Domain-Driven Design" will be published in the next edition of the

# July 9, 2007 5:06 PM

dongliheng said:

板桥里人 http://www.jdon.com 2006/12/6(转载请保留) 多变且复杂的需求 如果没有多变的需求,也许就没有今天的面向对象软件,我们曾经试图通过需求管理、需求跟踪等等管理方式约束和减少需求频繁更新带给软件的冲击,可是这样下去的结果只有一个:使得软件更加僵化;或者程序员更加 劳累。 需求不但多变,而且经常是不可能第一次就能掌握,需求反映了某个领域的专业知识,例如数学、管理、财务或 电子商务等等,每个特定案例需求又有其特别复杂之处,几乎没有人能够第一次接触就可以深入掌握这些专业领域的

# July 26, 2007 12:26 AM

Born 2 Code .NET » Blog Archive » DDD - The list said:

Pingback from  Born 2 Code .NET  » Blog Archive   » DDD - The list

# August 20, 2007 6:35 AM

ζ浮云¢惊龙 said:

面向对象与领域建模

板桥里人http://www.jdon.com2006/12/6(转载请保留)

多变且复杂的需求 如果没有多变的需求,也许就没有今天的面向对象软件,我们曾经试图通过需...

# January 15, 2008 3:39 AM

Cena said:

现在怎么跑出这么多中国话?

全世界的人都在讲中国话,孔夫子的话越来越国际化。

谢谢

# March 17, 2008 9:35 PM

nick_lilaac said:

# December 30, 2008 6:29 AM

Jason said:

The author mentions one flaw of MS-TLSA is that the business logic appears across different layers. To support this, the author shows the Order Business.Component communicating with a data access component. While this is true, the exact same thing would happen in a domain object. The "Order" object calls the repository. The repository is going to call some data layer. You can use a repository or provider model pattern in TLSA so as not to couple BL and DAL. Therefore, the comment "I think that it’s safe to say that the .NET Pet Shop check out logic is not only scattered over the Business Components and Business Entities implementations but also across the layers.", makes no sense.

# January 30, 2009 12:08 PM

Richard said:

The idea of MS-TLSA is to provide layers and decoupling of UI components from the domain. Even in DDD you have an application service layer which buffers the domain model from UI and other consumers(which isn't mentioned in this article). In this DDD sample you also have checkout logic "scattered" over various domain objects. No different than scattering check logic over MS-TLSA business components and entities...so WTF?

# January 30, 2009 12:12 PM

Peter said:

Nice article but the image urls are all broken

# October 20, 2009 8:01 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)