I know excpetion handling in actors should in general be done with a supervisor strategy. But is this valid for all cases?
Example
There is one actor which is some kind of database.
There are several source actors which can add data to the database actor.
The parent child relationships of these actors are unknown.
To add data to the database actor the source actors must be registrated at the database actor.
If a not registrated source actors tries to add data to the database an exception is thrown.
If I follow the the error handling strategies of akka actors strictly, a supervising actor would have to handle this case.
I would prefer to catch the exception inside the database actor and send to the source actor a message, that something went wrong. Then the source actor could react (registrate to the database and try again).
Is this a good practice? Or is the total actor setup wrong? If a supervisor strategy is preferred, how should it be implemented?
It's perfectly fine to catch exceptions and make them into responses when you feel it's appropriate. I'd recommend using Scala's Try, as in:
Try(dangerousOperation()) match {
case Success(res) => sender() ! res
case Failure(ex) => sender() ! UnableToStoreThingy("reasons...", ex)
}
Or something like that (you can also try.failed.map { ex => doThings(ex) }), depends on your style preference.
Related
I've came across code with functions which do nothing except check a conditional and throw an exception or do nothing depending on the outcome of the evaluation of the conditional.
The code would look something like this:
public string MyMethod() {
var name = "foo";
EnsureSuccess(name);
return name;
}
// Throws an exception if name is not "bar"
public void EnsureSuccess(string name) {
if (name != "bar")
{
throw new ArgumentException("Not bar!");
}
}
What is this called? Is this a named design pattern?
Also is this considered a good practice or a bad practice?
Example of code in the wild that uses this is the EnsureSuccessStatusCode method in HttpResponseMessage.cs which is part of System.Net.Http by Microsoft. (code, documentation)
That's not a design pattern. It's called programming assertion.
In computer programming, an assertion is a predicate (a true–false
statement) placed in a program to indicate that the developer thinks
that the predicate is always true at that place. If an assertion
evaluates to false at run-time, an assertion failure results, which
typically causes execution to abort.
In addition to the #Chris Eelmaa answer, I'll say that also Don't_repeat_yourself principle is used. Seems that EnsureSuccess(string name) is being used a lot..otherwise I don't see the point of extracting 2 lines of code.
Another interesting thing in the example is not like you pointed
throw new Exception("Not bar!");
But according to the MSDN Best Practices for Exceptions - Don't throw new Exception()
So please note that should be
throw new SpecificException("Not bar!");
Exception is a too broad class, and it's hard to catch without side-effects. Derive your own exception class, but derive it from Exception. This way you could set a specialized exception handler for exceptions thrown by the framework and another for exceptions thrown by yourself.
In the code example they are:
throw new ArgumentOutOfRangeException ();
throw new ArgumentNullException ("......");
throw new HttpRequestException (string.Format ("{0} ({1})", (int) statusCode, ReasonPhrase));
Imagine the code of EnsureSuccess being in-line at MyMethod:
public string MyMethod() {
var name = "foo";
// Ensure success
if (name != "bar")
{
throw new ArgumentException("Not bar!");
}
return name;
}
First, it would require a comment to explain what it's doing. Second, as pointed out before, you'd be repeating this code at every place you need to check this condition.
There's a refactoring (which is like a coding pattern) called extract method that results in what you see here.
Extract method (in this case, 'Don't repeat yourself') is also an example of information hiding, since the details of EnsureSuccess are hidden away in that method. If ever a decision was made to change the logic of how EnsureSuccess works, one only changes the single method, and everywhere that calls the method will not need changing.
It might be Visitor, where you put the functions in a class.
So maybe that class EnsureSuccess would act as some kind of validator.
Maybe this class' jobs are to execute all the exception handlings?
It can also be a Facade pattern.
This pattern is very common used as a validator.
Thank you,
I have the following code:
var s = Observable
.StartAsync(tnk => CERNWebAccess.GetWebResponse(reqUri))
.SelectMany(resp => Observable.StartAsync(tkn => resp.Content.ReadAsStringAsync()))
.Select(ParseToMD);
The ParseToMD is pretty simple:
private static IDocumentMetadata ParseToMD(string marc21XML)
{
return MARC21Parser.ParseForMetadata(marc21XML);
}
Unfortunately, it is quite legal for the ParseForMetadata to throw an exception. I'd very much like to be able to use the normal Rx techniques to deal with the exception. For example:
var goodOrEmpty = s.Catch(Observable.Empty<Tuple<PaperStub, PaperFullInfo>>());
How can I properly protect that Select call so exceptions are correctly turned into IObservable On Error? I'm also going to need to do it for the others (StartAsync).
A pattern I follow is a little different from the standard way of dealing with exceptions. Just because a select throws an exception doesn't necessarily mean the subscription is bad. The next event might be fine.
Note that in RX, when OnError is triggered it means the subscription must be terminated.
What I do is wrap my selects in a monadic Exceptional type to do the following
Exceptional<IDocumentMetadata> s = Observable
.StartAsync(tnk => CERNWebAccess.GetWebResponse(reqUri))
.SelectMany(resp => Observable.StartAsync(tkn => resp.Content.ReadAsStringAsync()))
.SelectExceptional(ParseToMD);
If you just want to skip the bad ones
s.SelectMany(s=>s)
or you can project it like
var Exceptional<ProcessedDocumentType> =
s.Select(document => ProcessDocument(document))
If you need to extract the exception from the Exceptional type you can do this with properties
bool HasException
Exception Exception
To get the value you can access the property
T Value
However you should use Select and SelectMany if you are just operating on the good values and don't need the exceptions.
My implementation was based on
Exception or Either monad in C#
From your comments, I have to wonder if you are seeing the effect of using StartAsync rather than FromAsync. These methods differ in one important detail; the former runs once as soon as it is evaluated - i.e. it runs exactly once regardless of and before any number of subscribers. If there are no subscribers and it throws you will have an unobserved exception. Contrast with FromAsync which is called per subscriber on subscription.
First of all, I know the standard answer will be that exceptions are never to be used for flow control. While I perfectly agree with this, I've been thinking a long time about something I sometimes did, which I'll describe with the following pseudo-code:
try
string keyboardInput = read()
int number = int.parse(keyboardInput)
//the conversion succeeds
if(number >= 1000)
//That's not what I asked for. The message to display to the user
//is already in the catch-block below.
throw new NumberFormatException() //well, there IS something wrong with the number...
catch(NumberFormatException ex) //the user entered text
print("Please enter a valid number below 1000.")
First of all, take this example in a very abstract way. This does not necessarily have to happen. The situation simply is:
A user input needs to be constrained and can go wrong in 2 ways,
either
by a thrown exception the language defines, or by a check. Both errors
are reported by the user in the same way, because they do not need to know
the technical difference of what caused it.
I have thought of several ways to solve it. To begin with, it would be better to throw a custom made exception. The problem I then face is, if I catch it locally, what to do with the other exception? In se, the custom exception would be cause for a second catch-block, in which the message would be copied into just as well. My solution:
//number is wrong
throw new MyException()
catch(NumberFormatException ex)
throw new MyException()
catch(MyException ex) {
print("Please enter...")
The meaning of the exceptions' names is everything here. This application of custom-made exceptions is widely accepted, but essentially I didn't do anything different from the first way: I forced to go into a catch-block, albeit by throwing a custom exception rather than a standard-library one.
The same way applied to throwing the exception on to the calling method (thus not having a catch block for the custom exception) seems to make more sense. My method can go wrong in what is technically two ways, but essentially one way: wrong user input. Therefore, one would write a UserInputException and make the method throw this. New problem: what if this is the main method of an application?
I'm not currently struggling with a specific application to implement this kind of behaviour, my question is purely theoretical and non-language specific.
What is the best way to approach this?
I would consider the first exception to be low-level, and I would handle it (by translation in this case) at the point of call. I find that this leads to code that is easier to maintain and refactor later, as you have less types of exceptions to handle.
try
string keyboardInput = read()
try
int number = int.parse(keyboardInput)
catch(NumberFormatException ex)
throw MyException("Input value was not a number")
//the conversion succeeds
if(number >= 1000)
throw MyException("Input value was out of range")
catch(MyException ex) //the user entered text
print( ex.ToString() )
print("Please enter a valid number below 1000.")
I think you have essentially a few ways to go about it with minimal code duplication in mind:
Use a boolean variable/store the exception: If there was an error anywhere in the the general logic of the specific task you are performing, you exit on the first sign of error and handle that in a separate error handling branch.
Advantages: only one place to handle the error; you can use any custom exception/error condition you like.
Disadvantages: the logic of what you are trying to achieve might be hard to discover.
Create a general function that you can use to inform the user about the error (pre-calculating/storing all information that describes the general error, e.g. the message to display the user), so you can just make one function call when an error condition happens.
Advantages: the logic of your intent might be clearer for readers of the code; you can use anu custom exception/error conditon you like.
Disadvantages: the error will have to be handled in separate places (although with the pre-computed/stored values, there is not much copy-paste, however complex the informing the user part).
If the intent is clear, I don't think throwing exceptions from within your try block explicitly is a bad idea. If you do not want to throw one of the system provided exceptions, you can always create your own that derives from one of them, so you only need a minimal number (preferably one) of catch blocks.
Advantages: only one place to handle error condition -- if there is essentially only one type of exception thrown in try-block.
Disadvantages: if more than one type of exception is thrown, you need nested try-catch blocks (to propagate the exceptions to the most outward one) or a very general (e.g. Exception) catch block to avoid having to duplicate error reporting.
The way I see it is this:
Assuming there's no other way to parse your int that doesn't throw an exception, your code as it is now, is correct and elegant.
The only issue would be if your code was in some kind of loop, in which case you might worry about the overhead of throwing and catching unnecessary exceptions. In that case, you will have to compromise some of your code's beauty in favor of only handling exceptions whenever necessary.
error=false;
try {
string keyboardInput = read();
int number = int.parse(keyboardInput);
//the conversion succeeds
if(number >= 1000) {
//That's not what I asked for. The message to display to the user
//is already in the catch-block below.
error=true;
} catch(NumberFormatException ex) { //the user entered text
error=true;
}
if (error)
print("Please enter a valid number below 1000.");
Also you can think about why you're trying to aggregate two errors into one.
Instead you could inform the user as to what error they did, which might be more helpful in some cases:
try {
string keyboardInput = read();
int number = int.parse(keyboardInput);
//the conversion succeeds
if(number >= 1000) {
//That's not what I asked for. The message to display to the user
//is already in the catch-block below.
print("Please enter a number below 1000.");
} catch(NumberFormatException ex) { //the user entered text
print("Please enter a valid number.");
}
You do not need any exceptions in this particular example.
int number;
if (int.TryParse(keyboardInput, out number) && number < 1000) // success
else // error
However, the situation you describe is common in business software, and throwing an exception to reach a uniform handler is quite common.
One such pattern is XML validation followed by XSLT. In some systems, invalid XML is handled through catching validation exceptions. In these systems, it is pretty natural to reuse the existing exception handling in XSLT (which can naturally detect some classes of data errors that a particular validation language cannot):
<xsl:if test="#required = 'yes' and #prohibited = 'yes'>
<xsl:message terminate='yes'>Error message</xsl:message>
</xsl:if>
It is important to see that if such conditions are extremely rare (expected to occur only during early integration testing, and disappear as defects in other modules get fixed), most of the typical concerns around not using exceptions for flow control do not really apply.
What about approaching this validation problem by writing several validator classes that take in an input and return errors, or no errors. As far as your struggle with exceptions: put that logic into each validator and deal with it there on a case by case basis.
after that you figure out the correct validators to use for your input, collect their errors and handle them.
the benefits of this are:
Validators do one thing, validate a single case
Its up to the validation function to decide how to handle the errors. Do you break on first validation error or do you collect them all and then deal with them?
You can write your code is such a way that the main validation function can validate different types of input using the same code, just picking the correct validators using your favorite technique.
and disadvantages:
You will end up writing more code (but if you are using java, this should be put into the 'benefits' bucket)
here is some example pseudo-code:
validate(input):
validators = Validator.for(input.type)
errors = []
for validator in validators:
errors.push(validator.validate(input))
if errors:
throw PoopException
and some validators:
MaxValidator extends IntValidator:
validate(input):
errors = []
errors.push(super.validate(input))
if input > 1000:
errors.push("bleee!!!! to big!")
return errors
IntValidator:
validate(input):
try:
int.parse(input)
catch NumberFormatException:
return ['not an int']
return []
of course you would need to do some trickery to make the parent validator possibly return you a valid version of the input, in this case string "123" converted to an int so the max validator can handle it, but this can be easily accomplished by making the validators statefull or some other magic.
I can't see this answer anywhere in here, so I'll just post it as another point of view.
As we all know, you can actually break the rules if you know them well enough, so you can use throwing an Exception for flow control if you know it's the best solution for your situation. From what I've seen, it happens usually with some dumb frameworks...
That said, before Java 7 (which brought us the mighty multicatch construct), this was my approach to avoid code repetition:
try {
someOffendingMethod();
} catch (Exception e) {
if (e instanceof NumberFormatException || e instanceof MyException) {
System.out.println("Please enter a valid number.");
}
}
It's a valid technique in C#, too.
Suppose I have a method
public Patient(int id)
{
----
}
that returns Patient object given an id.. I could define contract in 2 ways
Method would return null if patient does not exist
Method would throw an exception if patient does not exist. In this case I would also define a query method that returns true if the Patient exist in the database or false otherwise...
Which contract should I use? Any other suggestions?
Update: Please comment on this case too...
If it is not an database assigned Id and it is something a user enter in UI.. like SSN .. then which one is better..
Comment about Null pattern from Steve that I think is valid:
probably not a good idea here, as it would be really useful to know immediately when an ID did not exist.
And I also think Null pattern here would be somewhat heavy weight
Comment from Rob Wells on throwing exception because its bad Id:
i don't think a typo in a patient's name is an exceptional circumstance" IMHO
Keep in mind that going "over the wire" to another tier (whether a database or an application server) is one of the most expensive activities you can do - typically a network call will take several orders of magnitude longer than in-memory calls.
It's therefore worth while structuring your API to avoid redundant calls.
Consider, if your API is like this:
// Check to see if a given patient exists
public bool PatientExists(int id);
// Load the specified patient; throws exception if not found
public Patient GetPatient(int id);
Then you are likely to hit the database twice - or to be reliant on good caching to avoid this.
Another consideration is this: In some places your code may have a "known-good" id, in other places not. Each location requires a different policy on whether an exception should be thrown.
Here's a pattern that I've used to good effect in the past - have two methods:
// Load the specified patient; throws exception if not found
public Patient GetExistingPatient(int id);
// Search for the specified patient; returns null if not found
public Patient FindPatient(int id);
Clearly, GetExistingPatient() can be built by calling FindPatient().
This allows your calling code to get the appropriate behaviour, throwing an exception if something has gone wrong, and avoiding exception handling in cases where it is not needed.
Another option would be the Null Object pattern.
You should probably throw an exception. If you have an id that doesn't point to a valid patient, where did it come from? Something very bad has likely happened. It is an exceptional circumstance.
EDIT: If you're doing something other than an integer-based retrieval, like a search based on text, then returning null is fine. Especially since in that case you are returning a set of results, which could be more than one (more than one patient with the same name, same birth date, or whatever your criteria is).
A search function should have a different contract from a retrieval function.
It depends:
If you consider the normal operation will lead to a pation number not matching a file in the DB then an empty (NULL) record should be returned.
But if you expect that a given ID should always hit a record then when one is not found (which should be rare) then use an exception.
Other things like a DB connection error should generate an exception.
As you expect under normal situations the query to the DB to always work (though it may return 0 records or not).
P.S. I would not return a pointer. (Who owns the pointer??)
I would return an object that may or may not have the record. But that you can interogated for the existance of the record within. Potentially a smart pointer or somthing slightly smarter than a smart pointer that understands the cotext.
For this circumstance, I would have the method return null for a non-existent patient.
I tend to prefer using exceptions to assist graeful degradation when there is a problem with the system itself.
In this instance, it is mosdt probably:
a typo in the patient's ID if it was entered into a search form,
a data entry error, or
a workflow issue in that he patient's record hasn't been entered yet.
Hence, returning a null rather than an exception.
If there was a problem contacting the database, then I would have the method raise an exception.
Edit: Just saw that the patient ID in the signature was an integer, thanks Steven Lowe, so I've corrected my list of reasons.
My basic point about delineating when to use exceptions (for system errors) versus other methods of returning an error (for simple data entry typos) still stands though. IMHO.
HTH
cheers,
Rob
In a simple situation like this 1. seems to be more than sufficient. You may want to implement something like a callback method that the client calls to know why it returned null. Just a suggestion.
taking your descriptiong at face value, you probably need both:
bad IDs are errors/exceptions, as Adam pointed out, but
if you are given IDs elsewhere that might have disappeared, you will need the query method to check for them
Assuming I read that correctly...
When you call Patient(100) it will return an object reference for a Patient with an id of 100.
If no patient with an id of 100 exists, I think it should return null. Exceptions are overused IMO and this case doesn't call for it. The function simply returned a null. It didn't create some errored case that can crash your application (unless of course, you ended up not handling that null and passed it around to some other part of your application).
I would definitely have that function return 'null', especially if it was part of some search, where a user would search for a patient with a particular ID and if the object reference ended up being null, it would simply state that no patient with that id exists.
Throw an exception.
If you return null, code like this:
Console.WriteLine(Patient(id).Name);
would fail with a NullReferenceException if the id doesn't exist, which is not as helpful as a say a PatientNotFoundException(id). In this example, it's still relatively easy to track down, but consider:
somePatient = Patient(id)
// much later, in a different function:
Console.WriteLine(somePatient);
About adding a function that checks whether a patient exists: Note this won't prevent PatientNotFoundExceptions completely. For example:
if (PatientExists(id))
Console.WriteLine(Patient(id).Name);
-- another thread or another process could delete the patient between the calls to PatientExists and Patient. Also, this would mean two database queries instead of one. Usually, it's better to just try the call, and handle the exception.
Note that the situation is different for queries that return multiple values, e.g. as a list; here, it is appropriate to return an empty list if there are no matches.
I know two approaches to Exception handling, lets have a look at them.
Contract approach.
When a method does not do what it says it will do in the method header, it will throw an exception. Thus the method "promises" that it will do the operation, and if it fails for some reason, it will throw an exception.
Exceptional approach.
Only throw exceptions when something truly weird happens. You should not use exceptions when you can resolve the situation with normal control flow (If statements). You don't use Exceptions for control flow, as you might in the contract approach.
Lets use both approaches in different cases:
We have a Customer class that has a method called OrderProduct.
contract approach:
class Customer
{
public void OrderProduct(Product product)
{
if((m_credit - product.Price) < 0)
throw new NoCreditException("Not enough credit!");
// do stuff
}
}
exceptional approach:
class Customer
{
public bool OrderProduct(Product product)
{
if((m_credit - product.Price) < 0)
return false;
// do stuff
return true;
}
}
if !(customer.OrderProduct(product))
Console.WriteLine("Not enough credit!");
else
// go on with your life
Here I prefer the exceptional approach, as it is not truly Exceptional that a customer has no money assuming he did not win the lottery.
But here is a situation I err on the contract style.
Exceptional:
class CarController
{
// returns null if car creation failed.
public Car CreateCar(string model)
{
// something went wrong, wrong model
return null;
}
}
When I call a method called CreateCar, I damn wel expect a Car instance instead of some lousy null pointer, which can ravage my running code a dozen lines later. Thus I prefer contract to this one:
class CarController
{
public Car CreateCar(string model)
{
// something went wrong, wrong model
throw new CarModelNotKnownException("Model unkown");
return new Car();
}
}
Which do style do you use? What do you think is best general approach to Exceptions?
I favor what you call the "contract" approach. Returning nulls or other special values to indicate errors isn't necessary in a language that supports exceptions. I find it much easier to understand code when it doesn't have a bunch of "if (result == NULL)" or "if (result == -1)" clauses mixed in with what could be very simple, straightforward logic.
My usual approach is to use contract to handle any kind of error due to "client" invocation, that is, due to an external error (i.e ArgumentNullException).
Every error on the arguments is not handled. An exception is raised and the "client" is in charge of handling it. On the other hand, for internal errors always try to correct them (as if you can't get a database connection for some reason) and only if you can't handle it reraise the exception.
It's important to keep in mind that most unhandled exception at such level will not be able to be handled by the client anyway so they will just probably go up to the most general exception handler, so if such an exception occurs you are probably FUBAR anyway.
I believe that if you are building a class which will be used by an external program (or will be reused by other programs) then you should use the contract approach. A good example of this is an API of any kind.
If you are actually interested in exceptions and want to think about how to use them to construct robust systems, consider reading Making reliable distributed systems in the presence of software errors.
Both approaches are right. What that means is that a contract should be written in such a way as to specify for all cases that are not truly exceptional a behavior that does not require throwing an exception.
Note that some situations may or may not be exceptional based upon what the caller of the code is expecting. If the caller is expecting that a dictionary will contain a certain item, and absence of that item would indicate a severe problem, then failure to find the item is an exceptional condition and should cause an exception to be thrown. If, however, the caller doesn't really know if an item exists, and is equally prepared to handle its presence or its absence, then absence of the item would be an expected condition and should not cause an exception. The best way to handle such variations in caller expectation is to have a contract specify two methods: a DoSomething method and a TryDoSomething method, e.g.
TValue GetValue(TKey Key);
bool TryGetValue(TKey Key, ref TValue value);
Note that, while the standard 'try' pattern is as illustrated above, some alternatives may also be helpful if one is designing an interface which produces items:
// In case of failure, set ok false and return default<TValue>.
TValue TryGetResult(ref bool ok, TParam param);
// In case of failure, indicate particular problem in GetKeyErrorInfo
// and return default<TValue>.
TValue TryGetResult(ref GetKeyErrorInfo errorInfo, ref TParam param);
Note that using something like the normal TryGetResult pattern within an interface will make the interface invariant with respect to the result type; using one of the patterns above will allow the interface to be covariant with respect to the result type. Also, it will allow the result to be used in a 'var' declaration:
var myThingResult = myThing.TryGetSomeValue(ref ok, whatever);
if (ok) { do_whatever }
Not quite the standard approach, but in some cases the advantages may justify it.