Showing posts with label Duplication. Show all posts
Showing posts with label Duplication. Show all posts

Monday, July 28, 2008

Removing Redundant code with NDepend

As we refactor our code, some design changes make some existing code redundant. When you have unit tests on all your code you can't find this using coverage. So finding this redundant code can be tricky.

What you need is a tool that can analyze your code base. The best I have found for .Net is NDepend.

NDepend provides a query language for code.

I started a project and added all assemblies except the test ones. I then ran the query :
SELECT TYPES WHERE TypeCa == 0

TypeCa refers to the 'Afferent Coupling' of the type.. ie. how many other types refer to this one.

This found 40 files I could delete.

I used Resharper to double check each one was not used (except in tests).

I got a couple of false positives with types I am only using to pass as type parameters to generic classes. This is the only thing stopping me adding this check as part of our build script.

Finding all those classes by hand would have taken much longer, so...

Works for us!

Tuesday, August 14, 2007

Tip:#2 Smell: Duplicate Tests Indicate a Missing Class

Smell: A class with two public methods on it, both perform the same functionality, or one is a subset of the other. The existence of a private method is a good indication of this.

To fully test these public methods you have to repeat a bunch of tests. There has to be a lazier simpler solution.

Recently I have been getting this smell a lot using MVC in a .Net winforms app.

.Net forms are hard to unit test. It is therefore helpful to keep your Views as thin as possible. Just use them to expose the form fields as a bunch of properties and to catch events and call the corresponding method on the controller. This moves the logic to the Controller where it is far more testable.

This can however lead to methods on the controller like "OnStartButtonClicked" and "OnStartMenuItemSelected". Both are going to perform the same actions. Both are going to need the same set of tests.

The solution is simple. Use the 'Extract Class' refactoring to pull the private method out to another class and use Dependency Injection to pass an instance of this new class back to the original class.

Following this above advice though you end up with another object. In my experience this split makes a lot of sense. I call this new class a Service. I rename the new thinner Controller to Presenter which better resembles it's remaining responsibilities.

(Note: I've read a few things on the differences between MVC and MVP, but I don't really get it. What I have here may be what is meant by the naming. Either way I like this design better.)

I'm really liking the new code. The view is really thin. The presenter translates UI events to service calls, and knows which views to update when the domain changes.

A piece of advice Steve Hayes often gives is "Design your UI layer so you could replace it with a command line and everything would keep working". I have struggled to do this with .Net, even with MVC. Having this new split however I can see keeping the Service and Model layers and replacing the UI would be easy.

So... Look out for duplicates tests... get lazy and write better code!

GitHub Projects