S107 — Procedures should not have too many parameters

Language
VB.NET
Type
Code smell
Severity
Major
Tags
brain-overload

Why is this an issue?

Procedures with a long parameter list are difficult to use because maintainers must figure out the role of each parameter and keep track of their position.


Sub SetCoordinates(x1 As Integer, y1 As Integer, z1 As Integer, x2 As Integer, y2 As Integer, z2 As Integer) ' Noncompliant
    ' ...
End Sub

The solution can be to:


' Each function does a part of what the original setCoordinates function was doing, so confusion risks are lower
Sub SetOrigin(x As Integer, y As Integer, z As Integer)
   ' ...
End Sub

Sub SetSize(width As Integer, height As Integer, depth As Integer)
   ' ...
End Sub

Class Point ' In geometry, Point is a logical structure to group data

    Public x As Integer
    Public y As Integer
    Public z As Integer

End Class

Sub SetCoordinates(p1 As Point, p2 As Point)
    ' ...
End Sub

This rule raises an issue when a procedure has more parameters than the provided threshold.

Exceptions

The rule does not count the parameters intended for a base class constructor.

With a maximum number of 4 parameters:


Class BaseClass

    Sub New(Param1 As Integer)
        ' ...
    End Sub

End Class

Class DerivedClass
    Inherits BaseClass

    Public Sub New(Param1 As Integer, Param2 As Integer, Param3 As Integer, Param4 As Integer, Param5 As Long)
    ' Compliant by exception: Param1 is used in the base class constructor, so it does not count in the sum of the parameter list.
        MyBase.New(Param1)
        ' ...
    End Sub

End Class

The rule does not count a parameter that a framework, a dependency injection container, or a runtime binding supplies, because it is not part of the argument list a caller writes. Such a parameter is annotated with one of the following attributes, or with an attribute deriving from one of them:

The remaining parameters are still counted, so an issue is raised when they alone exceed the threshold. With a maximum number of 4 parameters:


Public Class OrderController
    Inherits ControllerBase

    ' Compliant by exception: Service is not counted
    Public Function Create(<FromServices> Service As IOrderService, Param1 As Integer, Param2 As Integer, Param3 As Integer, Param4 As Long) As IActionResult
        ' ...
    End Function

    ' Noncompliant: 5 parameters are supplied by the caller
    Public Function Update(<FromServices> Service As IOrderService, Param1 As Integer, Param2 As Integer, Param3 As Integer, Param4 As Long, Param5 As String) As IActionResult
        ' ...
    End Function

End Class

The rule does not raise on the constructor of a type that a dependency injection container or a framework instantiates, because a caller never writes its argument list.

This is the case for a constructor marked with Microsoft.Extensions.DependencyInjection.ActivatorUtilitiesConstructorAttribute. Only the marked constructor is exempt, and the attribute is not inherited by derived types.

Still with a maximum number of 4 parameters:


Public Class Service

    <ActivatorUtilitiesConstructor>
    Public Sub New(Param1 As Integer, Param2 As Integer, Param3 As Integer, Param4 As Integer, Param5 As Long) ' Compliant by exception
        ' ...
    End Sub

End Class

It is also the case for every constructor of a type annotated with Microsoft.AspNetCore.Mvc.ApiControllerAttribute or Microsoft.AspNetCore.Mvc.ControllerAttribute, and of a type deriving from or implementing one of the following:

Still with a maximum number of 4 parameters:


Public Class HomeController
    Inherits Controller

    Public Sub New(Param1 As Integer, Param2 As Integer, Param3 As Integer, Param4 As Integer, Param5 As Long) ' Compliant by exception
        ' ...
    End Sub

End Class

Two cases fall outside this exception:

↑ Back to top