3

I am looking to quantify the cost or problems of bad software development practices. Specifically can software that has been developed resulting in an anemic domain model be quantifiable in terms of business cost or risk?

My initial thoughts (which are all nearly impossible to generically quantify) are: -

  • Reduced flexibility.
  • Potential for increased support costs.

Any assistance you can offer would be greatly appreciated.

3
  • 6
    I'd tell you but my costing/risk-assesment domain model is really anemic.
    – psr
    Commented Jan 17, 2013 at 23:40
  • Funny thing, but I hardly agree with one word of that article -we practice some form of cqrs at work, using nhibernate for mapping. Strictly speaking, our domain models contain only data validation and basic data manipulation. I guess the author would suffer some sort mild convulsions upon seeing that code.
    – Max
    Commented Jan 18, 2013 at 6:21
  • 2
    CQRS doesn't prevent you from not using anemic data models. In fact, CQRS + DDD is a great fit. And DDD to promote models with behavior.
    – jgauffin
    Commented Jan 18, 2013 at 8:21

5 Answers 5

7

I don't believe what you are asking is actually possible to do. The reason I say this is simply because you are asking whether it is possible to justify one particular design over another when there are too many variables effecting it.

Firstly the debate over the anaemic domain model is not finalised. I've heard arguments from both sides as to whether it is good or bad. I think the reality is that "good" vs "bad" is completely dependant on the technologies you are employing and the application being developed. If you try to exclude those then there are too many "Yes - But"s to have such as answer.

The second consideration is that when comparing developing a product using X vs Y there are a whole host of factors that can mess with any numbers you try and come up with. Mostly because the idea of being able to compare project A with project B and deducing a comparison result on one factor is like comparing Boeing to Airbus and saying Arbus is better because they use titanium bolts where Boeing uses Hi Tensile Steel. I don't know if they do, but you get the idea.

The factors that will place question marks over your values are such things as the team members skills, design philosophies, experience and personal preferences and coding habits. The projects goals, technologies, time lines, customers and any prior history. Management support, funding, influence and control. No two projects will every be exactly the same in any of these factors and therefore any "quantifiable" results are at best questionable when it comes to "this" vs "that".

Various highly knowledgable people in the industry have used stats from large numbers of projects to make various generalisations about project development. These people are very smart and experienced. If you look into some of the background material on the waterfall vs agile debate you will see some of this data. I think that you request is far to macro to be able to make similar "factual" statements. Because of the complexities involved, you can only work at the large scale with these sorts of things.

3

With an anaemic domain model, testing becomes more expensive, because logic tends to be more coupled with persistence. One great benefit for the Domain Model Pattern is the possibility to test key features in a Unit Test fashion. Faster and cheaper.

As a result of an anaemic approach, some teams spend (or waste) a lot of time in test. Test need to include cleanups and to guarantee idempotency. They're more expensive, and usually do not provide the same degree of confidence that a test suite should provide. Some other teams, test less. Test doesn't look so appealing due to the big time investment, and so ...no confidence. Both approaches lead to bigger costs when it comes to further evolutions.

Confidence might not look like an appealing term for the management, but it badly influence the ability for an IT department to respond (or anticipate) evolving business needs.

However, not all portions of the software have the same expectations for the future. Some components might respond to a temporary need, and no evolution is on the horizon. Some others might need continuous evolution due to many factors.

  • Evolving business requirements.
  • Dependencies with external tools and libraries.
  • Continuous Learning of the domain.
  • Frequently changing regulations.

For software whose life expectancy is to include a lot of maintenance/evolution, it is pointless to focus on optimization of writing time (which is the most appealing marketing approach for most frameworks, by the way). For software whose expectation is different, more short-term strategies might be reasonable. Clearly, we can be wrong. :-)

2
  • Thanks very much for you answer it was very interesting and I had never contemplated the confidence aspect, great pick up.
    – Kane
    Commented Jan 19, 2013 at 1:47
  • Hi @Kane, thanks. Sorry I missed your response. :-P
    – ZioBrando
    Commented Mar 12, 2013 at 20:16
2

It's difficult to do, but it can be done if you have been keeping metrics regarding your development process. You'll also need a comparison to base your presumed costs against. Ideally, you would have an identical team / project without an anemic domain model to compare against. Obviously, that's not realistic so a one-off project built by the same team but without the drag of the domain model would suffice.

From there, you simply have to compare the rate of development between the two projects. Lines of code written is one method, but I don't think it's very meaningful. Similar feature requests would be a better comparison, in my opinion. And you'll want to measure the amount of time in both calendar and developer time that it took in order to deliver the features. If your metrics allow you to dig into requirements discovery and QA, those aspects of the SDLC can present helpful, supplementary information.

In an ideal case, you'll have requirements -> dev -> test / QA measured. A perfect feature comparison would have similar times for requirements and test, but an increased amount of development time. Since you've effectively controlled for other likely factors (different teams, ...) you can then point to the anemic domain model as the culprit for the increased development time.

Translating increased development time into money is equally "easy". There are two major factors to consider here - first is raw development dollars based upon internal rate of overhead * amount of increase in time. The second is opportunity cost. Add up your product's annual revenue and divide that by your developer time. That will provide a somewhat crude but valid measure of potential revenues lost once you multiply the hourly opportunity cost against the increase in dev time.

You mention support costs as well. A similar approach of documenting time spent on product ABC vs. XYZ with support calls will provide the basis of your analysis.

Realistically speaking, you're going to have a hard time coming up with ideal numbers like that. If you don't have any metrics at all, I'm not sure you're going to be able make a case. Document your assumptions, refine the numbers a bit to make them more manageable, and run your assessment by a trusted confidant within the business to make sure the message is clear.

2

Anemic data models usually comes with public setters. So you got something like this:

public class Order
{
    public string Id { get; set; }
    public string UserId { get; set; }
    public OrderState State { get; set; }
    public DateTime StateChangedAt { get; set; }
    public List<OrderLine> Products { get; set; }
}

Let's say that you have a routine which will scan all orders which will report orders have been in state WaitingOnStock for two weeks. Then in one place where that state is set you got

var order = _repository.Get(orderId);
if (product.StockCount == 0)
{
    order.Products.Add(new OrderLine(4, product));
    order.State == OrderState.WaitingOnStock;
}
_repository.Save();

See? Since the developer do not know / forgot about the StateChangedAt field the notification routine wont work.

If you instead have let the Order class control it's behavior that wouldn't have happened:

public class Order
{
    public string Id { get; private set; }
    public string UserId { get; private set; }
    public OrderState State { get; private set; }
    public DateTime StateChangedAt { get; private set; }
    public IEnumerable<IOrderLine> Products { get; private set; }

    public void Add(int quantity, Product product)
    {
        Products.Add(new OrderLine(quantity, product);

        if (product.Quantity < quantity)
        {
            StateChangedAt = DateTime.Now; 
            State = OrderState.WaitingOnStock;
        }
    }
}

So what you basically do is to follow the fundamental OOP principle encapsulation. As a bonus you get all business logic related to the order in one place which greatly simplifies any bug tracking.

I've also blogged about it: http://blog.gauffin.org/2012/06/protect-your-data/

2

I don't think there's going to be some peer reviewed study that you can rely on or a simple empirical model to draw from; even to the extent that such a thing might exist, proving that the data fits your situation might be pretty hard. The fact that such model fitting is so impractical is the reason that business tends to rely so much on surveying "case studies" of what is usually a single company or team that changes practice x to y (or supplier a to b). The narrative fallacy is often at work, but it's one of the few tools that have any sort of traction outside of pseudoscientific neo-Taylorism, because people have an incredibly good pattern matching ability and have an intuition (whether justified or not by other data) whether a given case study has any lesson transferable to their situation. I think this sort of case study dependence can be as intellectually bankrupt as "scientific management" was, but that won't stop people from using them.

The thing to measure really is development friction. You won't be able to predict exactly how a strong domain model can affect velocity, but if you start with an anemic domain model and start encouraging moving more business logic from service layers into the domain layer, and encourage frequent refactoring as you gain a better understanding of the domain, you can at least draw comparisons of velocity (if you're using something like story points to approximately measure task complexity), or customer satisfaction, or fragility of the system, or test coverage, or whatever resonates with your organization.

Based on my experience, I'd guess you'll find some initial hurdles as you start changing practices, as you'll likely have to deal with some nasty side effects and existing technical debt, but that you'll have a long term payoff if you make progressive investments in a real domain layer.

If you're trying to make the case that you need to move away from an anemic domain model, the best thing to do is provide data on what's hard to change now, what customer requests take longer than they should because you have to change code in four different places instead of one, for example. As I frequently argue, the best case for change is identifying the pain points of the existing system; working code will start winning any arguments about whether you're on the right path. Rather than focusing on delivering cost estimates, focus on a narrow scenario that you need to deliver near term business value on, and start attacking the problem by firming up the domain model.

To be case-study-ish without naming specific companies that I've dealt with this problem in, here are some problems that projects I've worked on with anemic domain models had:

  • Duplicated or slightly divergent business logic in multiple layers of the system, not enforced at the domain layer.
  • Poor developer understanding of business rules, because the actual business logic is spread around the system. This alone tends to result in lots of bugs.
  • Slow turnaround time on feature enhancements, or major functional regressions and bugs as a result of new feature work.
  • Unexpected side effects of code changes. (Typically, some bit of code assumes that some other part of the system kicks off some sort of asynchronous process or autonomous transaction, but doesn't have a way of verifying that it occurred, and a new developer doesn't know about this behavior or an existing developer forgets about it).
  • A big divergence between the way developers talk about the system and the way users talk about it, resulting in cognitive friction when trying to make sense of new requirements.
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.