I recently had the following bug in my code which took me for ever to debug. I wanted to inject an instance based on its interface like this:
MovementController(IMotorController motorController)
However I accidentally used the concrete type like this:
MovementController(MotorController motorController)
The project still built and ran fine until I tried to access the motorController
from the MovementController
instance. Since the underlying implementation of IMotorController
accesses hardware, it has to be a singleton or my locks code. However, since I had other classes with the injected IMotorController
, I now had two instances MotorController
in my object-graph, which both accessed the hardware over a serial connection. This caused an error, at run time at a much lower level, which took me forever to debug and find the true cause.
How can I avoid this type of bug or write a unit test for my StructureMap registry to catch this subtle bug?
You could easily check for this using a static analysis tool like NDepend. With it you would just look for types that were controllers and then inspect their constructors and warn if you found any constructor parameters that were not interface types.
Just to refine the Steve answer, you could write a code rule that could look like: (with NDepend a code rule is a C# LINQ query prefixed with warnif count > 0
)
// <Name>Don't use MotorController, use IMotorController instead</Name>
warnif count > 0
from m in Application.Methods
where m.IsUsing ("NamespaceA.MotorController ") &&
m.ParentType.FullName != "NamespaceB.ClassThatCanUseMotorController "
select m
The rule can be refined easily if there are zero or many ClassThatCanUseMotorController
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With