Posts Tagged ‘YAGNI’

3 Comments How code generation breaks YAGNI - 01/19/09

My post-title was getting too long, so I’ll just finish it here:

… and what you should do about it!

Actually, this is a bit of a follow up to post to my post about design principles. I felt I had something more to say about YAGNI in combination with software factories. Not very long ago, I talked about a software factory I layed my hands on.
Now, I’ve had the chance to mess around with it a little more.

Imagine starting a new project with a software factory. It generates a lot of code. Some of it usefull, some of it not very.
I’m asking two questions:
1) What code is actually usefull? => It depends on the case
2) What code is not usefull at all? => It depends on the case

According to YAGNI, we shouldn’t be writing code that we’re not going to use. But in this case, a lot of code we’re not going to use, has already been generated by the software factory. So the software factory breaks the YAGNI principle.
I don’t find it abnormal that the code generated by a SF breaks the YAGNI principle, but that doesn’t mean it’s OK to keep the code breaking YAGNI when using a SF!

Why does a SF break the principle?

A software factory, solves a common problem. But as we all know, every problem domain, has exceptions. A software factory will only be able to solve that what’s -generally- the same over all cases, thus the solution offered by the SF, will not be entirely correct in all cases.
Since we’re not starting from scratch with the codebase, the developer can’t avoid breaking the principle, since it’s the SF that breaks it. But as I said, that doesn’t mean it’s ok. While in cases we don’t use a SF, it’s the developer’s responsibility not to break the principle, now it’s the developer’s responsibility to clean up the mess the SF made.

Time to refactor the software factory?

If the SF is generating code that breaks YAGNI, doesn’t that mean it’s time to refactor? Well, yes and no. The SF is nothing more than an existing codebase, just like any other one. So it evolves with time, and like in every project, it also needs it’s refactoring love once in a while. We all know refactoring is a good thing.
During your refactoring-time, you could take into account what code to add, but most importantly since I’m talking about YAGNI here, what code to remove.
But that’s not an easy decision, since that code is usefull in one project, but not in the other one. The only code you can delete without thinking about it twice, is the code that’s just -never- used.
The code that deserves some serious brainstorming, headaches and analysis, is the code that is used in less than 80% of the cases.

The SF guys might be thinking: 80%??? Then you’re taking away 20% of value? And I’ll say, no, I’m not at all. I’m taking away the code, that is an added value for 20% of your projects, but that is an added misvalue (i had to give the kid a name) for the other 80% of the projects! I must say the developers that created this SF, thought about YAGNI carefully. If you only have about 20% that is YAGNI-code in code generated by a SF, I think we can say we’ve got ourselves a powerfull thingie here.

But still, you’ve got that overhead. That 20% of other code that’s only used in special cases.
You can’t delete it, still it bothers the hell out of you. And more important, it breaks the YAGNI principle! It makes your code base too big for nothing, and sometimes very confusing to work with.

Things I think should not be generated in the SF

- method overrides that only call your base implemenation: override them when you need them, typing “identifier override methodName” is not that hard, is it?
- tests that aren’t testing anything but prepare your mocks and variables: you could still have this partly handled by the SF, by creating a recipe for them

I’m sure I can add things, but these are the most obvious ones I’ve seen until now.

So what do we do about it?

Well, in my suggestion, I would just leave it in there… But not until the end of time!
You have to pay off your technical debt, and in this case it means you have to remove all YAGNI code! Plan some time to do this after you’ve finished a user story. If this seems to be too often, and you’re not removing hardly any code, you could choose to do this after each iteration. But don’t prolong it more than that, or you’ll end up not doing it at all, since it will take too much time to do it all in one go.

You’ll think, but what if I need that code in another user story, or an upcoming iteration? That’s where you’re breaking the principle. No excuses. After you’ve finished a user story or an interation, and you haven’t used the code, the chance you will be using it all, decreases a lot.
If you need it anyway in the end, just add it manually, it won’t kill you, I promise.

Important note!

If for some reason you need to regenerate your code (executing DSL’s for example), you should review all generated code for unused code again! And not after the iteration. I think in this case, it’s something you should do instantly. Do it at the same moment you regenerate your code. Consider it a part of regenerating your code. If you notice you’re regenerating a lot of code in different places while your change is small, then I would advice to take a look at your SF. It should offer you a way to regenerate parts of code, without affecting other ones.

How to identify YAGNI code?

Resharper already makes it easy to see YAGNI code (it will look gray) such as:
- unused overrides
- unused private methods
- unused parameters
- redundant code

But that won’t get you all the way through the cleanup. ReSharper only detects these redundancies locally (I’m hearing in a next version this option will be available solution wide), and it also gets harder with unused types. There are other tools that help you out with those problems.

FxCop is a great tool offered by Microsoft to perform static code analysis on compiled assemblies. On the other hand, -and I personally think this is the most powerfull code analysis tool on the market-, we’ve got NDepend. It analyzes your code, and let’s you examine dependencies, complexity, and  a bunch of other stuff using code metrics, graphs, other visual representations and -last but certainly not least-, CQL queries. NDepend already executes some CQL queries during the analysis, but afterwards you can even execute more specific CQL queries to analyze your codebase.

In our case, we’re looking for unused code. This CQL query is included in the analysis, so it’s veeeery easy! Just take a look at the results, and refactor them away.

For your information, here are the basic CQL queries NDepend uses for detection of dead code:

WARN IF Count > 0 IN SELECT TOP 10 TYPES WHERE
TypeCa == 0 AND     // Ca=0 -> No Afferent Coupling -> The type is not used in the context of this application.
!IsPublic AND       // Public types might be used by client applications of your assemblies.
!NameIs "Program"   // Generally, types named Program contain a Main() entry-point method and this condition avoid to consider such type as unused code.

WARN IF Count > 0 IN SELECT TOP 10 FIELDS WHERE
FieldCa == 0 AND  // Ca=0 -> No Afferent Coupling -> The field is not used in the context of this application.
!IsPublic AND     // Although not recommended, public fields might be used by client applications of your assemblies.
!IsLiteral AND    // The IL code never explicitely uses literal fields.
!IsEnumValue AND  // The IL code never explicitely uses enumeration value.
!NameIs "value__" // Field named 'value__' are relative to enumerations and the IL code never explicitely uses them.

WARN IF Count > 0 IN SELECT TOP 10 METHODS WHERE
MethodCa == 0 AND            // Ca=0 -> No Afferent Coupling -> The method is not used in the context of this application.
!IsPublic AND                // Public methods might be used by client applications of your assemblies.
!IsEntryPoint AND            // Main() method is not used by-design.
!IsExplicitInterfaceImpl AND // The IL code never explicitely calls explicit interface methods implementation.
!IsClassConstructor AND      // The IL code never explicitely calls class constructors.
!IsFinalizer                 // The IL code never explicitely calls finalizers.

If you haven’t looked at NDepend yet, I strongly advice you to do so!

Then, you’ll have a non-YAGNI codebase again.

60 Comments Design principles - 01/15/09

Recently, I was asked which patterns and principles I would use in an OO-project.

As I started summing them up, I noticed the person who asked getting a StackOverflowException :) . Obviously, I had a lot to tell about the subject…
I’ll add a description (I’ll try to keep it short) to each one of them, but if you don’t know the meaning, just read the papers, blogs, or books. I’ll link to them (also check the titles, they may be links).

Feel free to add anything I forgot!

 

Single Responsibility principle (The S in SOLID principles)

This principle states an object should only have one responsibility. Why? So a class only has one reason to change. Why? Because when a class has several responsibilities, they become coupled. So? If you change one responsibility of the class, it could have consequences in the other responsibilities, so you have to retest all responsibilities.
It’s a bit confusing in the beginning to recognize a responsibility. Uncle Bob says a responsibility within SRP can be defined as a reason to change. That should get you started!

Open Closed principle (The O in SOLID principles)

The OCP states that software entities, should be open for extension, but closed for modification. What? You should be able to extend a SE without changing it. Why? If you don’t change it, you won’t break it. You will only have to test what you extended. How? Abstract away the functionality that could be implemented in different ways. If you have calculations, create an interface ICalculation, and add an implementation per calculationtype. The consequence is, that your calculation is closed for modification (a calculation calculates something and that’s it) but open for extension (if you have an addition, but also need a substraction, just add a class that implements ICalculation and you’re done). This is also a perfect example of the Strategy pattern.

Liskov Substitution principle (The L in SOLID principles)

This principle states that if you have a base class Base and two subclasses SubC and SubD, you should always be reffering to them as Base and not as their specific implementations SubC and SubD. What? Let’s get back to the calculation issue. If you have an AdditionCalculation and a SubstractionCalculation, you have to refer to both of them as Calculations. Why? Well, imagine, that apart from the Addition and Substraction calculation, you create a multiplication, a division, an exponent, … The code where you are referring to addition and substraction has to be modified to also know how to handle multiplications and divisions… Consequence => you’re code explodes to unreliable, unmaintanable, unreadable spaghetti… If you would have referred to addition and substraction as a calculation in the first place, you would have never need to make a modification.

Interface seggregation principle (The I in SOLID principles)

The ISP states that a client should not be forced to implement members they won’t use. I know this is a very common example of this principle, but since I’ve been personally confronted with it, I’m going to use it as clarification. Just take a look at it, and you’ll get the point :D  

Dependency Inversion principle (The D in SOLID principles)

This principle states that:
a) High level modules should not depend on low level modules, they both should depend on abtractions
b) Abstractions should not depend upon details, but the details upon the abstractions.

That’s a mouthfull.
Just imagine calculating a wage. Here in Belgium, we discount RSZ (social security) and taxes. Of course this is oversimplified for the sake of this example. The calculation of RSZ depends on your statute. The RSZ is always 13.07% of the bruto salary.
- for laborers, this percentage is applied to 108% of the bruto salary
- for employees it’s applied on 100% of your salary.
The WageCalculator, shouldn’t be making this distinction. Why? Well, reread SRP and OCP if you don’t know why… How? Well if you just pass a parameter IRszCalculator to the WageCalculator class, you can just call it’s Calculate method without worrying about the implementation. You can imagine that calculation a Wage is a bit more complicated than this, and eventually you can end up with a few parameters, including IRszCalculator. That’s where Dependency injection comes into the picture.
What? The client calling the Calculate method of the WageCalculator class, is now responsible for passing the correct IRszCalculation to the method, and when you’ve got several of these, the burden on the client grows. This can be solved with Dependency Injection. How? Several containers exist that resolve the dependencies needed by methods for you, such as Windsor, Unity, StructureMap, Spring.NET… How you do that, deserves it’s own post, but Davy already covered that one for me:
- Intro to Dependency Injection
- Intro to DI with Widsor

Chris Brandsma also gives a great overview of all DI-containers out there. Check it out.

Dry prinicple

DRY stands for Don’t repeat yourself. The goal of this principle, is to avoid repetitive code. In other words: copy and paste is forbidden. Why? I’ll just tell you a story.
A while ago, I was working on an existing codebase. I got a workitem assigned that told to fix an issue regarding the processing of incoming data. OK, no problemo! I fixed it, tested it, and it worked. I released a new version and got an angry e-mail. This issue isn’t fixed, the processing-bug is still there! I ran the processing method again, to check what was wrong. Nothing was wrong! Ok, let’s try again. Eventually, I called a business analyst by my side, to show that it DID work. We went through the steps to trigger the processing, and it worked. How can this be possible??? It doesn’t work for me!!! (Note the frustration and anger in my signs !!!). Finally I said: I don’t have magic hands, I promise. Do it yourself, and you’ll see it works too. He started the application, and started the processing. BA: You see? There it is! It doesn’t work!. Me: Could you please repeat what you just did? The BA repeated what he did, and again, there was the error. The way I triggered the processing, and the way he triggered it, was different… Normally that shouldn’t matter, but it was obvious that in this case, it did matter. I went back to my computer, opened the codebase, and confirmed what I already knew. The processing method was copied.
The DRY principle shouldn’t only be applied with code. Apply it in your DB, tests, documentation, …, thus in your whole system.
I rest my case.

YAGNI principle

I’ll tell you about this one with another story. Some time ago, I had the chance to work out a project on my own. I analyzed the domain and built up a model. The data I had to create, needed to satisfy a couple of rules, so I wrote them out in specifications. I created the data I needed, and compared it to my spec as a validation (Read more about using specifications for validation in the blue bible). I added tests that checked if my specs worked. All was good.
The tests passed, I had a great code coverage, and even the BA didn’t find functional bugs. Great! I had only one question. How healthy (or unhealthy) was my codebase? NDepend to the rescue. I performed an analysis, and everything looked OK. But then the results of a particular CQL query got my attention. Potentially unused methods = 2. How could that be?
After digging into my codebase (which you can do with a double click from NDepend!), I found out that 2 specs I wrote in the beginning, weren’t being used. They turned out to be unnecessary, and the problem I thought they would be solving, was handled in another way. They existed without a reason. So? Well, in this case I’m talking about two small spec-classes, but if you don’t keep an eye on this, it can result in a code bloat. I also had tests that covered the spec, so that’s -again- unecessary code to maintain.
This is what YAGNI aims to prevent. Don’t just write code you -think- you are going to need in the future. Only write code you need right now. If in the end you need the other code too, so be it. If not, you will not have waisted your time writing it, nor maintaining it.

Law of demeter

I’ll try to demonstrate this one with a bit of dummy code.
This code violates LoD:

public class Class1
{
	Class2 class2Instance = new Class2(); 

	public Class1()
	{
		// violates Law of Demeter since Class1 needs to access Class3 and does that trough Class2
		class2Instance.Class3.DoSomething();
	}
} 

public class Class2
{
	// we also need some serious information hiding here!
	public Class3 Class3 { get; set; }
} 

public class Class3
{
	public void DoSomething()
	{}
}

This is wrong because Class1 needs to know about the internal structure of class2 to be able to do something.

This code fixes the problem above:

public class Class1
{
	Class2 class2Instance = new Class2(); 

	public Class1()
	{
		// doesn't violate Law of Demeter since Class2 propagates Class1's request to Class3
		class2Instance.DoSomething();
	}
} 

public class Class2
{
	private Class3 Class3 { get; set; } 

	public void DoSomething()
	{
		Class3.DoSomething();
	}
} 

public class Class3
{
	public void DoSomething()
	{ }
}

Another solution could be:

public class Class1
{
	Class2 class2Instance = new Class2();
	Class3 class3Instance = new Class3(); 

	public Class1()
	{
		// doesn't violate Law of Demeter since Class2 directly calls Class3
		class3Instance.DoSomething();
	}
} 

public class Class2
{
} 

public class Class3
{
	public void DoSomething()
	{ }
}

You should decide what the best option is depending on the situation, of course.

Roundup

This turned about to be a longer post than I thought, sorry! But hey, I’m covering a lot of stuff here. I think I covered the most important principles when designing and developing an object oriented application. There’s a lot more information about this principles out there. My examples were pretty brief, and without lots of concrete examples. Just Google them, and you’ll find everything you need to know. If that’s not enough, read the Agile Principles, Patterns and Practices in C#. I havn’t read it yet, but plan to in the near future (it sure has some great reviews out there). I know it covers the topics I wrote about in this post, just take a look at the table of contents.

|