6

I have an interface IMyService in a class library.

I have an implementation of this interface MyService in a separate class library.

MyService may raise a custom exception CustomException.

Should CustomException live in the interface class library, or the implementation class library?

asked Aug 7, 2018 at 8:02
2
  • My own thoughts on this are that the exception should probably live with the implementation, as the exception is most likely an implementation detail. The drawback to that is that you cannot act on specific exceptions within the interface's class library (which in my case is also my "business logic" library). Commented Aug 7, 2018 at 8:11
  • yes, The question goes to the heart of whether exceptions are part of the class deinfition ala java Commented Aug 7, 2018 at 8:29

4 Answers 4

6

This depends on the meaning/context of the exception.

For example, the current project I'm working on uses a BusinessException class. This is used for any explicitly thrown exception with a message (in more layers than just the BLL - I'm aware that the name is misleading). The BusinessException therefore lives in the domain layer (= where IMyService is located).

For those interested, the main reason to use BusinessException is that we allow these exception messages to be returned to the consumer of our web API, whereas all other exceptions get rephrased to "an error has occurred".

One of our business logic classes has a particular UserIsInactiveException. This particular exception is only used as a particular business logic rule (inactive users are not allowed to update data). Therefore, we inherently know that it will only be used on the Business Logic Layer, and therefore it lives in the BLL project (= where MyService is located).

UserIsInactiveException inherits from BusinessException. But the location of the exceptions would be the same regardless of them having an inheritance or not.

My own thoughts on this are that the exception should probably live with the implementation, as the exception is most likely an implementation detail.

What you say isn't incorrect, but it's not universally applicable either. Some exceptions are part of your framework more than they are an implementation detail, for example when your framework is expected to handle certain (custom) exceptions differently.

answered Aug 7, 2018 at 8:38
3

Should CustomException live in the interface class library, or the implementation class library?

Do you anticipate that all implementations of IMyService should support throwing CustomException, or just MyService?

If the former, put it in the interface library, so it's accessible to all implementations.

If the latter, then there's a further decision to be made. Does the rest of the app, save for any code associated with dependency injection, deal solely with IMyService? If so, again you should put it into the interface library, otherwise those other parts of the code must reference the implementation library just to get a reference to the exception.

If the answer is no though, or that implementation library must be referenced for other reasons, put it in the implementation library, so that it's collocated with the class that throws it.

answered Aug 7, 2018 at 8:11
2
  • "Do you anticipate that all implementations of IMyService should support throwing CustomException, or just MyService". Apart from unit testing implementations, yes all implementations will throw the exceptions (there is, as usual, only one implementation). However, C# has no mechanism for enforcing the exceptions that an interface method can throw, which makes it feel like a moot point. Commented Aug 7, 2018 at 8:14
  • @James However, C# has no mechanism for enforcing the exceptions that an interface method can throw, You can implement this indirectly, if you only allow the exception to be created via a method (since you can enforce a method signature via interfaces). So instead of throw new CustomException() you do throw CreateException(). The syntax remains otherwise unchanged (constructor arguments become method parameters) and you can now enforce an exception type. As a quick and dirty example: interface IThrows<TException> where TException : Exception { TException CreateException(); } Commented Aug 7, 2018 at 8:43
3

I'm going to go with "Keep custom exceptions with the implementation rather than the Interface"

By putting the Custom Exceptions in the Interface library you are implying that they are part of the contract that the interface enforces. If C# supported it, you would go further and specify throws on each method like Java.

However, I believe this approach is flawed. It implies that the Custom Exception will be known about by calling code and the only reason for that would be to use them for flow control. A recognised BAD THING(tm)

Furthermore we can easily imagine examples where each implementation would want to expose their own Custom Exceptions.

Consider a IRepository, with implementations Repository_Database and Repository_Files. Both implementations would by their nature want to throw exceptions related to their underlying implementations, "Can't connect to database", "Can't open file" etc

Rather than trying to force these repositories to catch and throw a generic "Cant initiate" exception, which the calling code would then use for flow control, I would add an Open method/ IsOpen property to the repository interface, should this be something that implementations be required to expose.

answered Aug 7, 2018 at 8:41
1
  • That's a good point about flow control. Commented Aug 7, 2018 at 8:59
0

Should CustomException live in the interface class library, or the implementation class library?

Yes of course! If this occurs because it is a common behavior of your process, you must include the exception statement as a comment at the top of the method code. I recommend you include it in the interface. The documentation for your method will look like this:

///<sumary>
/// Method's description
///</sumary>
///<exception cref="CustomException">Occurs when an incident happens</exception>
answered Aug 8, 2018 at 11:51

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.