Abstractions that are... too abstract? - oop

In the Vaughn Vernon's Domain-Driven Design Distilled book we can read that we should try to avoid creating technical abstractions that are perhaps too abstract and try to be more explicit by sticking to the concepts of the Ubiquitous Language.
Where I work we've built several tracking applications and in almost every of them there is the problem of having multiple specializations of the same thing, most likely with common behaviors, but different data and validation rules.
For instance, imagine an incident logging application where various kind of incidents are reported over the phone (e.g. car accident, fire, robbery). The information gathering process is similar to every incidents, but the captured data may vary widely as well as the validation rules that constrains this data.
So far, we have always solved these kind of problems with very technical abstractions (this is an oversimplified model, but you should get the idea):
As you can see, the DataValidationRules, DataFields and DataEntries abstractions have very little to do with the business of incident logging. Actually, they are part of a very generic solution to the problem of representing multiple entity specializations with different data in any domain.
I'd like to move away from this kind of very abstract model, but at the same time I do not see what would be the correct approach in making the business concepts explicit. I understand that the answer would be different in every domain, but in essence, should I be looking into having a single class per specialization? E.g. CarAccidentIndicent, FireIncident and RobberyIncident?
With a very limited number of specializations it seems like it could be manageable, but what if I have hundreds of them?
What about the UI? That means I'd have to move away from a generic way of generating the UI as well.
After thinking a little more about it I think I may have found a better and simpler way to express my concerns when it comes to DDD, OO and modeling many specializations.
On the one hand I want to come up with a model that is faithful to the Ubiquitous Language (UL) and model domain concepts explicitly. On the other hand I'm trying to respect the "favor composition over inheritance" mantra I'm so used to apply.
It seems that boths are conflicting because in order to enable composition I'll have to introduce abstractions that are most likely not part of the UL (e.g. Entity--Field composition) and when it comes to explicit modeling I do not see any other way than inheritance with one class per specialization.
Am I wrong in trying to avoid inheritance to represent hundreds of specialized entities that mainly differ in terms of data structure, not behaviors?
Then again, assuming they did differ a lot in terms of behaviors as well I'd have the same dilemma.
Just to be more explicit on the design choices:
In one scenario, composition would be achievable dynamically without requiring multiple classes per specialized compositions:
class Incident {
Set<Detail> details;
IncidentType type;
}
interface Detail {
public DetailType type();
}
class SomeDetail implements Detail {
...
}
class SomeOtherDetail implements Detail {
...
}
In the other scenario compositions are static and do require one class per specialized composition:
class CarAccidentIncident extends Incident {
SomeDetail someDetail;
SomeOtherDetail someOtherDetail;
}
class SomeDetail {}
class SomeOtherDetail {}
Obviously, the second approach is more explicit and offers a natural home for specific behaviors and rules. In the first approach we would have to introduce some abstract and technical concepts like Operation and DetailValidation which may not align well with the UL.
With a small number of different specializations I'd probably choose the latter without a second though, but because there are many of them it seems like I'm leaning more towards dynamic composition (even thought being dynamic is not required). Should I?

When to use DDD?
The thing is, DDD is not necessarily the right fit for all systems. It's particularly well suited to large systems with complex business rules.
If the business rules that need expressing to capture the essence of a FireIncident are simple enough to be encoded in a DataValidationRules record and a set of DataFields, then that suggests that perhaps those rules do not require the complexity of a DDD implementation.
The Domain of Data Validation
However, if you acknowledge that, you can shift your perspective towards intending to actually build a pure data validation engine. The domain of data validation should include entities such as data validation rules, and data fields, and would contemplate such questions related to the lifecycles of rules and fields - e.g. 'what happens if a validation rule changes - do all existing records that have previously been validated need revalidation?'
If the lifecycle of a data validation rule itself is complex enough to warrant it, then by all means, use DDD to implement that domain, although you may still choose to use CRUD if you find there are no complex rules or processes in the domain of data validation.
Who are your Domain Experts?
The further consequence of that is that your domain experts are no longer your end users (the people who know about car accidents and fire incidents) they are now the people (most likely specialists) who craft the validation rules and fields. If using DDD, you need to be asking them what types of rules they need and how they need the rules to work, and implementing using the Ubiquitous Language that they use to talk about the art and process of crafting validation rules.
Those people, in turn, would be 'programming' a next level system (you might say they are using a 4GL language tailored to the domain of incident logging) using your data validation engine. The thing is, their domain experts would be the people who know about car accidents. But the specialists wouldn't strictly be using DDD to craft the rules of a car accident, because they would not be expressing their model in software, but in the constrained language of your data capture and validation engine.
Additions following Update
Have been pondering this since your update and had a few more thoughts/questions:
Data Validation vs Entity Lifecycle/Behavior
Most of your concern is around representing data validation rules on create/update. Something that would help to understand is - what behavior/rules are represented by your entities other than data validation? i.e. in an incident management system, you might track an incident through a set of states such as Reported, WaitingForDispatch, ResponseEnRoute, ResponseOnSite, Resolved, Debriefed? In an insurance system you might track Reported, Verified, AwaitingFunding, Closed, etc.
The reason I ask, is that in the absence of such lifecycle behavior - if the main purpose of your system is pure data validation, then I return to my original thought of wondering if DDD is really the right approach for this system, as DDD brings greatest value when there is complex behavior to be modelled.
If you do have such lifecycles or other complex behavior - then one possibility is to consider the approach from the perspective of different bounded contexts - i.e. have one bounded context for data validation - which uses the approach you've described with more technical abstractions - as it is an efficient way to represent the validations - but another context from the perspective of lifecycle management, in which you could focus more on business abstractions - if all incidents follow similar set of lifecycles, then that context would have a much smaller number of specific entities.
Keeping entities sync'd between contexts is a whole 'nother topic, but not too troublesome if you adopt a service bus or event type technology and publish events when things change.
Updates to Validation Rules?
How do your business experts express requests for changes to validation rules? And how do you implement them? I'm guessing from what you've said, they probably express them in domain terms such as 'FireIncident'. But the implementation is interesting - do you have to craft data modification statements in SQL which get applied as part of a deployment?
Inheritance vs Composition
It seems that boths are conflicting because in order to enable composition I'll have to introduce abstractions that are most likely not part of the UL (e.g. Entity--Field composition)
I do not think this is true - composition does not have to require introducing technical abstractions. With either composition or inheritance, the goal is to distil insights into the domain to discover common patterns.
e.g. look for common behaviours or data validation sets and find the business language term that describes this commonality. e.g. You might find RobberyIncident and FireIncident both apply to Buildings.
If using inheritence you might create a BuildingIncident and RobberyIncident and FireIncident would extend BuildingIncident.
If using composition, you might create a valueobject to represent a Building and both RobberyIncident and FireIncident would contain a Building property. However RobberyIncident would also contain a Robbery property and FireIncident would also contain a Fire property. CarAccidentIncident and CarRobberyIncident would both contain a Car property, but CarRobberyIncident would also contain a Robbery property of the same type as the Robbery property on RobberyIncident - assuming they are truly common behaviours.
You may still have hundreds of classes representing specialised incident types, but they are simply composed of a set of value object properties representing the set of common patterns they are composed of - and those value objects can and should be in terms of ubiquitious language concepts.

My take on this is that not all information is pertinent to the domain.
I think that in many instances we try to apply techniques in an "all-or-nothing" approach whereas we may need to be focusing on the "right tool for the job". In the answer provided by Chris he asks the question "When to use DDD?" and mentions "The thing is, DDD is not necessarily the right fit for all systems." I would argue that DDD may not be appropriate for some parts of a system.
Would DDD be useful to create, say, a word processing application? I don't really think so. Although some good old proper OO would go a long way.
DDD is absolutely great for business behaviour focused bits of a system. However, there are going to be bits that can be modeled in a more technical/generic way that feed into more interesting business functionality. I'm sure that those incidents end up in some business process. An example may be a Claim. The business is very interested in tracking a claim and the claim amount, but where that claim came from isn't all too interesting. For all intents and purposes the "initiating documentation" may be filled in using pen and paper and scanned in to be linked to said claim. One could even start a new claim on the system using a plain text input.
I have been involved in a number of systems where a lot of peripheral data was sucked into the system but actually it wasn't really contributing much (law of diminishing returns and such).
I once worked on a loan system. The original 20 year-old system was re-written in C#. The main moving bits:
Client
Loan Amount
Payment schedule
Financial transactions (interest, payments, etc.)
All-in-all it is really a simple system. Well, 800+ tables later and stacks of developers/BAs and the system is somewhat of a monster. One could even capture stock and title deeds as guarantee. Now, my take would be to scan in some of this information and link it to the loan. However, somehow some business folks decide that they absolutely "must have" this information in the system. It isn't core though, I would say.
On the other end, another system I worked on calculated premiums. It was modeled quite business-like and was quite a maintenance nightmare. It was then re-written very generically by simply defining calculations that work on given inputs. There were some lookup tables for values and so on but no business processing as such.
Sometimes we may need to abstract moving bits into something that makes sense as an input or output and then use that in our domain. I think the UL should be used by ourselves and domain experts but it doesn't mean that we are not going to end up using technical concepts that are not part of the UL, and I think that that is okay. I'm sure a domain expert wouldn't care much for a SqlDbConnection even though we are going to using one of those in our code :) --- similarly we could model some structures outside of the domain proper.
In response to your update and question: I would not create a concrete class unless it really does feature in the UL in a big way. On a side note, I still favour composition over inheritance. I typically implement interfaces where necessary and go with abstract classes when inheriting, just to place some default behaviour when it helps.
The UL, as with any design, represents a model with nuances. We can apply DDD without using domain events. When we do use domain events we may even go with event sourcing. Event sourcing has very little to do with the UL in much the same way that the terms "Aggregate", "Entity", or "Value Object" would. The UL is going to be specific to the domain / domain experts and when we, as domain modelers, talk to each other we can describe various models in terms of DDD tactical patterns in order to bring across some of the specific UL concepts.
We have to listen to how a domain expert describes the problem space. As soon as we hear "When", as stated in so many other places, we know that we are probably dealing with an event. In much the same way we can listen to how a domain expert talks about the aggregates. For instance (totally bogus example):
"When a customer is registered we need to inform the supervisor of the CSR that initiated the request"
More loosely related to your example:
"When an incident takes place we need to capture some specific details regarding the incident. Depending on the type we need to capture different bits and validate that we have sufficient data to process our claim
Between these two we can see a distinct difference in how they are referring to interacting with the problem space. When a domain expert thinks of something in very broad terms I think it is prudent that we do the same.
On the other hand, should the conversation be more along the lines of this:
"When a car accident is registered we need to assign an assessor an wait for an assessment report that has to answer..."
Now we have something much more specific. These are, necessarily, mutually exclusive in that if they only ever talk about specifics then we go with "specific". If they first mention in broad terms and then specifics, we can also work in broad terms.
This is where our modeling is tricky to get right. It is the same nuance as we have in the Address as an aggregate vs value object "debate". It all depends on the context.
These things are going to be tricky and dependent on the domain in order to get right. As Eric Evans did mention: it may take a couple of models to get something that fits just right. This is necessarily so based on one's experience with the domain.

Related

Is it common tradeoff to consider, that interaction between Bounded Contexts may "cripple Open Closed Principle"?

I am implementing interaction between bounded contexts and I found out that it "somehow" cripples open closed principle and I am not sure, whether it is natural consequence of designing BCs and common tradeoff to consider or my design failure.
Consider Shop BC where you can create Order out of Cart with some items. Created order consists of OrderItems, each of them containing one of various types of ItemSpecification Value Object Interface like ProductSpecification or FooServiceSpecification, protecting invariants and containing some data. When Order is created, asynchronous event that can be listened to by any other BC is emitted.
That asynchronous event is created out of Order and is represented as (serialized) OrderCreatedEvent object, containing OrderDTO object, all placed in Core namespace which is shared with every BC so that any BC can depend on Core, but not the other way. All good so far, almost:
That OrderItemDTO must contain interface ItemSpecificationDTO, which need be implemented for every type of specification. My ItemSpecification VO (like any other VO/Entity in Order) has toCoreDTO() method to pragmatically achieve easy translation and it also makes relatively hard to implement new ItemSpecification and forget to implement according DTO. That's probably okay.
But what about other BC's which listen to that Event? In every BC this Event needs to be translated in it's AntiCorruption Layer and that BC may be interested only in some types of ItemSpecificationDTO and translate them to various Value Objects, important for that specific BC.
As Uncle Bob says about OCP in a wit:
You should be able to extend the behavior of a system without having
to modify that system.
But when I implement new type of ItemSpecification, for every BC which may be interested in this new type I need to specifically translate that new type from CoreDTO (okay I could write some abstraction for translating in each BC so I would still be just adding code without modyfying anything like adding if($x instanceof X)). But still, by adding new type of ItemSpecification I need to make appropriate extensions (and maybe even modify something because we don't live in ideal world) in other BCs.
And I do not know how to think about that. Is that downside of whole DDD approach? Or maybe feature indeed, because that hunting for what, where and how needs to be further extended in other BCs, is driven by domain needs instead of technical concerns? It seems right. In the end, I'm trying to do domain driven design :-) But it seems to me somehow dangerous too. I am afraid that one day we can forget to update some other BC and something bad happens. But that is probably because I play big part of domain expert role too, under which that "fear" should probably belong. Is my problem just sitting on two chairs or did I got something wrong? :-)
There are a lot of interesting details about this topic, but I would concentrate here on one specific aspect of bounded contexts.
That is that they are bounded for a reason. As in, there should be a boundary between the models/understanding of these contexts. Two contexts, even if they are related should have a different view on the system, even on the data that might be partly shared.
It seems to me that your "bounded contexts" want to work on the same model. You even created a "core" model which everyone can see and apparently must be able to understand. If this is the case, I'd argue that you lost the benefits of having different contexts, and you are just creating one big application, with one model.
To correct this problem, I think you would need to get rid of any central/core models, and work with "local" (bounded) models in the different contexts/services. When you need to communicate with other components, you need to define a protocol for those two, dictated by either or both parties.
For example a Shopping Cart might need to know the product-id for the backend system to create the order there. But the backend system doesn't need to know the model the shopping cart uses to know what the order is about (in its own model).

How to design a business logic layer

To be perfectly clear, I do not expect a solution to this problem. A big part of figuring this out is obviously solving the problem. However, I don't have a lot of experience with well architected n-tier applications and I don't want to end up with an unruly BLL.
At the moment of writing this, our business logic is largely a intermingled ball of twine. An intergalactic mess of dependencies with the same identical business logic being replicated more than once. My focus right now is to pull the business logic out of the thing we refer to as a data access layer, so that I can define well known events that can be subscribed to. I think I want to support an event driven/reactive programming model.
My hope is that there's certain attainable goals that tell me how to design these collection of classes in a manner well suited for business logic. If there are things that differentiate a good BLL from a bad BLL I'd like to hear more about them.
As a seasoned programmer but fairly modest architect I ask my fellow community members for advice.
Edit 1:
So the validation logic goes into the business objects, but that means that the business objects need to communicate validation error/logic back to the GUI. That get's me thinking of implementing business operations as objects rather than objects to provide a lot more metadata about the necessities of an operation. I'm not a big fan of code cloning.
Kind of a broad question. Separate your DB from your business logic (horrible term) with ORM tech (NHibernate perhaps?). That let's you stay in OO land mostly (obviously) and you can mostly ignore the DB side of things from an architectural point of view.
Moving on, I find Domain Driven Design (DDD) to be the most successful method for breaking a complex system into manageable chunks, and although it gets no respect I genuinely find UML - especially action and class diagrams - to be critically useful in understanding and communicating system design.
General advice: Interface everything, build your unit tests from the start, and learn to recognise and separate the reusable service components that can exist as subsystems. FWIW if there's a bunch of you working on this I'd also agree on and aggressively use stylecop from the get go :)
I have found some o fthe practices of Domain Driven Design to be excellent when it comes to splitting up complex business logic into more managable/testable chunks.
Have a look through the sample code from the following link:
http://dddpds.codeplex.com/
DDD focuses on your Domain layer or BLL if you like, I hope it helps.
We're just talking about this from an architecture standpoint, and what remains as the gist of it is "abstraction, abstraction, abstraction".
You could use EBC to design top-down and pass the interface definitions to the programmer teams. Using a methology like this (or any other visualisation technique) visualizing the dependencies prevents you from duplicating business logic anywhere in your project.
Hmm, I can tell you the technique we used for a rather large database-centered application. We had one class which managed the datalayer as you suggested which had suffix DL. We had a program which automatically generated this source file (which was quite convenient), though it also meant if we wanted to extend functionality, you needed to derive the class since upon regeneration of the source you'd overwrite it.
We had another file end with OBJ which simply defined the actual database row handled by the datalayer.
And last but not least, with a well-formed base class there was a file ending in BS (standing for business logic) as the only file not generated automatically defining event methods such as "New" and "Save" such that by calling the base, the default action was done. Therefore, any deviation from the norm could be handled in this file (including complete rewrites of default functionality if necessary).
You should create a single group of such files for each table and its children (or grandchildren) tables which derive from that master table. You'll also need a factory which contains the full names of all objects so that any object can be created via reflection. So to patch the program, you'd merely have to derive from the base functionality and update a line in the database so that the factory creates that object rather than the default.
Hope that helps, though I'll leave this a community wiki response so perhaps you can get some more feedback on this suggestion.
Have a look in this thread. May give you some thoughts.
How should my business logic interact with my data layer?
This guide from Microsoft could also be helpful.
Regarding "Edit 1" - I've encountered exactly that problem many times. I agree with you completely: there are multiple places where the same validation must occur.
The way I've resolved it in the past is to encapsulate the validation rules somehow. Metadata/XML, separate objects, whatever. Just make sure it's something that can be requested from the business objects, taken somewhere else and executed there. That way, you're writing the validation code once, and it can be executed by your business objects or UI objects, or possibly even by third-party consumers of your code.
There is one caveat: some validation rules are easy to encapsulate/transport; "last name is a required field" for example. However, some of your validation rules may be too complex and involve far too many objects to be easily encapsulated or described in metadata: "user can include that coupon only if they aren't an employee, and the order is placed on labor day weekend, and they have between 2 and 5 items of this particular type in their cart, unless they also have these other items in their cart, but only if the color is one of our 'premiere sale' colors, except blah blah blah...." - you know how business 'logic' is! ;)
In those cases, I usually just accept the fact that there will be some additional validation done only at the business layer, and ensure there's a way for those errors to be propagated back to the UI layer when they occur (you're going to need that communication channel anyway, to report back persistence-layer errors anyway).

Where to start when doing a Domain Model?

Let's say I've made a list of concepts I'll use to draw my Domain Model. Furthermore, I have a couple of Use Cases from which I did a couple of System Sequence Diagrams.
When drawing the Domain Model, I never know where to start from:
Designing the model as I believe the system to be. This is, if I am modelling a the human body, I start by adding the class concepts of Heart, Brain, Bowels, Stomach, Eyes, Head, etc.
Start by designing what the Use Cases need to get done. This is, if I have a Use Case which is about making the human body swallow something, I'd first draw the class concepts for Mouth, Throat, Stomatch, Bowels, etc.
The order in which I do things is irrelevant? I'd say probably it'd be best to try to design from the Use Case concepts, as they are generally what you want to work with, not other kind of concepts that although help describe the whole system well, much of the time might not even be needed for the current project. Is there any other approach that I am not taking in consideration here? How do you usually approach this?
Thanks
Whether DDD, or not, I would recommend with determining the ubiquitous language (UL) by interviewing the product owner(s). Establishing communication in a way that will have you and the product owners speaking the same language not only aides in communication, but being able to discuss the project in common terms tends to help the domain model define itself.
So, my answer is basically to discuss, listen, and learn. Software serves a need. Understanding the model from the viewpoint of the experts will lay the solid groundwork for the application.
I'd start by a drawing a class diagram with all the relationships and implement only the classes that are necessary according to the requirements of your application.
You can use an anemic approach (attributes plus getters and setters) to keep things simple and avoid the step of writing business logic in the same step. With an anemic model, the logic would go into a corresponding Service class. That way you can consider Use Cases later on.
I know some people don't appreciate this way of doing things but it does help with maintenance and avoids some dependency issues.
Answer to devoured elysium's question below:
In terms of analysis, starting with Use cases (What) and then proceeding to the class diagram (How) sounds like a good rule of thumb. Personally, I'd do the Sequence diagram (When and Who?) afterwards, as you'd need to know between which processes/objects messages need to be sent.
Beyond that my take on things is that UML is simply a way to model a system/project and not a methodology by itself (unlike Merise, RAD, RUP, Scrum, etc.). There is nothing stopping someone starting off with any diagram as long as they have the sufficient information to complete it. In fact, they should be done simultaneously since each of the diagrams is a different perspective of the same system/project.
So, all in all it depends on how you go about the analysis. During my studies I was taught the rigid waterfall approach, where you do a complete analysis from start to finish before producing some code. However, things can be different in practice, as the imperative might be to produce a working application in the least time possible.
For example, I was introduced to the Scrum methodology recently for an exercise involving the creation of a web site where people can post their fictions. As there was a time constraint and a clear vision of what should be achieved, we started right away with a bare bones class diagram to represent the domain model. The Use cases were then deduced from a series of mock screens we'd produced.
From memory, the classes were Story, Chapter, User and Category. This last class was phased out in favour of a more flexible Tag class. As you'd imagine, the complete class diagram of the existing project would be much more complex due to applying domain driven design and the specificities of the Java programming language.
This approach could be viewed as sloppy. However, a web site like this could easily be made in a couple of weeks using an iterative process and still be well designed. The advantage an iterative process has over the waterfall approach is that you can continually adjust requirements as you go. Frequent requirements changing is a reality, as people will often change their minds and the possibility of producing a working application after each iteration allows one to stay on course so to speak.
Of course, when you're presenting a project to a client, a complete analysis with UML diagrams and some mock screens would be preferable so they have an idea of what you're offering. This is where the UML comes in. Once you've explained some of the visual conventions, an individual should be able to understand the diagrams.
To finish off, if you're in the situation where you're trying to determine what a client wants, it's probably a good idea to gradually build up a questionnaire you can bring with you. Interviewing a person is the only way you can determine what concepts/features are really needed for an application, and you should expect to go back in order to clarify certain aspects. Another tip would be to do some quick research on the web when you're confronted with a subject matter you're unfamiliar with.
In your example, this would be to go through the basics of anatomy. Among other things, this will help you decide what the model should contain and what granularity it should have (What group of organs should be considered? How precise does it need to be? Do only the organs need to modeled or should they be decomposed into their constituents like tissues, cells, chemical composition, etc. ?).
I think the place to start would be whatever feels logical and comfortable. It's probably best to start with the use cases, as they give you clear direction and goals, and help you avoid YAGNI situations. Given that you should be trying to develop a strong domain model, it shouldn't really matter, as the whole picture of the domain is important.
I would like to share my experience for such type of situations. I usually start with writing tests and code. And try to cover one end to end use case. This gives me fair enough idea about problem and at the end I also have something working with me which I can show case to my client. Most of the time subsequent stories build on top of previous one, but it also happens to me that subsequent stories require changes in the previous model I came up with. But this does not impact me as I already have good test coverage. In this way I came up with the model which fits for the current problem, not the model which maps the real world.
You start with Business Requirements which can be formalized or not. If formalized you would use Use Case Diagrams.
For example here are use case diagrams for an e-commerce app:
http://askuml.com/blog/e-commerce/
http://askuml.com/files/2010/07/e-commerce-use-case.jpg
http://askuml.com/files/2010/07/e-commerce-use-case2b.jpg
From these use cases, you can naturally deduce the business entities: product, category of product, shopping cart, ... that is start to prepare class diagrams.
This is best practice in many methodologies but this is also just common sense and natural.
Short answer
Pick a use case, draw some collaboration diagram (and a class diagram) to realize the domain objects involved. Concentrate only on those objects participated in order to accomplish use case goal. Write TDD test case to set the expectation and gradually model your domain classes to meet the expectations. TDD is very helpful to understand the expected behaviors and it helps to get the cleaner domain model. You will see your domain evolve gradually along with the TDD expectations.
Long answer
My personal experience with DDD was not easy. That was because we didn't have necessary foundations in the first place. Our team had many weak points in different areas; requirements were not captured properly and we only had a customer representative who was not really helpful (not involved). We didn't have a proper release plan and developers had a lack of Object Oriented concepts, best principles and so on. The major problem we had was spending so much time on trying to understand the domain logic. We sketched many class diagrams and we never got the domain model right, so we stopped doing that and found out what went wrong. The problem was that we tried too hard to understand the domain logic and instead of communicating we made assumptions on the requirements. We decided to change our approach, we applied TDD, we started writing the expected behavior and coded the domain model to meet the TDD's expectations. Sometimes we got stuck writing TDD test cases because we didn't understand the domain. We straight away talked to the customer representative and tried to get more input. We changed our release strategy; applied agile methodology and release frequently so that we got real feedback from the end user. However, needed to ensure the end user expectation was set at the right level. We refactored based on the feedback, and in that way the domain model evolved gradually. Subsequently, we applied design patterns to improve reusability and maintainability. My point here is that DDD alone cannot survive, we have to build the ecosystem that embraces the domain, developers must have strong OOP concepts and must appreciate TDD and unit test. I would say DDD sits on top of all the OOP techniques and practices.

I've never encountered a well written business layer. Any advice?

I look around and see some great snippets of code for defining rules, validation, business objects (entities) and the like, but I have to admit to having never seen a great and well-written business layer in its entirety.
I'm left knowing what I don't like, but not knowing what a great one is.
Can anyone point out some good OO business layers (or great business objects) or let me know how they judge a business layer and what makes one great?
Thanks
I’ve never encountered a well written business layer.
Here is Alex Papadimoulis's take on this:
[...] If you think about it, virtually every line of code in a software
application is business logic:
The Customers database table, with
its CustomerNumber (CHAR-13),
ApprovedDate (DATETIME), and
SalesRepName (VARCHAR-35) columns:
business logic. If it wasn’t, it’d
just be Table032 with Column01,
Column02, and Column03.
The
subroutine that extends a ten-percent
discount to first time customers:
definitely business logic. And
hopefully, not soft-coded.
And
the code that highlights past-due
invoices in red: that’s business
logic, too. Internet Explorer
certainly doesn’t look for the strings
“unpaid” and “30+ days” and go, hey,
that sure would look good with a #990000 background!
So how then is possible to encapsulate all of this business logic
in a single layer of code? With
terrible architecture and bad code of
course!
[...] By implying that a system’s architecture should include a layer dedicated to business logic, many developers employ all sorts of horribly clever techniques to achieve that goal. And it always ends up in a disaster.
I imagine this is because business logic, as a general rule, is arbitrary and nasty. Garbage in, garbage out.
Also, most of the really good business layers are most probably proprietary. ;-)
Good business layers have been designed after a thorough domain analysis. If you can capture the business' semantics and isolate it from any kind of implementation, whether that be in data storage or any specific application (including presentation), then the logic should be well-factored and reusable in different contexts.
Just as a good database schema design should capture business semantics and isolate itself from any application, a business layer should do the same and even if a database schema and a business layer describe the same entities and concepts, the two should be usable in separate contexts--a database schema shouldn't have to change even when the business logic changes unless the schema doesn't reflect the current business. A business layer should work with any storage schema provided that it's abstracted via an intermdiate layer. For example, the ADO.NET Entity framework lets you design a conceptual schema which maps to the business layer and has a separate mapping to the storage schema which can be changed without recompiling the business object layer or conceptual layer.
If a person from the business side of things can look at code written with the business layer and have a rough idea of what's going on then it might be a good indication that the objects were designed right--you've succesfully conveyed a solution in the problem domain without obfuscating it with artifacts from the solution domain.
I've always been stuck between a rock and a hard place. Ideally, your business logic wouldn't be at all concerned with database or UI-related issues.
Keys Cause Problems
Still, I find things like primary and foreign keys causing problems. Even tools like Entity Framework don't completely eliminate this creep. It can be extremely inefficient to convert IDs passed as POST data into their respective objects, only to pass this to the business layer, which then passes them to the data layer to just be stripped down again.
Even NoSQL databases come with problems. They tend to return full object models, but they usually return more than you need and can lead to problems because you're assuming that object model won't change. And keys are still found in NoSQL databases.
Reuse vs. Overhead
There's also the issue of code reuse. It's pretty common for data layers to return fully populated objects, including every column in that particular table or tables. However, often business logic only cares about a limited subset of this information. It lends itself to specialized data transfer objects that only carry with them the relavent data. Of course, you need to convert between representations, so you create a mapper class. Then, when you save, you need to somehow convert these lesser objects back into the full database representation or do a partial UPDATE (meaning a another SQL command).
So, I see a lot of business layer classes accepting objects mapping directly to database tables (data transfer objects). I also see a lot of business layers accepting raw UI values (presentation objects), as well. It's also not unusual to see business layers calling out to the database mid-computation to retrieve needed data. To try to grab it up-front would probably be inefficient (think about how and if-statement can affect the data that gets retrieved) and lazy loaded values result in a lot of magic or unintended calls out to the database.
Write Your Logic First
Recently, I've been trying to write the "core" code first. This is the code that performs the actual business logic. I don't know about you, but many times when going over someone else's code, I ask the question, "But, where does it do [business rule]?" Often, the business logic is so crowded with concerns about grabbing data, transforming it and whatnot that I can't even see it (needle in a hay stack). So, now I implement the logic first and as I figure out what data I need, I add it as a parameter or add it to a parameter object. Getting the rest of the code to fit this new interface usually falls on a mediator class of some kind.
Like I said, though, you have to keep a lot in mind when writing business layers, including performance. The approach above has been useful lately because I don't have rights to version control or the database schema yet. I am working in a dark room with just my understanding of the requirements so far.
Write with Testing in Mind
Utiltizing dependency injection can be useful for designing a good architecture up-front. Try to think about how you would test your code without hitting a database or other service. This also lends itself to small, reusable classes that can run in multiple contexts.
Conclusion
My conclusion is that there really is no such thing as a perfect business layer. Even in the same application, there can be times when one approach only works 90% of the time. The best we can do is try to write the simplest thing that works. For the longest time I avoided DTOs and wrapped ADO.NET DataRows with objects so updates were immediately recorded in the underlying DataTable. This was a HUGE mistake because I couldn't copy objects and constraints caused exceptions to be thrown at weird times. I only did it to avoid setting parameter values explicitly.
Martin Fowler has blogged extensively about DSLs. I would recommend starting there.
http://martinfowler.com/bliki/dsl.html
It was helpful to me to learn and play with CSLA.Net (if you are a MS guy). I've never implemented a "pure" CSLA application, but have used many of the ideas presented in the architecture.
Your best bet is keep looking for that elusive magic bullet and use the ideas that best fit the problem you are solving. Keep it simple.
One problem I find is that even when you have a nicely designed business layer it is hard to stop business logic leaking out, and development tools tend to encourage this. For example as soon as you add a validator control to an ASP.NET WebForm you have let business logic leak out into the view. The validation should occur in the business layer and only the results of it displayed in the view. And as soon as you add constraints to a database you then have business logic in your database as well. DBA types tend to disagree strongly with this last point though.
Neither have I. We don't create a business layer in our applications. Instead we use MVC-ARS. The business logic is embedded in the (S) state machine and the (A) action.
Possibly because in reality we are never able to fully decouple the business logic from the "process", the inputs, outputs, interface and that ultimately people find it hard to deal with the abstract let alone relating it back to reality.

Service-Orientation vs Object-Orientation - can they coexist?

There's been a lot of interest in Service-Oriented Architecture (SOA) at my company recently. Whenever I try to see how we might use it, I always run up against a mental block. Crudely:
Object-orientation says: "keep data and methods that manipulate data (business processes) together";
Service-orientation says: "keep the business process in the service, and pass data to it".
Previous attempts to develop SOA have ended up converting object-oriented code into data structures and separate procedures (services) that manipulate them, which seems like a step backwards.
My question is: what patterns, architectures, strategies etc. allow SOA and OO to work together?
Edit: The answers saying "OO for internals, SOA for system boundaries" are great and useful, but this isn't quite what I was getting at.
Let's say you have an Account object which has a business operation called Merge that combines it with another account. A typical OO approach would look like this:
Account mainAccount = database.loadAccount(mainId);
Account lesserAccount = database.loadAccount(lesserId);
mainAccount.mergeWith(lesserAccount);
mainAccount.save();
lesserAccount.delete();
Whereas the SOA equivalent I've seen looks like this:
Account mainAccount = accountService.loadAccount(mainId);
Account lesserAccount = accountService.loadAccount(lesserId);
accountService.merge(mainAccount, lesserAccount);
// save and delete handled by the service
In the OO case the business logic (and entity awareness thanks to an ActiveRecord pattern) are baked into the Account class. In the SOA case the Account object is really just a structure, since all of the business rules are buried in the service.
Can I have rich, functional classes and reusable services at the same time?
My opinion is that SOA can be useful, at a macro level, but each service probably still will be large enough to need several internal components. The internal components may benefit from OO architecture.
The SOA API should be defined more carefully than the internal APIs, since it is an external API. The data types passed at this level should be as simple as possible, with no internal logic. If there is some logic that belongs with the data type (e.g. validation), there should preferably be one service in charge of running the logic on the data type.
SOA is a good architecture for communicating between systems or applications.
Each application defines a "service" interface which consists of the requests it will handle and the responses expected.
The key points here are well defined services, with a well defined interface. How your services are actually implemented is irrelevant as far as SOA is concerned.
So you are free to implement your services using all the latest and greatest OO techniques, or any other methodology that works for you. ( I have seen extreme cases where the "service" is implemented by actual humans entering data on a screen -- yet everything was still text book SOA!).
I really think SOA is only useful for external interfaces (generally speaking, to those outside your company), and even then, only in cases when performance doesn't really matter, you don't need ordered delivery of messages.
In light of that, I think they can coexist. Keep your applications working and communicating using the OO philosophy, and only when external interfaces (to third parties) are needed, expose them via SOA (this is not essential, but it is one way).
I really feel SOA is overused, or at least architectures with SOA are getting proposed too often. I don't really know of any big systems that use SOA internally, and I doubt they could. It seems like more of a thing you might just use to do mashups or simple weather forecast type requests, not build serious systems on top of.
I think that this is a misunderstanding of object orientation. Even in Java, the methods are generally not part of the objects but of their class (and even this "membership" is not necessary for object orientation, but that is a different subject). A class is just a description of a type, so this is really a part of the program, not the data.
SOA and OO do not contradict each other. A service can accept data, organize them into objects internally, work on them, and finally give them back in whatever format is desired.
I've heard James Gosling say that one could implement SOA in COBOL.
If you read Alan Kay's own description of the origins of OOP, it describes a bunch of little computers interacting to perform something useful.
Consider this description:
Your X should be made up of Ys. Each Y should be responsible for a single concept, and should be describable completely in terms of its interface. One Y can ask another Y to do something via an exchange of messages (per their specified interfaces).
In some cases, an X may be implemented by a Z, which it manages according to its interface. No X is allowed direct access to another X's Z.
I think that the following substitutions are possible:
Term Programing Architecture
---- --------------- ------------
X Program System
Y Objects Services
Z Data structure Database
---- --------------- ------------
result OOP SOA
If you think primarily in terms of encapsulation, information hiding, loose coupling, and black-box interfaces, there is quite a bit of similarity. If you get bogged down in polymorphism, inheritance, etc. you're thinking programming / implementation instead of architecture, IMHO.
If you allow your services to remember state, then they can just be considered to be big objects with a possibly slow invocation time.
If they are not allowed to retain state then they are just as you've said - operators on data.
It sounds like you may be dividing your system up into too many services. Do you have written, mutually agreed criteria for how to divide?
Adopting SOA does not mean throw out all your objects but is about dividing your system into large reusable chunks.