Business Objects, Validation And Exceptions

后端 未结 18 917
自闭症患者
自闭症患者 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条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-02 05:39

    It depends on what sort of validation you will be performing and where. I think that each layer of the application can be easily protected from bad data and its too easy to do for it not to be worth it.

    Consider a multi-tiered application and the validation requirements/facilities of each layer. The middle layer, Object, is the one that seems to be up for debate here.

    • Database
      protects itself from an invalid state with column constraints and referential integrity, which will cause the application's database code to throw exceptions

    • Object
      ?

    • ASP.NET/Windows Forms
      protects the form's state (not the object) using validator routines and/or controls without using exceptions (winforms does not ship with validators, but there's an excellent series at msdn describing how to implement them)

    Say you have a table with a list of hotel rooms, and each row has a column for the number of beds called 'beds'. The most sensible data type for that column is an unsigned small integer*. You also have a plain ole object with an Int16* property called 'Beds'. The issue is that you can stick -4555 into an Int16, but when you go to persist the data to a database you're going to get an Exception. Which is fine - my database shouldn't be allowed to say that a hotel room has less than zero beds, because a hotel room can't have less than zero beds.

    * If your database can represent it, but let's assume it can
    * I know you can just use a ushort in C#, but for the purpose of this example, let's assume you can't

    There's some confusion as to whether objects should represent your business entity, or whether they should represent the state of your form. Certainly in ASP.NET and Windows Forms, the form is perfectly capable of handling and validating its own state. If you've got a text box on an ASP.NET form that is going to be used to populate that same Int16 field, you've probably put a RangeValidator control on your page which tests the input before it gets assigned to your object. It prevents you from entering a value less than zero, and probably prevents you from entering a value greater than, say, 30, which hopefully would be enough to cater for the worst flea-infested hostel you can imagine. On postback, you would probably be checking the IsValid property of the page before building your object, thereby preventing your object from ever representing less than zero beds and preventing your setter from ever being called with a value it shouldn't hold.

    But your object is still capable of representing less than zero beds, and again, if you were using the object in a scenario not involving the layers which have validation integrated into them (your form and your DB) you're outta luck.

    Why would you ever be in this scenario? It must be a pretty exceptional set of circumstances! Your setter therefore needs to throw an exception when it receives invalid data. It should never be thrown, but it could be. You could be writing a Windows Form to manage the object to replace the ASP.NET form and forget to validate the range before populating the object. You could be using the object in a scheduled task where there is no user interaction at all, and which saves to a different, but related, area of the database rather than the table which the object maps to. In the latter scenario, your object can enter a state where it is invalid, but you won't know until the results of other operations start to be affected by the invalid value. If you're checking for them and throwing exceptions, that is.

提交回复
热议问题