Can you violate the Interface Segregation Principle without violating the Liskov substitution principle? - solid-principles

When reading about ISP, I keep running into examples where a class implementing an interface has a method that throws some type of not-implemented exception. Isn't this also a violation of LSP?
However, if ISP always comes down to cases where you have unsupported methods then you're always violating LSP at the same time making ISP redundant.
I'm guessing I'm missing something, so can someone provide a clear example where you're violating ISP and not violating LSP?
I'm guessing the answer might be related to the exact meaning of "no client should depend on methods it doesn't use". What is meant by client here? Is it a class that implements the interface or a class that has access to an object implementing that interface and may make calls on it?

Related

Application design - When should interfaces be used?

I kind of understand an interface as being a contract that can be applied to classes that would otherwise have nothing in common (ex: Comparable in Java). However, in what situation(s) would you have the reflex of adding an interface at the design stage?
Whenever you are using a statically typed language, and you want to make it possible for the developer to use your code while providing an alternate implementation - in other words, in such language it is necessary to achieve low(er) coupling.
Languages that use ducktyping as a rule, rather than strict type checking, for example, python, would generally have no need for interfaces.
"I kind of understand an interface as being a contract that can be applied to classes that would otherwise have nothing in common" - that's probably not the way to think about what an Interface is.
An Interface describes behaviour, and implementing an interface means a class enters into a contract to deliver that behavior.
By programming to an interface, rather than an implementation, you enable polymorphism and get more flexible code with lower coupling. For example, this method can take any instance that implements IQuack:
public void DoSomething(IQuack quacker)
{
// ...
}
If you are designing a product and you know the product is going to interact with a type of device, service etc. but not necessarily which, you can use an interface to move forward with the overall architecture, PROVIDED that you know enough about those types of devices to write an interface that can be successfully used by any given device of that type. Of course if you are in the design phase, you better have that knowledge. It's not uncommon to do high level designs using only interface declarations. I'm not saying it's good or bad, but it seems to be a pretty common practice of those who use software (like Rose etc) to generate a skeleton from UML.
Another time would be if you know exactly what device you are going to use but you think there might be a chance that you will need to work with different or multiple types of that device down the road.
A third usage of interfaces is to reduce duplicated code. This is probably the only place people ever get carried away with interface usage and if it wasnt for that, I'd be comfortable saying dont ask "Should this be an interface?" but "Can this be an interface?".

Should my persistence class return Option or rely on exceptions?

My application's persistence layer is formed by a Storage trait and an implementing class. I'm vacillating on this issue: should the fetchFoo(key: Key) methods should return Option[Foo], or should they throw FooNotFound exceptions if the key cannot be found?
To add flavour to the issue, the persistence layer - it is written in Scala - is called by Java code. Dealing with scala.Option in Java code? Hmmm.
In fact, until yesterday, the persistence layer was written in Java; I've just re-written it in Scala. As a Java code base, it relied on exceptions rather than returning nulls; but now that I've encountered scala.Option, I'm reconsidering. It seems to me that Scala is less enamoured of exceptions than Java.
My take on the general problem is that it depends on where the keys are coming from.
If they are being entered by some user or untrusted system, then I use Option so I can meaningfully denote the possibility of an unknown key and deal with it appropriately.
On the other hand, if the keys are coming from a known system (this includes things like keys embedded in links that originally came from the system), and are assumed to be valid and exist, I would leave it as a runtime exception, handled by a catch-all at the outer level. For the link example, if someone manually changes the key in a url for one reason or another, it should be considered as undefined behaviour and an exception is appropriate, IMO.
Another way to think of it is how you would handle the situation when it arises. If you're using Option and are just delegating the None case to some catch-all error handling, then an exception is probably more appropriate. If you're explicitly catching the NotFound exception and altering the program flow (eg, asking the user to re-enter the key), then use Option, or a checked exception (or Either in Scala) to ensure that the situation is dealt with.
In relation to integrating with Java, Option is easy enough to use from there once the Scala runtime library is available on the classpath. Alternatively, there's an Option implementation in the Functional Java library. In any case, I would steer clear of using null to indicate "not found".
In Java, you can call Option's isEmpty, isDefined and get without any special hassle (the really useful Option methods, such as getOrElse, are another matter.) Checking the result of the isDefined method in an if-clause should be faster than checking exceptions in a try-catch block.
In some cases (like your example) an Option is fine and the "monadic" behavior (map, flatMap, filter...) very convenient, but in other cases you need more information about the cause of problem, which can be better expressed with an exception. Now you probably want your error handling as "uniform" as possible, so I would suggest to use Either, which gives you both a behavior similar to Option and an expressiveness like an exception.
In Java, you need just a helper function which "unpacks" an Either. If it finds a Right(value), it gives the value back, if it finds a Left(Exception), it re-throws it. After this, your back to normal Java behavior.

Business component with many different types of errors

This is just a general design question. If you are developing a business component or service, (e.g. an object/service that exposes a relatively simple interface for handling billing transactions), what are some good ways to handle business-related errors?
Say the component/service must integrate with a few different external web services that all report back different errors, and must also do some database work on your side. There are many different things that can go wrong, both network/database-wise and business rule-wise. Would it be better to try to catch all types of errors within the component and report them back to the caller using an error-code scheme, or try to wrap all errors into various types of exceptions and throw them on to the caller.
This seems to be a struggle, because it gets awkward to deal with the business rule checks using exceptions, and I've read in several places to avoid using exceptions to control "non-exceptional" or business-logic flows. I feel that "exceptional" is often a debatable term, and it gets sticky trying to keep different cases defined as "exceptional" vs. "non-exceptional." (e.g. if your business logic checks for spending limits, age limitations, etc.). At the same time, using an error-code scheme is also awkward, because the caller might choose to ignore the error codes.
Any tips or references would be appreciated!
I'd go for the error code scheme, because you said "many different things that can go wrong". You might want to have a scheme that returns a List of Error objects, where Error would encapsulate the code, explanation, original data, etc.
An exception can only tell one thing that's wrong, and it should be of an "exceptional" nature, not a run-of-the-mill problem.
Or perhaps a hybrid where you throw an exception that has a List of Error objects as a private data member and an access method that lets you iterate over the errors.
Business related errors should not be exeptions. Exceptions are there if there is an event in the program that the program is not designed to handle or completly unforseen.
To this end, if you anticipate a large number of different exceptions, by all means implement some useful numbering scheme. Here I would recommend a guid for the reason of component reuse. Every component should expose some interface to query the list of possible exception numbers (this can then be added to a data store for documentation). Also as you reuse components, error codes will not conflict.
User or business data errors on the other hand almost warrant some numbering scheme. There is almost no way to anticipate all the silly things a user is capable of. However, I would strongly discourage formal language exceptions in favour of some custom error object. Language exceptions may incur significant overhead, or require specialized handling to prevent them from propogating up the call stack. A business error object may very well be a nice way to go.
Services are borderline, especially if they have to be hit from various languages that may not handle SOAP exceptions properly. There are also security concerns if it's on the WWW.
If it's not a service, is internal, and/or will be accessed by clients in known languages, use exceptions to handle failure conditions. Clients are not guaranteed to check error codes.
See
http://msdn.microsoft.com/en-us/library/ms229030.aspx
for a great discussion of this. (It's also in the book Framework Design Guidelines.)
There's absolutely nothing that could prevent you from making both business rules and technical rules violations exceptions. I'd use exceptions in two cases:
Precondition violation. If your function's specification says "the amount spent should not exceed the limit for this type of account", and user, knowing this, specifies greater limit anyway, throw the exception right into him!
Postcondition violation. If all preconditions are met, but due to unexpected denial (database connection, for example; or completion of the transaction violates anti-monopoly law) you can't supply the correct result, do not supply it. Throw an exception.
Since all business logic probably is within one component and doesn't rely on anything else, case 2 for business exceptions is quite rare. And what falls into case 1 should be checked for in the front-end application. This makes me think that the approach of not throwing business-logic exceptions is not that you "should not do", but likely "you mostly don't need to".
Anyway, from the perspective of the language you're programming, it hardly notices the difference between "technical" and "business" exceptions, so it'll handle them all correctly. Second, exceptions are caught somewhere. I guess, that, from architector's point of view, business and technical exceptions will be caught in the different components. Of course, unless they're effectively uncaught, merely displaying error messages without programmatical handling falls into this category. So the use of the same mechanism won't make you mix these errors.
So, my point is, that if you chose not to repulse exceptions as programming concept, you may use them for business logic as well.

Exceptions and Abstractions

When should you throw a custom exception?
e.g. I have some code that connects to a server. The code that connects to the server throws an IOException when it fails to connect. In the context of the method it's called, this is fine. It's also fine in the network code.
But as this represents not having a connection (and therefore not working) the exception goes all the way up to the ui. At this stage, an IOException is very ambigous. Something like NoConnectionException would be better.
So, my question is:
At what stage should you catch an exception to instead throw another (custom) exception that better fits the abstraction?
I would expect exceptions to talk in terms of what I've asked the originating method to do. e.g.
read -> ReadException
connect -> ConnectException
buildPortfolio -> FailedToBuildPortfolioException
etc. This abstracts away what's going on under the covers (i.e. are you connecting via sockets etc.). As a general rule, when I create an interface for a component, I often create a corresponding exception or set of exceptions. My interface will be called Component, and my exceptions are usually ComponentException (e.g. RateSource and RateSourceException). It's consistent and easy to export to different projects as a complete component set.
The downside is that you create quite a lot of exceptions, and you may have to perform quite a lot of translations. The upside is that (as you've identified) you get little to no abstraction leakage.
At some point during the hierarchy of method calls (and thus exceptions) you may decide that no recovery can take place (or it's at an inappropriate place) and translate to unchecked exceptions to be handled later.
I know this is tagged as "language-agnostic", but I don't think it really is. Coming from a C++ perspective, I expect very few basic operations to throw an exception - the C++ Standard Library only uses exceptions in a very few places. So my own code is often the first place where exceptions can be generated. In that code, I like a very flat hierarchy - I don't want to be messing with hundreds of catch() clauses later in the code, and have never understood Java and C#'s apparent obsession with creating Baroque heirarchies of class and namespace.
So, for my C++ code - one type of exception, containing a meaningful error message, per library. And one for the final executable.
I think there are two questions hidden here:
a) When should one hide an exception behind a different exception.
b) When should one use a custom exception for this.
a) I'd say: when ever an exception travels across the border of two layers in the application, it should get hidden behind an exception that is more apropriate for the new layer.
Example: because you are doing some remote stuff, you get a ConnectionWhatEverException.
But the caller shouldn't be aware of Connection problems. Since he just wants to get some service performed, so he gets a ServiceOutOfOrderException. The reason for this is: Inside the layer, doing remoting, you might to do something usefull with a ConnectionException (retry, write into a backout queue ..). Once you left that layer, nobody knows how to handle a ConnectionException. But they should be able to decide, what do do, when the Service does not work.
b) When there is no matching existing Exception. There are a couple of useful Exception in Java for example. I use IllegalState and IllegalArgument quite often. A strong argument for a new exception class is, if you have some useful context to provide. For example the name of the service that failed could be an argument of a ServiceFailedException. Just don't create a class for every method call, or anything to that effect. 100 Exception classes aren't a problem, as long as they have different behavior (i.e. at least different fields). If they differ only by name and reside on the same abstraction level, make them one Exception, and put the different names in the message or a single field of that exception class.
c) At least in java there is the discussion about checked exceptions. I wrap those directly in an unchecked one, because I hate the checked kind. But that is more an opinion then advice.
Is there any case where you would get NoConnectionException which isn't caused by an IO issue? Conversely, is knowing whether the cause is IO based or not going to help the client recover sensibly?
When should you throw a custom exception?
I. When you can provide more (diagnostic) information.
Note: this additional information may not be available at the place where the original exception (IOException) was thrown. Progressive layers of abstractions may have more information to add like what were you trying to do which led to this exception?
II. When you must not expose implementation details: i.e. you want the (illusion of?) abstraction to continue.
This may be important when the underlying implementation mechanism can change. Wrapping the underlying exception in a custom exception is a good way of insulating your clients from implementation details (by lifting the level of abstraction)
III. Both I and II
NOTE: Furthermore your clients should be able to tune into the exact level of information they are interested in or rather they should be able to tune out anything they are not interested in. So it's a good idea to derive your custom exceptions from IOException.

Should a business rule violation throw an exception?

Should a business rule violation throw an exception?
No. It's part of normal conditional-handling logic in the program (and often just a disguised form of user error).
It depends on what the business rule is, IMO. I would venture to say "not usually" but I'd view it on a case-by-case basis. I don't think there is any one answer, as different business rules might warrant it while others might not.
First, a couple of quotes from chapter 18 of Applied Microsoft .NET Framework Programming (page 402) by Jeffrey Richter:
"Another common misconception is that an 'exception' identifies an 'error'."
"An exception is the violation of a programmatic interface's implicit assumptions."
If I'm inferring correctly from your question that a business rule violation would be data that falls outside a certain range (for example), this is an error that you could handle with a conditional as #ahockley suggested. Based on the definition of an exception from Richter, the appropriate use of an exception would be if your code wasn't able to retrieve a business rule from whatever repository you're using. Being able to retrieve a business rule would be a reasonable implicit assumption for that interface to have, so an exception should be thrown if this assumption was violated.
One good example of Richter's first quote (exception != error) is the ThreadAbortException. If you call Response.Redirect(url) (in ASP.NET), a ThreadAbortException is thrown even though the redirect succeeds. Why? The implicit assumption of ASP.NET page execution is that a page will execute completely. Response.Redirect(url) violates this assumption, hence the exception.
Because of the way I do my validation and my use of LINQtoSQL for ORM, yes. If an entity fails validation on a business rule during the OnValidate method, the only way to notify the calling code is to throw an Exception. In this case, I throw a custom DataValidationException. Using the OnValidate method hook in a partial class implementation of the entity makes it possible for me to enforce validation on update/insert so only valid data gets saved to the database.
EDIT I should make it clear that I typically do validation of user input at the client so the persistence layer validation is typically more insurance and rarely, if ever, fails. I don't handle the client-side validation as exceptions, but rather with conditional logic.
Do you mean, for example, that a value is supposed to be in the range 0-99 but somehow ended up being 105?
If it's coming from the user it's a matter of validation. Whether it is handled using exceptions or not depends on the idioms of your language.
If it's coming from your data store then yes, it seems reasonable to throw an exception. It means you have bad data and you need to figure out how it got there and prevent it from happening again.
No
Violating a business rule is a BUSINESS issue where an exception is a technical one. Violating a business rule is something that the system should regard as normal operation and for which it should have a programmed response, not an exception.
As an alternative view to most of the answers...
It can be useful to throw exceptions from the business logic, particularly if they are cuased by a failure in validation. If you are expecting an object and you get a null, it suggests that some problem has evaded detection in the user interface (or other interface). It may be completely valid to throw exceptions at this point. Indeed, you may decide to place this type of validation in the business logic when there are multiple interfaces.
Throwing exceptions in some languages / frameworks (I am thinking .NET) can be costly but this should not immediately worry you. It does mean that, at the name suggests, they are used for exceptional circumstances and not as part of the standard flow of a program. You certainly shouldn't throw an exception just to exit a method. You should also consider a graceful recovery where possible that may not include throwing an exception.
So, summing up... It depends...
I would say not normally but I don't think you can say never.
For instance it depends on who/what is handling of the failed rule. If it is a user interface/user then I would use conditional logic to deal with the failure appropriately. However if it is a business rule failure in, for instance, a faceless process that logs any errors to an event log which will be monitored by for a technical resource then an exception may be just as appropriate. In this later case an appropriately named exception can be just as helpful as a nicely formatted message.
Business rules could throw exception but they shouldn't.
If you have another way to communicate information about common and predictable validation error, you should use it.
Throwing exceptions can be computationally intensive, they are outside of the norm. For example in .net you have performance counters that are incremented - that is a heavyweight acitivty and so not something you would want to do instead of a simple conditional.
It really depends on what it is and where it is.
If it's some data coming from the user then as levand said it's a matter of validation. Validation can turn up both successful and failed, both are expected options with clear further action scenarios.
If it's something like method execution errors it could be a better idea to throw an exception and stop right there before more harm is done (such as producing inconsistencies in the database).
It is often a matter of perspective and your application design.
Usualy I put the condition in a Specification object that implements
bool IsVerfiedBy(T entity);
So you can check the condition without exception.
If there is a place in your code where the specification should be verified beforehand, you can throw an exception because this is a prerequisit of you function.
For instance if your entity must be in a specific state before persistance, throw an exception when the specification is not verified, but use the specification before persisting so that the exception does not happen.
Business rules should not throw an exception, unless they are used to validate parameters of some API (i.e.: checking requests validity) or in unit tests (i.e.: using business rules to simplify .NET unit tests).
Generally business rules output error and warning messages to the validation scope, though.
There is good guidance in the wiki for the book 97 Things Every Project Manager Should Know, in particular in the chapter Distinguish Business Exceptions from Technical.
So, if your programming language supports it, the best thing is to create custom exception classes so the their workflow and handling can be different from technical exceptions.