In 1964 Abraham Kaplan said: “Give a small boy a hammer, and he will find that everything he encounters needs pounding”.
Another famous version of this is known as Maslow’s hammer, and it goes like this: “if all you have is a hammer, everything looks like a nail”.
This post is about how every time there’s a new tool, new approach or an old idea made new in software, it becomes like a hammer in a small boy’s hands. And it will be used to pound on everything.
Read on for a few examples:
IoC Containers
If you write code that conforms to the Dependency Inversion Principle then it means that your classes do not depend on other concrete classes, they depend on abstractions, for example:
public class MyClass
{
private readonly IDependency1 _dependency1;
private readonly IDependency2 _dependency2;
private readonly IDependency3 _dependency3;
public MyClass(IDepdendency1 dependency1, IDependency2 dependency2, IDependency3 dependency3)
{
_dependency1 = dependency1;
_dependency2 = dependency2;
_dependency3 = dependency3;
}
//...
}
Creating an instance of this class “by hand” is a pain, you have to instantiate all of it’s dependencies:
MyClass myClass = new MyClass(new Dependency1(...), new Dependency2(...), new Dependency3(...));
An IoC container solves this problem, when you ask it for MyClass
it will get you an instance of MyClass
with all its dependencies instantiated. To do this it only needs you to specify rules for how to instantiate IDependency1
, IDependency2
and IDependency3
. For example in StructureMap for IDependency1
it would be something like this:
For<IDependency>().Use<Dpendency1>();
The neat thing about this is that if Dependency1
has dependencies of its own, the IoC container will resolve them for you.
This is the problem that IoC containers solve. It is intimately related to the Dependency Inversion Principle and constructor injection.
To tie all of this up frameworks provide some mechanism to create types that you can extend and plug in your favourite IoC container. For example in ASP.NET MVC there’s an interface you can implement named IDependencyResolver with a method named GetService(Type type)
that gets called when a Controller
needs to be created. An implementation of it looks something like this:
public object GetService(Type type){
return YourFavoriteIoCContainer.Resolve(type);
}
Is this how IoC containers are used? No, what you frequently see instead is what is known as the service locator pattern. The above example usually looks like:
public class MyClass
{
private readonly IDependency1 _dependency1;
private readonly IDependency2 _dependency2;
private readonly IDependency3 _dependency3;
public MyClass()
{
_dependency1 = IoCContainer.Resolve<IDependency1>();
_dependency2 = IoCContainer.Resolve<IDependency2>();
_dependency3 = IoCContainer.Resolve<IDependency3>()
}
//...
}
Usually the calls to the IoC container are spread all over the place, not only in the constructor.
So what is the problem of doing this? First, that code depends on a particular IoC container, so if you want to share it with someone that is using another IoC container then tough luck.
Second, you need the IoC container to instantiate that type, it won’t work without it. This becomes glaringly obvious when you find a code base where the unit tests need an IoC container to run.
It seems that the reasoning for using IoC containers was: “it’s a new thing we should all use, you should never new
up things in your code, so replace them all with IoCContainer.Resolve
, problem solved”.
There are also other more creative uses of IoC containers. When they were the new big thing it was easy to find code that would use them in conditional statements. For example, imagine you need to create different word documents, and you decide which to create through an IoC container:
IDocumentCreator documentCreator;
if (templateToUse == "Letter")
{
documentCreator = IoCContainer.Resolve<IDocumentCreator>("letterTemplate");
}else if (templateToUse == "Book"){
documentCreator = IoCContainer.Resolve<IDocumentCreator>("bookTemplate");
}
documentCreator.CreateDocument(...);
Most IoC containers allow you to specify a “named mapping”, i.e. you can create a rule that says when IType
is requested with name “A” resolve with TypeX
, when requested with name “B” resolve with TypeY
.
IoC containers were not designed with this type of scenario in mind, so much so that the above approach has the serious limitation of requiring a new if
statement and a new IoC mapping every time a new template type is added.
Generics
In .Net generics where introduced in version 2.0 of the framework. Before generics were introduced every time you used a collection, for example a List
, you would add its elements as type object
and when you wanted to retrieve them you would have to cast them to their original type (or a base class of that type).
For example:
ArrayList numbers = new ArrayList();
numbers.Add(1);
numbers.Add(2);
int firstNumber = (int)numbers[0];
The example above also illustrates what happened with value types. They had to be “boxed” and “unboxed”, which crudely means that the value types would have to be converted to object
(boxed) and be allocated in the heap, and when they were retrieved they had to be converted back to their original value type (unboxed) and that process was slow and lead to more garbage collections.
Generics solved this problem, no more casting for your data-structures and no more boxing and unboxing of value types.
A creative use of generics that somehow became popular is their use “to define dependencies”. In .Net it is possible to define constraints on the generic type, for example:
public class MyClass<T> where T: new(), IType
{
//...
}
The where T: new(), IType
means that type T needs to provide a parameterless constructor and implement IType
.
This allows someone to write in a method of MyClass<T>
:
public void SomeMethod()
{
T t = new T();
t.DoSomething(); //DoSomething is a method that interface IType defines
}
Instead of this IType
could be passed as a parameter in MyClass
‘s constructor. There’s absolutely no advantages in doing this with generics.
A sure sign that this is happening is if you generic type does not have any method returning any generic parameter.
Code regions
Code regions were a mechanism to delimit code that was generated by a tool (usually a visual designer) and therefore should not be touched. Before .Net had partial classes, if you’d create a Windows Forms application and opened the main Form you’d see something like this:
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//...
}
#endregion
And you would know that if you changed any of the code in the region you would lose it as soon as you made any changes in the designer.
Somehow regions become a popular way to organize code. Is your class too long? No problem just organize the code in different regions:
#region Helpers
...
#endregion
#region Managers
...
#endregion
...
I purposely named the regions Helpers
and Managers
. Two names that have no place in object oriented programming unless you are writing an application about football or something that needs a helper (can’t remember of any).
Also, here’s an interesting article about the more general idea of “code folding” being a design error.
Partial classes
Partial classes are a more elegant way to deal with generated code. Instead of putting it all in a region on the same file that you have to edit, put the generated part in a different file and let the compiler deal with putting it all together.
There’s no good reason for using partial classes if one of the partials is not generated code, but somehow partial classes became a way to deal with classes that become too big.
I’ve seen much of this in ASP.NET MVC where when controllers become too big, they are split up in partials, where each partial has a descriptive name, for example:
File: BookController_Retrieve.cs
public partial class BookController: Controller
{
//action methods related to retrieving books
}
File: BookController_Storing.cs
public partial class BookController: Controller
{
//action methods related to saving books
}
There’s no good reason for using partials like this. The tragedy is that some of the visual studio templates use partial classes this way, if you create a new ASP.NET MVC application and select Individual User Accounts, the project is initialised with a Startup.cs with several partials.
Unit testing
The idea behind creating unit tests, and having an automated way of testing your code in general, is that you can find problems with your code without having to test it manually.
For all of this to work the tests have to follow certain rules. For example, they have to be written in a way that their execution order does not change their outcome. A very common problem is to find code bases where the unit tests share state, so they might not run if you change the order they are executed in.
In unit testing you are supposed to execute some code and verify if your expectations about that code are verified. There’s even a popular pattern for writing unit tests named “Arrange Act Assert” where you write some code to setup the state you want to test, call a method, and verify the result of calling that method.
The verification part, for some reason, is very frequently neglected. The reason for that is that a test will pass if no exception is thrown and virtually all testing frameworks provide asserting mechanisms that when fail throw an exception, here’s an example:
[Test]
public void SomeMethod_SomeStateToTest_ExpectedResult()
{
SomeClass c = new SomeClass();
c.DoSomething();
}
The only way this test will fail is if an exception is thrown.
Another, slightly more elaborate version of this, but nearly as useless, is to just check if the return value is not null, for example:
[Test]
public void SomeMethod_SomeStateToTest_ExpectedResult()
{
SomeClass c = new SomeClass();
var result = c.DoSomething();
Assert.IsNotNull(result);
}
There are also other more creative uses for unit tests. Because the tooling makes it easy to run the tests with a click of a button they are sometimes used to populate databases using ORMs, for example:
[Test]
public void PopulateDatabase()
{
var c = new EntitiesContext();
c.Table.AddOrUpdate(...);
c.Table.AddOrUpdate(...);
c.Table.AddOrUpdate(...);
}
Conclusion
I don’t really have an explanation for why this is so prevalent in the software industry, maybe it’s because it’s dominated by men and everybody knows that “real men don’t read the instructions”.
Maybe technology, because it evolves so quickly, is frequently learned by word of mouth, and this process becomes a little bit like that game of Chinese whispers where details are lost along the way.
How about you dear reader? Do you think this just happens in software, or do you think other areas have their own version of “The daily WTF”? Have you seen some creative use for some tool/technology that completely misses the point? Please share in the comments!