views:

171

answers:

3

hi,

assume i have a huge input form, which of course representing classes. i need this input to be loaded into the class's instances. this input obviously contains (some very complicated validation) checks, obviously the logic layer contains those input validation already. the question is what am i doing with gui.

should i just, in a very ugly way, just rewrite all those validations in the GUI?

or should i write some statics methods in the logic layer, in use those methods in the gui and in the logic layer, but still creating a duplication of the validating it self (first the gui validate itself, then the logic validate what sent to it)

or should i just assume the gui is okay, surround the relevant code that use the logic layer, with a try block, and then, if exception is thrown, inform the user that SOMETHING is not right (without giving him a chance to know what it is)

or should i expose the exception, in which way i expose to him parameters, classes and namespaces names, which he probably won't understand.

or should i make a special exception class for every single error, and this way inform the user exactly what the problem, but creating maybe hundred of possible exceptions

or should i separate it to general exceptions, which everyone include enum describe the exact content of the error, then catch those exceptions, and by checking the enum inform the user what exactly the problem, but make the app heavier by catching unnecessarily exceptions all the time.

or should i (someone has offered this to me, this isn't my idea, don't shout at me :D) to validate the input in the logic layer, and check it only in the gui (seems to be me absolutely horrible solution :D)

and much more important question - where should i learn such things? usually my instincts are pretty good, but i don't want to unnecessarily invent the wheel.. (i'm pretty sure there already conventions for such basic things you bombed into every day).

thank you very much!

+1  A: 

I've just finished doing a very similar thing in a project at work. I had 3 fairly large forms and a whole lot of classes representing the data that was required. Each class had a bool IsValid() method.

When the user clicks the save button, a method is called which builds up all the classes from the input items on the form. Each property has very simplistic validation (type, default values if not set, etc). Once all the classes are built up (into a tree like structure - one top level class containing a whole lot of other classes), the IsValid method is called on the parent which in turn calls IsValid on all of its children.

If IsValid returns False, the Errors property on the parent is set with the Errors properties of all of its children that failed the IsValid call. I then display the errors in a user friendly view.

However, there were a few instances where I needed to validate certain criteria before the save button was clicked, which I provided methods for on the relevant classes.

I really don't think you should be putting validation in the GUI class at all. Each class should be responsible for its own validation requirements. However, I think it's fine to use the GUI to provide 'hints' to the user on what areas of the form are required, for example using change events to enable or disable parts of the form.

I think, generally, it's a good idea to write all your logic and classes in such a way that you wouldn't require a GUI. What if you wanted to create a console front end instead of a Windows Forms one? You should be able to swap one for the other without changing the business classes you already have.

Josh Smeaton
i know, that's my way of thinking too. but the most important question is.. where do i learn such conventions? usually my instincts are pretty good, but i don't want to unnecessarily invent the wheel.
Itay
+3  A: 

Certainly you should be validating user inputs. If the inputs and validation logic are as complex as you say they are, its even more important to validate the input in the GUI, in a way that makes it obvious to the user what the expected values are, and, if there are any errors, what they are. Bonus points if you can suggest how to fix those errors!

It really doesn't help the user to be seeing exceptions and exception details -- so try to avoid that.

Also, since you're dealing with input validation in the GUI, and bad input is an expectation, and isn't really out of the ordinary, using Exceptions isn't necessarily a good idea. A simple IsValid() method to check whether something is valid or not is preferable. I always follow the rule that states "Exceptions are for Exceptional circumstances".

So if you accept that validation in the GUI is a good thing, then the next question is: How?

You say that you already have a lot of validation in place, but it doesn't sound like your validation logic is available separately. A practice that I've always found useful is to keep the validation code separated from other business logic. That allows you to re-use the validation logic where appropriate, and in this case, would allow you to share the same validation logic between your business objects and the GUI. There are, obviously, many design approaches and frameworks to do this, but the fundamental principle is a "separation of concerns" - keep the validation logic separate, and make it available for use. You seem to be thinking along the same lines when you say "write some statics methods in the logic layer, in use those methods in the gui and in the logic layer", and that's an approach that is proven to work.

Just for clarity's sake -- I'm not suggesting you put the validation logic in the GUI itself. Rather, make the validation logic available to be used by the GUI. The only part of the validation that should be in the GUI is the part that takes the inputs from the user (to submit to validation) and the part that displays the results of the validation (to the user).

Edit:

I don't want to sound like a shill for a particular design philosophy, but lately I've been doing more work using Domain Driven Design principles. I've found it works very well, and it addresses many of the questions you're asking. There are a few questions on SO that give more details on what it is and where some resources are:

http://stackoverflow.com/questions/1353742/domain-driven-design-ddd-readings
http://stackoverflow.com/questions/100995/what-is-domain-driven-design

Also, have a read here: http://www.lostechies.com/blogs/jimmy%5Fbogard/archive/2009/02/15/validation-in-a-ddd-world.aspx

Edit 2:

Also a useful (and related) read: http://stackoverflow.com/questions/88541/business-objects-validation-and-exceptions

Nader Shirazie
that was my preferred option too, but the only disadvantage is that those validate functions would actually be used unnecessarily twice for the same input (from the gui, and then eight away in the logic layer). should i write bool parameter that indicated whether or not to validate the gui? ugliness vs performance...
Itay
Generally the applications I've worked on are server/client. In those cases, indeed in many layered designs, both the service layer and the presentation (GUI) layer are responsible for performing validation (eg, what if a malicious user bypasses validation). If you don't have that problem (eg, suppose its just a GUI app, no physically separated layers), I'd prefer validation in the GUI, where its useful to the user. But if there's any way of bypassing GUI validation, you need it in both places.
Nader Shirazie
As for performance - until you've proved there's a performance problem, don't worry about it. If doing the validation twice doesn't actually cause a problem, do it twice. This is especially true if it leads to a better design / architecture.
Nader Shirazie
A: 

This is an excellent question. The idea of putting validations in the data layer is a classic OO notion, but when the rubber meets the road it can be awkward. I like the idea of putting validation rules for an entity into their own class so that they can be reused; however, there is more to consider.

I generally use a layered approach to data validation, with top layer (the presentation layer) containing the most sophisticated and helpful code. In the middle tier and data tier, validation is focused on validating assertions and throwing exceptions when invalid data is encountered. The idea is that you expect the presentation layer to validate data completely, but in the event that invalid data gets through you want to protect business logic and provide good diagnostics. You definitely don't want to show a raw exception to a user, but it is good to preserve exception information so you can get to it. For example, you can write an exception trace to a log file and/or send it to yourself in an email message and/or display it to the user in the proper context if you think the user can handle it.

When you consider the particulars of data validation, the classic idea of creating an object that "knows" how to validate itself becomes less useful than it first appears. Each layer of validation address somewhat different concerns. Even if the underlying business rules drive the validations across all tiers, the response to invalid data is different depending on the context of the code. The main difference is that, in the presentation layer, you really want to focus on communicating clearly with the user and creating a good user experience in the face of invalid data. It does make sense that this code should be built in to individual screens and controls.

It is definitely advisable to distill simple, atomic business rules into simple functions or constants within classes dedicated to validation. You could also put these rules into static functions on the data layer classes as you suggest. The main thing is to define the validation rules only once. For example, if the application limits a value between 10 and 100, the constants 10 and 100 should appear only once in your code. But these constants, or a simple function that performs the range validation, will be used from multiple validation functions in different tiers.

On a related topic, it is also possible to define validation assemblies full of classes with only validation constants and simple validation functions. These validation assemblies can then be loaded in the SQLCLR and used for database layer validation. In this way the same validation definitions can span the entire system all the way down to the database layer.

Paul Keister