Exception type name does not end in Exception

ID

vbnet.maintainability.exception_suffix

Severity

info

Remediation Complexity

trivial

Remediation Risk

medium

Remediation Effort

low

Resource

Naming

Language

VB.NET

Description

Reports a type that derives from an exception type whose own name does not end in Exception - InvalidOrder rather than InvalidOrderException, ShipmentFailure rather than ShipmentFailureException. The base type is recognized from the Inherits clause, so Inherits Exception, Inherits System.Exception, Inherits ApplicationException and Inherits InvalidOperationException all make the declaring type an exception. Names that end in another failure word, such as Error or Failure, are reported as well, because the convention names exactly one suffix. This is a convention rule and is reported at informational severity.

Rationale

Exception types are unusual in that they are almost never read at their declaration - they are read in Catch clauses and in Throw statements, written by developers who did not define them, often while looking at a stack trace rather than at source. The suffix is what makes those places legible: Catch ex As InvalidOrderException states plainly what kind of thing is being handled, while Catch ex As InvalidOrder reads as though a domain object were being caught, and a stack trace or a log line containing Ordering.InvalidOrder gives an on-call reader no signal that it names a failure at all. The suffix is also what makes exception types findable: a developer looking for the failures a component can raise searches for *Exception, and a type without the suffix is invisible to that search and to every code-completion list filtered the same way. A type named OutOfStockError is worse than merely unconventional, because Error in .NET suggests the unrecoverable Error-style conditions of other platforms, and readers coming from Java or JavaScript will draw exactly the wrong conclusion about whether it should be caught.

The following code illustrates the pattern detected by this rule:

Namespace Ordering

    ' BAD: an exception type whose name does not say so.
    ' FLAGGED: Exception type name does not end in Exception
    Public Class InvalidOrder
        Inherits ApplicationException

        Public Sub New(ByVal message As String)
            MyBase.New(message)
        End Sub

Remediation

Rename the type so that it ends in Exception: InvalidOrder becomes InvalidOrderException, ShipmentFailure becomes ShipmentFailureException and OutOfStockError becomes OutOfStockException - drop the competing failure word rather than stacking it, so ErrorException never appears. Use the rename refactoring in the IDE so that every Catch clause, Throw statement and documentation reference is updated in the same step. While renaming, check the rest of the exception contract, which is usually incomplete on a type named this way: derive from Exception rather than the obsolete ApplicationException, provide the three standard constructors - parameterless, message, and message plus inner exception - and mark the type <Serializable> if it can cross an application-domain or process boundary. If the type is not really an exception, do not rename it: make it a plain result or state object and stop deriving from an exception type.

Configuration

This detector does not need any configuration.