Question

I know it is expensive but (IMO) I believe it is a very good practice. I'm talking about rules like say, you can't save an Invoice if you are not a sales person... so in that case throwing an exception saying 'your are not authorized' or such...

Another approach it would be having objects with a status or something like that

Is there any other approach? how do you feel about it?

Was it helpful?

Solution

If you mean representing individual business rule checks with exceptions, then I don't think it's a very good idea. Many times you have to report more than one failed condition, and not stop on the first one.

On the other hand, I do believe that checking for all rules and then throwing an exception with the summary is a good practice.

OTHER TIPS

In the example you've given us I think that raising an exception is a bad idea. If you know that the user is not authorized before they start working and you still allow them to do some function and then smack them with an message AFTER they've already completed the task, that's just a bad design.

Using exceptions to enforce business rules is not a good design.

I don't see what value throwing an Exception has in creating good business logic. There are dozens of approaches to handling business logic that do not involve using a system that is meant for addressing unexpected conditions in the operation of a system.

It is expected that in business logic, conditions will not be met; that's the reason for having it in the first place, and you don't want to piggyback on the same mechanism that handles unexpected I/O failures, out of memory errors and null references. Those are failures of the system, but detecting unmet business conditions is the successful operation of the system.

Additionally, it is a system that is ripe for unintended consequences. Because an exception has to be caught at some point, you run the risk of having a new business rule exception ened up being caught somewhere that it's not intended or you chance having the code that looks for business rules catching exceptions that aren't actually meant for it. Yes, these conditions can be accounted for with good coding practices, but in any non-trivial system on which more than one developer is working, mistakes will happen, and you just have to hope that they won't be costly mistakes.

expressing business rules is one thing, implementing them is another

think about the user experience; if the user is not a salesperson, why give them a button that says 'create invoice' at all?

That depends entirely on what's being done.

First, what is the actual behavior you want? If somebody is entering their own information, then a rejection and a dialog box saying, essentially, "You can't do that" is probably correct. If this is a data entry person, working from a pile of forms, a dialog box is probably also good, and the data entry person can put the invalid forms in a special pile. If you're doing batch processing, you don't want to bring things to a halt, but flag it and move to the next.

Once you have the behavior, you need to decide how you're going to implement it. Having a business rules checker that throws an exception is probably a good idea. Returning an return code and having it passed along is something else that can go wrong, and you certainly don't want the erroneous entries getting further.

Don't worry about performance expense. In the case of an individual entering data, it's trivial compared to the other times involved. Typically, the human will take the most time in that system. In the case of a batch job, if exceptions are a performance problem, you're entering far too many bad records, and in reality handling and re-entering all of those is going to be more of a problem than the exceptions.

Having a robust and well designed exception API that is consistent is very appropriate. Using this to enforce business rules can also be appropriate. In fact in my experience, the more complicated the business rule the more likely that it will end up being handled this way. It's often just as easy if not easier to write a system where exceptions are expected than to write authoritative branching logic.

This is to say that simple rules that can be described in a single sentence generally should be implemented in a preventative or authoritative manner depending on which it is. However if you have a rule that is multi-dimensional and requires more than three or four factors (especially if the selection of these factors is based on one or more of the other factors) then exception coding may be more maintainable. Often in these cases the logic path will have many precursor exceptions that need to be thrown, (checks for why the action cannot be performed) then (or vice-versa) there is a fall through to security (to check that the action is authorized), sometimes there will be some authoritative accumulation logic that needs to be checked (descendant/ancestor availability, precursor states that objects must be put into, etc. ) then the logic will fall through to the actual process which may include the more direct authoritative logic checks directly pertinent to the process.

One benefit that derives from this type of exception throwing is that it allows you to separate out and reuse the precursor exceptions across multiple areas of your project. (This is the essence of Aspect Oriented Programming.) By doing this you are encapsulating one particular aspect of your general business rules in a self contained and maintainable component. In general these components will correspond 1-1 with the error messages thrown. (Although sometimes you will have one component that throws several different exceptions, you should almost never have the same exception thrown from multiple components.)

In my opinion it is more difficult to design systems that are exception based the and the initial development time is longer since you have to build the exception process across all N levels. However these system generally end up being much more stable. While it is never possible to design a system that 'will not fail' the benefit of exception based design is that you are always anticipating failure. For most people the process can be counter-intuitive. It's like asking for directions and having someone tell you all the streets that you shouldn't turn on.

Licensed under: CC-BY-SA with attribution
scroll top