Tuesday, June 19, 2007

Domain Driven Design - What's in an Exception Name ?

Colin Jack does not feel that exception names should be part of the domain language. In one of my blog posts, he comments :
I also don't see the exceptions are part of the domain language, instead I see the associated rules as being part of the domain language. So for me the rule name should become part of the domain language but the exceptions do not have to be, its the rules that matter to me when discussing things with the domain experts.

Colin, I have to disagree with you. Here is an example from a real life project (as per your request in my blog comments) and a real discussion session with one of the domain experts.

Here is a snippet from a Capital Market Solutions codebase. The codebase is replete with domain specific terms, as it should be in a domain model implementation, starters (and unstarters) of the capital market domain are requested to look up relevant information for background of the terminologies .. apologies :-(

Class PositionManager is the domain abstraction for managing the Position of an account. Note that Position is the domain term which indicates the balance of the account.


class PositionManager {
  //..
  //..
  void updatePosition(Instrument ins, Date tradeDate,
    BigDecimal amount, TradeType tt, ..) {
    Position currentPosition = getPosition(acc, ins, tradeDate);
    currentPosition.doUpdate(amount, tt);
  }
  //..
}



Now have a look at the method Position#doUpdate invoked above. Here the update is done through a business rule modeled as a Strategy design pattern. The rule can have multiple implementations, hence modeled as an interface. Again we use domain driven principles here to isolate the execution of a process from the rules on which it operates. Note the checked exception which the method catches - ShortPositionException, we will come back to the name in just a moment. Keep reading ..

Here is the definition :


class Position {
  private PositionUpdationStrategy strategy;

  //..
  //..
  void doUpdate(BigDecimal amount, TradeType tt) {
    try {
      strategy.doUpdate(amount, tt);
    } catch (ShortPositionException sbex) {
      //.. handle
    }
  }
  //..
}



The PositionUpdationStrategy is the actual business rule for updating the position of an account and I show the default implementation of the rule.


interface PositionUpdationStrategy {
  void doUpdate(..) throws ShortPositionException;
}



The rule has been modeled purely using the domain language (aka the Ubiquitous Language) and is fairly intuitive to read even by a non-programmer domain guy. Just wear the hat of a domain guy and see if the following codebase sounds domainish.
If the trade is a buy-trade, add to the existing position. If the update results in a short-balance, throw an exception ShortPositionException.

I have highlighted the domain terms above to indicate that the rule implementation is a direct translation of what the domain guy speaks. Colin also agrees to the rule being part of the domain language. Now what about the exception which the rule throws ? We could have named it InsufficientBalanceException and in fact, we did it exactly that way only. Then I was going through a session with one of the domain experts, when he was trying to interpret the correctness of the business rule implementation looking at the codebase. He noted that the short-balance check should ideally raise an exception which indicates that it is related to a short-balance check - once again a part of the domain language. InsufficientBalanceException is too generic a term and should be narrowed to a more fitting domain terminology for the exception here. And thus came the ShortPositionException name, which is part of the Ubiquitous Language. Here is the snippet ..


class DefaultPositionUpdationStrategy
  implements PositionUpdationStrategy {
  //..
  //..

  void doUpdate(BigDecimal amount, TradeType tt)
    throws ShortPositionException {
    if (tt.isBuyTrade()) {
      // add to position
    } else if (isShortBalance(currentPosition, amount)) {
      throw new ShortPositionException(..);
    }
    // subtract from position
  }
}



Look at the interface for the rule, how the checked exception makes the contract much more domain friendly.

17 comments:

Flavio Oliveri said...

I'll try to explain this in english. Sorry but I'm from Argentina and my english is not very good.

The situation of short balance have not to be modeled as an exception. Is a situacion that could happen in the domain. The exceptions are for exceptional things, like illegal states of objects, wrong parameters, etc. So, exceptions named domain oriented, for me, are smell.

Flavio Oliveri said...

In addition...

The InsufficientBalanceException is an example that I use when I teach. That kind of exceptions drives to manage the domain logic inside the specific way of managing errors of the language.

An account with insufficient balance isn't an error, isn't an exception. Is a possibility inside the logic of the domain and have to be modeled like that. An account trying to do something with insufficient money mustn't break sequence with an exeption.

elPablo said...

I have to disagree with you Flavio, I think checked exceptions are the natural way to express conditions that, while unlikely to happen, have to be taken into account when invoking an operation.

Think of the InsufficientBalanceException... how would you let the caller know that there are insufficient funds if you don't throw an exception? Returning null or another flag? That would lead to using ifs to decide the action to take, which, in my opinion, is far uglier than cleanly writting the handler code inside a catch block.

Personally, I prefer using checked exceptions to model exceptional but expected flow of events, and unchecked exceptions for unrecoverable error conditions which the caller code can't do anything to handle.

My 2 cents.
Regards,
Pablo.

Flavio Oliveri said...

Handle exceptional but expected situations inside a catch block never is "clean". Expected things are part of the business, are part of the main flow. In this case, the caller can ask first if the account has money, or can use the Specification pattern, or something else.

Marcos said...

Hi Pablo.

I think Flavio is right. When you model that kind of situation trhowing an exception, you are mixing the logic of what you want to do with the error logic. It's like a controlled goto. In addition... if you first ask if you can do something and then you do it, there's going to appear the method that is modeling the condition and you are going to capture that piece of knowledge for your domain model. You can use SpecialCase or Specification if you don't like ifs.

Regards.

Debasish said...

I am 100% +1 with Pablo. Modeling alternate flows of use cases with checked exceptions is a very much practiced idiom in Java. That is what checked exceptions are for! They make your api s robust and express the intent at a level which is much closer to the domain. In the example that I have cited, the domain expert actually told me that when they have a short-position for an account while processing a trade in the back-office, they flag it as an exceptional condition which needs to be treated in a special way. They need extra authorization from the supervisor to determine if the trade should go through considering other factors like collaterals etc.

Mikhail.Khludnev said...

Hello Debasish

First, I whant to tell you about my apprecation of your blog. It's greate! very informative and useful.

But, I can't agree with you about using checked exception in domain.

Yes, checked exception are made for "modeling alternate flows". But, Do you shure that it are required for this? I belive that "prevent throw by checking" technic (such we use in Iterator) is more suitable in DDD than amazing throwing/catching.

Marcos said...

Debasish:

you are confusing domain error flow with application error flow. What about the error flow of the error flow then?
If the domain expert told you that, then it's not an exceptional condition for you as modeler, it's the way they normally work.

Debasish said...

@Marcos:
In that case how do u plan to handle domain exceptions like ShortBalance during Position Updation? I would like the user to force take specific action when I hit this condition in course of the usecase. And my contract should reveal this - hence typed checked exceptions ..

Jing said...

Debasish,
I agree with you that exceptions, being crucial part of any contract, should be considered part of the domain.
But when it gets to checked vs. unchecked, Here's why I have to disagree with you. :-)

In short, to me, a method throwing a checked exception is dictating its _immediate_ caller, which is kind of making things going backwards.

Cheers.
--
Jing

Gabriel C. said...

I think basically it boils down to what philosophy are you using for exceptions.
I always frowned at using exceptions for control flow (and not sure of the performance implications).
In your example, you get a ShortPositionException because you're violating the contract. AFAIK if you follow DbC, the caller is responsible to ensure the position is not short before calling update if you're not buying.
On the other hand, if the domain speaks of exceptions, I understand trying to follow it as close as possible, but I'm not sure that plain Java is the right language to do it...

Debasish said...

@Jing:
I am not yet a belonger to any specific camp regarding checked exceptions in Java - I am still wondering .. I see that you are quite clear on your camp :-). In this current context, if I would like to force the caller of my api handle the alternate route of the use case as part of the business rule, what alternatives do I have other than checked exceptions ? This is where I vascillate - those typed api s where the client needs to be enforced into handling exceptional routes.

Jing Xue said...

@Debasish
"I would like to force the caller of my api..." that's the philosophy I'm against really :-) - checked exception is just the expression of that philosophy on the surface.

And the reason is very simple - I can't find any software engineering doctrine that says the callee mandating the caller's logical flow is a good thing. Imagine a language where an API can explicitly define rules for its callers like "you must have an alternate flow to deal with my return value if it's 0,1,or 2." That would sound crazy, but it's essentially the same as checked exceptions in Java.

Other languages learned from Java's mistake - C# exceptions are all unchecked, for instance.

Cheers.
--
Jing

Debasish said...

@Jing:
I fully appreciate your point of view and the fact that many languages have learnt from Java's apparent mistake in checked exception design. This is the reason I mentioned in my earlier comment, that I am still looking for the proper camp. People who feel checked exceptions are evil say that it is not according to the doctrine of software engineering to force callers to handle exceptions. But, tell me, one thing - do you consider exceptions to be part of the api ? Or part of the contract ? I do. And hence I feel that callers should also honor the design of the contract and should be forced to handle the exception, which the designer considers as part of his api. Correct me, if I am wrong, but is this also not design by contract ?

Jing Xue said...

@Debasish,

I absolutely agree with you that exceptions are part of the contract. However, IMHO, an API contract should _not_ dictate implementation - either way for that matter. That an exception is part of the contract only goes as far as saying "be _prepared_ to handle this exception," but not "you _must_ handle this exception right here right now."

Again let's use the return value analogy - it's perfectly fine for a contract to say "I might return null so don't be surprised when you see one," but it's rather excessive to say "you must have an if testing my return value and do something differently if it's null."

There are, again IMHO, actually two flaws in Java's exception design. The first one is the checked exceptions themselves, and the second one the complete compile-time ignoring of unchecked ones. Folks who feel checked exceptions are necessary are actually falling victims of the second flaw - there aren't any compile-time support for enforcing contracts including unchecked exceptions, therefore the overly prescriptive alternative must be used.

What Java could have done is to make all exceptions equal, and not to force any exception handling, but instead honor the "throws" declarations, and issue warnings on those aren't handled.

I also realize that you feel stronger urge to enforce exception handling in contracts than I do, because of another philosophical difference - I think things like "insufficient balance" aren't really exceptions, and should be expressed as the status of an account or a transaction in a first-class domain object.

But I guess that's an even finer line to draw, so, another debate for another day... :-)

Cheers.
--
Jing

Debasish said...

@Jing:
"Folks who feel checked exceptions are necessary are actually falling victims of the second flaw - there aren't any compile-time support for enforcing contracts including unchecked exceptions, therefore the overly prescriptive alternative must be used."


I agree to this observation. I have worked in large C++ projects where it was a real pain going through half-baked documentations to find out everything about exceptions. It is an irony that people only lament on the pains of checked exceptions, but totally ignore the pain that is caused by the lack of them. I have been through the second class of sufferings and I know what it takes.

Cheers.

Anonymous said...

情趣用品,情趣用品,情趣用品,情趣用品,情趣,情趣,情趣,情趣,按摩棒,震動按摩棒,微調按摩棒,情趣按摩棒,逼真按摩棒,G點,跳蛋,跳蛋,跳蛋,性感內衣,飛機杯,充氣娃娃,情趣娃娃,角色扮演,性感睡衣,SM,潤滑液,威而柔,香水,精油,芳香精油,自慰套,自慰,性感吊帶襪,吊帶襪,情趣用品加盟AIO交友愛情館,情人歡愉用品,美女視訊,情色交友,視訊交友,辣妹視訊,美女交友,嘟嘟成人網,成人網站,A片,A片下載,免費A片,免費A片下載愛情公寓,情色,舊情人,情色貼圖,情色文學,情色交友,色情聊天室,色情小說,一葉情貼圖片區,情色小說,色情,色情遊戲,情色視訊,情色電影,aio交友愛情館,色情a片,一夜情,辣妹視訊,視訊聊天室,免費視訊聊天,免費視訊,視訊,視訊美女,美女視訊,視訊交友,視訊聊天,免費視訊聊天室,情人視訊網,影音視訊聊天室,視訊交友90739,成人影片,成人交友,美女交友,微風成人,嘟嘟成人網,成人貼圖,成人電影,A片,豆豆聊天室,聊天室,UT聊天室,尋夢園聊天室,男同志聊天室,UT男同志聊天室,聊天室尋夢園,080聊天室,080苗栗人聊天室,6K聊天室,女同志聊天室,小高聊天室,上班族聊天室,080中部人聊天室,同志聊天室,聊天室交友,中部人聊天室,成人聊天室,一夜情聊天室,情色聊天室,寄情築園小遊戲情境坊歡愉用品,情境坊歡愉用品,情趣用品,成人網站,情人節禮物,情人節,AIO交友愛情館,情色,情色貼圖,情色文學,情色交友,色情聊天室,色情小說,七夕情人節,色情,情色電影,色情網站,辣妹視訊,視訊聊天室,情色視訊,免費視訊聊天,美女視訊,視訊美女,美女交友,美女,情色交友,成人交友,自拍,本土自拍,情人視訊網,視訊交友90739,生日禮物,情色論壇,正妹牆,免費A片下載,AV女優,成人影片,色情A片,成人論壇,情趣,免費成人影片,成人電影,成人影城,愛情公寓,成人影片,保險套,舊情人,微風成人,成人,成人遊戲,成人光碟,色情遊戲,跳蛋,按摩棒,一夜情,男同志聊天室,肛交,口交,性交,援交,免費視訊交友,視訊交友,一葉情貼圖片區,性愛,視訊,視訊聊天,A片,A片下載,免費A片,嘟嘟成人網,寄情築園小遊戲,女同志聊天室,免費視訊聊天室,一夜情聊天室,聊天室