Business Objects, Validation And Exceptions

后端 未结 18 854
自闭症患者
自闭症患者 2020-12-02 04:54

I’ve been reading a few questions and answers regarding exceptions and their use. Seems to be a strong opinion that exceptions should be raised only for exception, unhandled

相关标签:
18条回答
  • You want to delve a bit in the remarkable work of Paul Stovell concerning data validation. He summed up his ideas at one time in this article. I happen to share his point of view on the matter, which I implemented in my own libraries.

    Here are, in Paul's words, the cons to throwing exceptions in the setters (based on a sample where a Name property should not be empty) :

    • There may be times where you actually need to have an empty name. For example, as the default value for a "Create an account" form.
    • If you're relying on this to validate any data before saving, you'll miss the cases where the data is already invalid. By that, I mean, if you load an account from the database with an empty name and don't change it, you might not ever know it was invalid.
    • If you aren't using data binding, you have to write a lot of code with try/catch blocks to show these errors to the user. Trying to show errors on the form as the user is filling it out becomes very difficult.
    • I don't like throwing exceptions for non-exceptional things. A user setting the name of an account to "Supercalafragilisticexpialadocious" isn't an exception, it's an error. This is, of course, a personal thing.
    • It makes it very difficult to get a list of all the rules that have been broken. For example, on some websites, you'll see validation messages such as "Name must be entered. Address must be entered. Email must be entered". To display that, you're going to need a lot of try/catch blocks.

    And here are basic rules for an alternative solution :

    1. There is nothing wrong with having an invalid business object, so long as you don't try to persist it.
    2. Any and all broken rules should be retrievable from the business object, so that data binding, as well as your own code, can see if there are errors and handle them appropriately.
    0 讨论(0)
  • 2020-12-02 05:22

    Assuming that you have separate validation and persist (i.e. save to database) code, I would do the following:

    1. The UI should perform validation. Don't throw exceptions here. You can alert the user to errors and prevent the record from being saved.

    2. Your database save code should throw invalid argument exceptions for bad data. It makes sense to do it here, since you cannot proceed with the database write at this point. Ideally this should never happen since the UI should prevent the user from saving, but you still need it to ensure database consistency. Also you might be calling this code from something other than the UI (e.g. batch updates) where there is no UI data validation.

    0 讨论(0)
  • 2020-12-02 05:24

    I my opinion this is an example where throwing an exception is okay. Your property probably does not have any context by which to correct the problem, as such an exception is in order and the calling code should handle the situation, if possible.

    0 讨论(0)
  • 2020-12-02 05:25

    Perhaps you should look at having both client-side and server-side validation. If anything slips past the client-side validation you can then feel free to throw an exception if your business object would be made invalid.

    One approach I've used was to apply custom attributes to business object properties, which described the validation rules. e.g.:

    [MinValue(10), MaxValue(20)]
    public int Value { get; set; }
    

    The attributes can then be processed and used to automatically create both client-side and server-side validation methods, to avoid the problem of duplicating business logic.

    0 讨论(0)
  • 2020-12-02 05:28

    I think it depends on how much your business model is important. If you want to go the DDD way, your model is the most important thing. Therefore, you want it to be in a valid state at all time.

    In my opinion, most people are trying to do too much (communicate with the views, persist to the database, etc.) with the domain objects but sometimes you need more layers and a better separation of concerns i.e., one or more View Models. Then you can apply validation without exceptions on your View Model (the validation could be different for different contexts e.g., web services/web site/etc.) and keep exception validations inside your business model (to keep the model from being corrupted). You would need one (or more) Application Service layer to map your View Model with your Business Model. The business objects should not be polluted with validation attributes often related to specific frameworks e.g., NHibernate Validator.

    0 讨论(0)
  • 2020-12-02 05:29

    You might like to consider the approach taken by the Spring framework. If you're using Java (or .NET), you can use Spring as-is, but even if you're not, you could still use that pattern; you'd just have to write your own implementation of it.

    0 讨论(0)
提交回复
热议问题