3

I've been in the process of re-writing the back-end for a web site and have been moving it towards a three-tiered architecture.

My intention is to structure it so:

Web site <--> WCF Service (1) <--> Business Layer (2) <--> Data Layer (3)

My issue is with the placement of the DTO's within this structure. I'll need to use DTO's to move data between the business layer and the WCF service and from the WCF service to the consuming web site.

During my research on here I've read some excellent discussions though I've been left scratching my head a bit:

  • Davide Piras makes some great points in this post and if I were to follow this design then I'd declare interfaces for the POCOs in a separate project. These would then be implemented by tiers (1) and (2). Whilst I like the use of interfaces it does seem like I'd be making more work for myself by declaring POCOs in (1) and (2) and then copying their data back and forth using something like AutoMapper.

  • This post uses a system where a business objects project is created which would be referenced by all tiers. This seems to be simplier than the other solution and seems to lead me to a solution that would be

Web site <--> WCF Service (1) <--> Business Layer (2) <--> Data Layer (3)

^               ^                       ^
|               |                       |
[ -- Business Objects Referenced here --]

My question is this: is there a code smell from sharing the business objects across three layers of the solution or are the two methods I've listed above just two different ways of cracking the same nut?

GrandMasterFlush
  • 6,269
  • 19
  • 81
  • 104
  • 1
    Great question. Well worded and researched. I was about 2 days from being able to ask such a question but it helped some pieces of the puzzle fall into place. Sort of sounded like 'Ka-Chung, Ka-Chung!' – SleepyBoBos Jan 22 '14 at 04:56

2 Answers2

2

I would say that it often depends on the complexity of the project you're building. For smaller projects that I've built, I shared my 'entities' (they were just simple DTOs, serializable data buckets with getters and setters) across the layers and didn't care too much about this. On of the biggest downsides was that the logic got scattered across the project (not only in the 'Business Layer') and had a procedural-style all around. This really seems like the Anemic Domain Model, but the complexity didn't creep in as the project didn't grow too much. Entity Framework has some templates you can build you entities off of as such (if I'm not mistaken they're called self tracking entities?).

For medium/bigger projects, I wouldn't use this approach and would keep entities and DTOs separately as they would serve different roles. The DTOs might have a totally different shape than your entities and trying to share them between the tiers/layers would be often smelly.

Stefan Szasz
  • 1,247
  • 11
  • 27
  • Thanks for your thoughts. I'd not considered the size of the project when looking at these two methods. As the web site isn't a massive one and most of the growth will probably reconsist of re-use of the existing objects I'm probably swinging towards the shared business objects. – GrandMasterFlush Jul 17 '12 at 12:41
2

Let's think of your UI (website) and service (WCF + BL + DAL) as two distinct entities.

  • If you have 100% control over both, you should choose approach #2 since it will avoid translation between WCF proxy objects and your business objects in the UI layer.

  • Else, you are better off with approach #1 since one of the entities is kind of a 'black box' and is subject to change by external stakeholders. So, it's safer to maintain an internal set of business objects. This will need translation between your business objects and the WCF proxy objects (through Extension methods or a translator framework).

Now, not exactly sure of your UI layer complexity or its implementation (MVC, WebForms, etc.), so you may or may not need View specific objects (lighter for data-binding, faster to serialize to JSON, etc.), let's call this object as the Model.

  • If you don't need a distinct UI specific Model, suggest to mark your business objects as DataContract (in the context of WCF) and use them across layers. Don't forget to explicitly mark entities as Serializable if you are invoking WCF via the web ($.ajax).

  • Else, use DataContract in the service and a translator to convert DataContract to Model in the UI layer. A Service Adapter is a good fit here - it sits in the UI layer and is responsible for consuming the WCF service and translating between DataContract and Model. You may use a Service Proxy in the UI layer, which is a wrapper over your WCF service and is consumable over the web.

Lastly, aren't you are missing a reference to the Business Objects in your Data Layer? I believe you will populate your Business Objects from the data-store in the Data Layer itself.

Channs
  • 2,091
  • 1
  • 15
  • 20
  • Thanks for taking the time to reply. I think I'm swinging towards method #2, as you said with me having control over both the web site and the backend and it not being a large site I'd be making more work for myself with little benefit using method #1. The site isn't MVC and is just plain web forms. Long term, I might move it over to MVC and I'd not given any thought as to whether this would affect that. I'll bear in mind what you've said, cheers! – GrandMasterFlush Jul 18 '12 at 08:43
  • With regards to the data layer and business objects reference, my Data Layer just exposes a static class that allows the business layer access to the database. Looking at it, I may have muddied the boundaries between the two layers doing that. – GrandMasterFlush Jul 18 '12 at 08:45