If you validate something in code you can either work with a return value indicating that something is wrong or you can throw an exception. In my controller I have Exceptional validation like this:
void DoSomething()
{
Validate(); // throws exception if something is wrong
.....
}
I wonder if there is a common naming convention that implies that an exception is thrown when something is wrong so that I don't need to add the comment // throws exception if something is wrong and distinguishes from if (!IsValid())
Note: validation-naming-conventions does not answer my question.
Update after accepting the answer: What I have learned from this Question
AssertValid() or VerifyAndThrow() are good names (tnx #hacktick)
Validation must distinguish with a context (warning or error)
Exceptional Validation is good as a kind of Contract or second line of defense that might exist only in Debug mode to ensure that the surrounding if (IsValid(...)) does not miss something (tnx # Cody Gray)
Typically you would use:
// for a validations that returns just plain yes no (true|false). in the case of a property use caching for the last validationresult.
bool IsValid
// for a validation that returns a list of errors of some sort (messagelist, id list, custom objects, whatever you need).
object Validate();
// validates and throws an exception if one or more error occured.
void ValidateAndThrow();
Also make sure to consider if you need warnings of some kind. For example if you validate your registration DTO model and want to warn a user if the password is weak but do not want to prevent the user from saving it if he chooses to.
Related
I'm not sure if this is limited to Yii2 or if it could be also discussed with other frameworks or even in general.
In Yii2 I can call validate() on a model object. This will return true or false. If it is false I can call getErrors() to see which validation problems currently exist within this object.
Why is this behavior implemented this way? Why does validate() not throw some ValidationExceptions? I find it also somehow strange that errors are part of the model object. Why are they not part of such an exception?
What are the advantages of this implementation? Why is it done this way? I would prefer exceptions. With this, I could better distinguish between desired and exceptional processing. All that is not desired is handled in catch blocks. The desired happens in try blocks. Isn't this a good idea?
Because in general the errors are used in combination with a form.
Let's say you have a form with some input fields (linked to the model attributes/properties) and you want to do something with these fields, maybe save them or something.
Before saving the fields you would like to verify that they are all valid. When the validate() method is called all attributes are validated one by one and each one will generate an error if needed. If the validation is false and you have an error collection you can again show the form, but this time attach the errors to the fields.
If you throw an exception each time an error occurs your application would stop running and only display the one error. Or you would have to write try-catch blocks for all attributes, which is just unnecessary. When your validation returns true you can run the next step which does the processing and you can be sure all values are valid.
If you really want exceptions you can, of course, write your own Validators (http://www.yiiframework.com/doc-2.0/yii-validators-validator.html)
I was reading Uncle Bob book today on Exception handling and what I could recollect from handing null values was that methods should not be handling null values because it clutters the code. I am a little confused with it.
I have always thought that a method should always make sure that it's dependencies are not null (unless they are injected in constructor and constructor assures of nullability).
For example, if I have a method
public void SendMessage(IEmailSender emailSender, contactList list)
{
if(emailSender == null)
{
throw new ArgumentNullException("Failed to send
message.",MethodBase.GetCurrentMethod().GetParameters[0].Name);
}
if(list == null)
{
throw new ArgumentNullException("Failed to send
message.",MethodBase.GetCurrentMethod().GetParameters[1].Name);
}
// rest of code goes here
}
Am I missing something?
There are two perspectives:
On the one hand, with your approach you would always tell the caller what exactly he did wrong by calling your method. Which is great for the caller because he can fix it right away when he gets your exception. This would be true and valid if you where writing API code that is used by a third party.
On the other hand, if you call your method yourself, a reasonable argument to throw an exception is, because you want to be able to handle this situation with a catch block inside your calling code! If you have no reason to handle it somewhere, why throwing an exception at all? The only reason i see is, to have a detailed error logging by catching those exceptions in a GlobalExceptionHandler.
So you see we have two categories of exceptions here: The one for developers, to avoid wrong usage of APIs, and the other one to be used as the method's error-result.
If you are writing API code that will be used by others, your choice would be, not to listen to Bob ;-)
For those who did not read CleanCode, Bob is suggesting two things:
1.You should not write methods that return null (To avoid unnecessary checks afterwards). So Instead of writing this:
var myObject = GetObjectThatDoesSomthing();
if(myObject != null)
{
myObject.DoSomething();
}
... you should be able to write this:
var myObject = GetObjectThatDoesSomething();
myObject.DoSomething();
Cleaner.
2.You should not pass null to your methods to avoid unnecessary checks at the beginning of a method, like here:
public Point Add(Point p1, Point p2)
{
if(p1 == null) throw ArgumentException();
if(p2 == null) throw ArgumentException();
...
}
The point of these rules is: if you stick with it, you know that you dont have to write these null-checks and your code gets cleaner and easier to read. But at the moment you are using third party code, you are not able to tell if they have applied the same rules in their API, so you are starting to pre- or postcheck again. The same thing when you write an API for others: How do the consumers of your API know that you have coded with Bobs rules in mind...
I haven't read the book but I can only imagine that Uncle Bob is advocating the use of the Null Object Pattern in preference to explicit null reference handling.
for example, rather than
if(log != null)
log.Write("My log message");
You could instead create an ILogger interface containing a Write method and create two classes that implement this interface: a NullLogger and a FileLogger. The NullLogger would have an empty body for the Write method's implementation.
In my mind this is different to your explicit pre-condition validation that you have in your example
It depends what type of code are you writing.
If your public method is designed to be used by the wide range of developers non familiar with usage it makes always sense to check parameters and throw a verbose exception.
If you are writing a private method which is only used from the same class or some internal called by another friendly class also written by you or by your collaborator it makes less sense to make paranoia null checks. Your injection design and tests must ensure your internas are not getting null values.
And if private/internal method parameters still get nulls it is anyway too late. Throwing ArgumentNull exception form a private/internal method does not help external user to fix the cause, so it makes no difference for him either to get ArgumentNull or NullReference exception.
Suppose I have a service StateService which has a method ChangeState.
ChangeState(State toState, DomainObject object)
I have business rules that checks whether the destination state is valid or not in the domain objects current "state", how can I technically check those rules without first setting the toState on the domain object? It feels wrong to first set the new state, run validation and if one or more rule breaks unset the state.
One solution I came up with is to create some context object that drives the validation eg.
ChangeStateContext that contains the DomainObject along with the State that is to be set.
Another related question is how to report back from the ChageState call how it went?
I can collect all validation rules that broke and throw an exception with those rules that the caller can catch and handle accordingly or I can add a return type on the ChangeState-method like ValidationSummary that contains information about broken rules and such. What is best practices in these cases?
Can't you throw an exception from the ChangeState method when the state transformation is invalid? You can throw specific exceptions such as StateTransformationException or ValidationException that you can catch higher on the call stack. You can optionally include extra properties to these exception types so that you can communicate very precisely what went wrong to the user.
When you want to call multiple ChangeStates after a single user action, you will need a way to revert or rollback. What I usually do is using the unit of work pattern (supplied to me by LINQ to SQL and Entity Framework) and change all state within this unit of work. When an exception is thrown I throw away the complete unit of work with all its changes.
The DomainObject class could have a public bool CanChangeState(State toState) instance method, returning True if toState is a valid transition from the current state of the subject DomainObject. Such method can be called prior to the StateService.ChangeState call.
Of course, if the StateService is responsible for the state change validation, then a CanChangeState(State toState, DomainObject obj) method should be added to the StateService.
To report back the validation error messages, change the return Type of the CanChangeState to a custom Type responsible for reporting validation errors.
I have a repository data access pattern like so:
IRepository<T>
{
.. query members ..
void Add(T item);
void Remove(T item);
void SaveChanges();
}
Imagine the scenario where I have a repository of users, users have a user name which is unique, if I create a new user with a username that exists (imagine I have a dumb ui layer that doesn't check), when I add it to the repository, all is fine.. when I hit SaveChanges, my repository attempts to save the item to the database, my database is enforcing these rules luckily and throws me back an aborted exception due to a unique key violation.
It seems to me that, generally this validation is done at the layer ABOVE the repository, the layers that call it know they should ensure this rule, and will pre-check and execute (hopefully in some kind of transaction scope to avoid races, but doesn't always seem possible with the medium ignorance that exists).
Shouldn't my repository be enforcing these rules? what happens if my medium is dumb, such as a flat database without any integrity checks?
And if the repository is validating these kind of things, how would they inform callers about the violation in a way that the caller can accurately identify what went wrong, exceptions seem like a poor way to handle this because their relatively expensive and are hard to specialize down to a specific violation..
I've been playing around with a 'Can' pattern, for example.. CanAdd with Add, add will call CanAdd and throw an invalid operation exception if can returns a violation.. CanAdd also returns a list of violations about what went wrong.. this way I can start to stack these routines through the stack.. for example, the service layer above would also have a 'Can' method that would return the repositories report + any additional violations it wanted to check (such as more complicated business rules, such as which users can invoke specific actions).
Validation of data is such a fundamental yet I feel there is no real guidance for how to handle more advanced validation requirements reliably.
Edit, additionally in this case, how do you handle validation of entities that are in the repository and are updated via change tracking.. for example:
using (var repo = ...)
{
var user = repo.GetUser('user_b');
user.Username = 'user_a';
repo.SaveChanges(); // boom!
}
As you could imagine, this will cause an exception.. going deeper down the rabbit hole, imagine I've got a validation system in place when I add the user, and I do something like this:
using (var repo = ...)
{
var newUser = new User('user_c');
repo.Add(newUser); // so far so good.
var otherUser = repo.GetUser('user_b');
otherUser.Username = 'user_c';
repo.SaveChanges(); // boom!
}
In this case, validating when adding the user was pointless, as 'downstream' actions could screw us up anyway, the add validation rule would need to check the actual persistence storage AND any items queued up to persist.
This still doesn't stop the previous change tracking problem.. so now do I start to validate the save changes call? it seems like there would be a huge amount of violations that could happen from aparently unrelated actions.
Perhaps I'm asking for an unrealistic, perfect safety net?
Thanks in advance,
Stephen.
The ideal rule is that each of your layers should be a black box and none of them should depend on validation of another layer. The reason behind this is that the DB has no idea of the UI and vice versa. So when the DB throws an exception, the UI must have DB knowledge (bad thing) to convert that into something the UI layer can understand, so it can eventually convert it into something the user can understand. Ugh.
Unfortunately, making validation on every layer is also hard. My solution: Either put the validation in a single place (maybe the business layer) and make the other layers really dumb. They don't check anything elsewhere.
Or write your validation in an abstract way into the model and then generate all validation from that. For example:
String name;
Description nameDesc = new Description("name",
new MaxLength(20), new NotNull());
This way, you can write code which examines the Description stuff (generate code or even at runtime) and do the validation in each layer with little cost because one change fixes all layers.
[EDIT] For validation, you only have these cases:
Duplicate key
Above some limit
Below some limit
Null (not specified)
Empty
Formatting error (date fields, etc)
So you should be able to get away with these exception classes which have object, field, old&new value plus special info like the limit that was hit. So I'm wondering where your many exception classes come from.
For your other question, this is ... uh ... "solved" by the two phase commit protocol. I say "solved", because there are situations when the protocol breaks down and in my experience, it's much better to give the user a "Retry?" dialog or some other means to fix the problem rather than investing a lot of time into TPC.
Visual Studio Test can check for expected exceptions using the ExpectedException attribute. You can pass in an exception like this:
[TestMethod]
[ExpectedException(typeof(CriticalException))]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
You can also check for the message contained within the ExpectedException like this:
[TestMethod]
[ExpectedException(typeof(CriticalException), "An error occured")]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
But when testing I18N applications I would use a resource file to get that error message (any may even decide to test the different localizations of the error message if I want to, but Visual Studio will not let me do this:
[TestMethod]
[ExpectedException(typeof(CriticalException), MyRes.MultipleOrganisationsNotAllowed)]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
The compiler will give the following error:
An attribute argument must be a
constant expression, typeof expression
or array creation expression of an
attribute
Does anybody know how to test for an exception that has a message from a resource file?
One option I have considered is using custom exception classes, but based on often heard advice such as:
"Do create and throw custom exceptions
if you have an error condition that
can be programmatically handled in a
different way than any other existing
exception. Otherwise, throw one of the
existing exceptions." Source
I'm not expecting to handle the exceptions differently in normal flow (it's a critical exception, so I'm going into panic mode anyway) and I don't think creating an exception for each test case is the right thing to do. Any opinions?
I would recommend using a helper method instead of an attribute. Something like this:
public static class ExceptionAssert
{
public static T Throws<T>(Action action) where T : Exception
{
try
{
action();
}
catch (T ex)
{
return ex;
}
Assert.Fail("Exception of type {0} should be thrown.", typeof(T));
// The compiler doesn't know that Assert.Fail
// will always throw an exception
return null;
}
}
Then you can write your test something like this:
[TestMethod]
public void GetOrganisation_MultipleOrganisations_ThrowsException()
{
OrganizationList organizations = new Organizations();
organizations.Add(new Organization());
organizations.Add(new Organization());
var ex = ExceptionAssert.Throws<CriticalException>(
() => organizations.GetOrganization());
Assert.AreEqual(MyRes.MultipleOrganisationsNotAllowed, ex.Message);
}
This also has the benefit that it verifies that the exception is thrown on the line you were expecting it to be thrown instead of anywhere in your test method.
The ExpectedException Message argument does not match against the message of the exception. Rather this is the message that is printed in the test results if the expected exception did not in fact occur.
Just an opinion, but I would say the error text:
is part of the test, in which case getting it from the resource would be 'wrong' (otherwise you could end up with a consistantly mangled resource), so just update the test when you change the resource (or the test fails)
is not part of the test, and you should only care that it throws the exception.
Note that the first option should let you test multiple languages, given the ability to run with a locale.
As for multiple exceptions, I'm from C++ land, where creating loads and loads of exceptions (to the point of one per 'throw' statement!) in big heirachies is acceptable (if not common), but .Net's metadata system probably doesn't like that, hence that advice.
I think you can just do an explicit try-catch in your test code instead of relying on the ExpectedException attribute to do it for you. Then you can come up with some helper method that will read the resource file and compare the error message to the one that comes with the exception that was caught. (of course if there wasn't an exception then the test case should be considered a fail)
If you switch over to using the very nice xUnit.Net testing library, you can replace [ExpectedException] with something like this:
[Fact]
public void TestException()
{
Exception ex = Record.Exception(() => myClass.DoSomethingExceptional());
// Assert whatever you like about the exception here.
}
I wonder if NUnit is moving down the path away from simplicity... but here you go.
New enhancements (2.4.3 and up?) to the ExpectedException attribute allow you more control on the checks to be performed on the expected Exception via a Handler method. More Details on the official NUnit doc page.. towards the end of the page.
[ExpectedException( Handler="HandlerMethod" )]
public void TestMethod()
{
...
}
public void HandlerMethod( System.Exception ex )
{
...
}
Note: Something doesn't feel right here.. Why are your exceptions messages internationalized.. Are you using exceptions for things that need to be handled or notified to the user. Unless you have a bunch of culturally diverse developers fixing bugs.. you shouldn't be needing this. Exceptions in English or a common accepted language would suffice. But in case you have to have this.. its possible :)
I came across this question while trying to resolve a similar issue on my own. (I'll detail the solution that I settled on below.)
I have to agree with Gishu's comments about internationalizing the exception messages being a code smell.
I had done this initially in my own project so that I could have consistency between the error messages throw by my application and in my unit tests. ie, to only have to define my exception messages in one place and at the time, the Resource file seemed like a sensible place to do this since I was already using it for various labels and strings (and since it made sense to add a reference to it in my test code to verify that those same labels showed in the appropriate places).
At one point I had considered (and tested) using try/catch blocks to avoid the requirement of a constant by the ExpectedException attribute, but this seemed like it would lead to quite a lot of extra code if applied on a large scale.
In the end, the solution that I settled on was to create a static class in my Resource library and store my exception messages in that. This way there's no need to internationalize them (which I'll agree doesn't make sense) and they're made accessible anytime that a resource string would be accessible since they're in the same namespace. (This fits with my desire not to make verifying the exception text a complex process.)
My test code then simply boils down to (pardon the mangling...):
[Test,
ExpectedException(typeof(System.ArgumentException),
ExpectedException=ProductExceptionMessages.DuplicateProductName)]
public void TestCreateDuplicateProduct()
{
_repository.CreateProduct("TestCreateDuplicateProduct");
_repository.CreateProduct("TestCreateDuplicateProduct");
}