Devlico.Us
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @devlicious

Derik Whittaker

Thoughts on Software Development, .Net, OOP, Design Patterns and all things cool



Unused code is the worst of the 7 Wastes of Software

Today I was having another round of conversations with a buddy of mine about the concept of waste and unused code.

In agile there is a concept called YAGNI (You Ain't Gonna Need It) that basically states that you should not add code that is not immediately needed as it is waste.

In Lean software this is known as one of the 7 Wastes of Software.  To quote from 'Implementing Lean Software Development'

'The worst of the seven wastes of software development is adding features (read that as simply code) that are not needed to get the customers' current job done.'

The context of our conversation was around code generation.  Now I am NOT a huge fan of CodeGen as I have been on the wrong side of a project that used CodeGen.  What we were debating was if it was just better to CodeGen up all the CRUD logic (they are using data driven design, not a domain driven approach) prior to needing it or create it as you need it.

The conversation started with this statement from my buddy.

'If I had to go stub a select out for a table, I'd be like WTF. Whoever created this app sucks, they did not even create select procs for me'

When he made this statement I knew I was in for a uphill battle, but I tried to convey my thoughts.  However, at the end of the conversation we agreed to disagree (but he is still wrong :)) and we went back to our neutral corners.

So, what are my thoughts on why unused code is waste:

  • You are creating speculative code for a need that you may or may not ever realize.  And my experience tells me more often then not that code will not be needed.
  • There is now more code to be maintained (in his case I have to modify/regen code if my db tables change) which leads to more work in the long run.
  • There is now more code to test, which means more tests to fix/refactor when that code changes.
  • There is now more code to refactor if you change directions later, and we all know you will change directions.
  • Your needs may/will change between the time you originally wrote the code and the time you needed it.

The only real responses he could make were:

  • Since this code is created via CodeGen, who cares if it changes I can ReGen it.
    My response - This is a weak excuse as re-creating massive amounts of code is expensive and time consuming.  Also not mention everyone on the team may not necessarily know/understand how to do the CodeGen
  • I do not want to take time later to build the functionality out as I need it.  Especially when it comes to things like CRUD proc.
    My response - This is about the lamest excuse ever.  Creating the functionality as needed, when needed, is the ONLY want to correctly solve your business problem.

So, what lesson have learned here today.  Unused code is waste and there is no 2 ways about it.

Till next time,

[----- Remember to check out DimeCasts.Net -----]



Comments

Brian said:

I couldn't agree with you more.  This is what Fowler refers to as speculative generalities, a 'down home' term I like to use for this 'code gold plating' - we're all taking the same beast though.

I too have NEVER been on the good side of a code-gen app...all the failures I've seen I don't know how anyone can say that they're a good idea.  I'd like to meet someone who actually has been and the application isn't a bloated memory hogging pig that requires a lot of 'insider' knowledge to extend or maintain and new developers end up having a 6+ month learning curve.

I have NEVER been on the good side of a application full of extra moving parts either - they've been maintenance nightmares; consequently most have been either code gen/interface heavy, or a combination of the two.

So you know I agree with you 9 times out of 10, but what really surprised me though, is that after reading what you said the other day about wanting to have more interfaces to make your testing easier in ASPNET MVC, that you'd turn around and say we need less moving parts and quote the lean software development piece about not introducing code that isn't needed to get the customer's job done  (which is where I categorize any code that is strictly for a test framework/methodology)

They kind of go against each other...write lean software...well wait, no, unless it's for testing, then add a bunch of interfaces, moving parts, and as much crap as you'd like to make the test framework blend smoother; it reduces friction on the testing tools...this is why I gave you a hard time about that the other day.

Anyway, not trying to bring up old blogs...but your contradicting yourself, and there has to be those 1 out of 10 times.  :)

# August 6, 2008 9:54 PM

Kamran Shahid said:

100% Agreed.

# August 7, 2008 2:46 AM

Reflective Perspective - Chris Alcock » 2008 » August » 07 said:

Pingback from  Reflective Perspective - Chris Alcock  » 2008 » August » 07

# August 7, 2008 3:50 AM

Paul Kinlan said:

Hi,

I half agree with "If I had to go stub a select out for a table, I'd be like WTF. Whoever created this app sucks, they did not even create select procs for me".  If I have to create a stub for a select, I would be like WTF, but its because I don't need it so why stub it!

There is absolutely nothing wrong with auto generated code.  The problem that people have is that the auto code generating tools they have used, in most cases, try to generate too much code and therefore don't cover the exact requirements that you have.  That is why in my belief, DSL tools by microsoft for modelling applications is excellent, you can do as much or as little as you like.  

Next people will be saying don't use XSD.exe or the like!

For Brians comments, interfaces are just for testing and they are add too many moving parts? in fact interfaces are a very static part of the application, they define an explicit contract the the consumer of the interface must adhere to and the implementation must directly follow.  And for this reason they are good for testing because there is an expectation in the test and the implementation.

Paul.

# August 7, 2008 3:52 AM

Derik Whittaker said:

@Paul, @Brian

I am in no way saying that I want interfaces on everything.  What I am saying is i would like them in places where it makes sense (to me).

For example.  When you base a class off of the FilterAttribute it exposes a method 'OnAuthorization'.  This method has a single parameter AutherizationContext.   When I was writing my code in this method I would have liked to be able to better/easier test this, but was not able to because a concrete class was used and mocking that was very, very painful (lots of moving parts have to be mocked).

Had it implemented an interfaces say 'IAutherizationContext' I could have very easily mocked this and written my tests.

This is what I am referring to by wanting interfaces used more.

# August 7, 2008 6:17 AM

AllanN said:

1) 'recreating massive amounts of code is expensive and time consuming.' - HUH?  if your code generation is done right, it is worst case one button click, and best case automated as part of your build or whatever and people don't even have to think about it.  I've had projects with tens of thousands of lines of generated code that were trivial to maintain (just a few templates need maintenance).  Even our unit tests for CRUD were generated (this was surprisingly useful).

2) I actually agree with the basic principle behind your 2nd response, however in a data driven design it is pretty rare for for all CRUD operations not to be needed for data that you've determined is required.  The most common exception would be Updates and Deletes.  But because humans aren't writing that code, I don't think there is any actual waste there.  The work you're doing is with the templates.  In fact, a system where you have to specify which operations are required for a specific data table seems like it would involve EXTRA work that serves no other purpose than to conform with the principle, not because you would actually be deferring any real work.  I think a more common problem with the YAGNI principle in data driven design is that people are creating data structures/tables/fields much before they're actually needed by the application.

Not that code generated ORM systems are the best option (I prefer dynamic, runtime generated systems like Linq to SQL), but YAGNI doesn't seem to be a valid excuse for not using them.

# August 7, 2008 10:51 AM

anonymous said:

>>I actually agree with the basic principle behind your 2nd response, however in a data driven design it is pretty rare for for all CRUD operations not to be needed for data that you've determined is required

Well said.  We're not talking about creating "massive" amounts of CRUD methods.  Maybe only 5-10 per class.  That's not huge and you'll most likely end up creating them anyways for most objects.  So it's not waste at that point if you're only stubbing out just a small select few basic CRUD operations that take in a basic ID, or whatever.

# August 7, 2008 11:09 AM

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# August 7, 2008 11:14 AM

Derik Whittaker said:

Let me see if i can put this another way.

Code you create now, but do not have a direct, immediate need for NOW is waste.

You can make excesses all you want, but it is still waste.

Take a look at it this way.

When you brush your teeth (god i hope you do) do you turn off the water while you are actually brushing?  If you do, it is because you recognize that you do not need that water right NOW and you are generating waste.  What you do is turn it on, use it.  Turn it back off.  Then only turn it back on when you need it.

The same thing applies to software.

# August 7, 2008 11:17 AM

jdn said:

"Also not mention everyone on the team may not necessarily know/understand how to do the CodeGen"

You're kidding, right?  As opposed to using DI/IoC, which is so much simpler than CodeGen?

# August 7, 2008 11:34 AM

Derik Whittaker said:

@JDN,

You always have to go there don't you?

# August 7, 2008 11:39 AM

Peter Ritchie said:

One issue with "unused" code (code that isn't used right away; but is available to use a later date) is that despite being unit tested (or not) its use in-the-wild won't be close to when it is written.  This means bug-fixes will be more expensive than necessary.

# August 7, 2008 11:42 AM

jdn said:

Go where?

Substitute 'NHibernate' for DI/IoC.  Heck, substitute just about anything.

CodeGen is easy.  I think sometimes people are against it when they don't control it (think the code gen'd by a typed dataset).  If you use something like CodeSmith and control the templates that gen the code, CodeGen can also be awesome.

# August 7, 2008 11:44 AM

Derik Whittaker said:

@JDN,

i think you forgot to include OO conecpts as well.  Most do not even understand them.

# August 7, 2008 11:50 AM

Peter Ritchie said:

@Brain:  So, you think writing code that is continually testable is over designing and a waste?

# August 7, 2008 11:53 AM

jdn said:

There you go, now you understand.

Let me go turn the faucet on.

# August 7, 2008 11:57 AM

Dave Schinkel said:

>>One issue with "unused" code (code that isn't used right away; but is available to use a later date) is that despite being unit tested (or not) its use in-the-wild won't be close to when it is written.  This means bug-fixes will be more expensive than necessary.

Ok, Lets put this into perspective.  We are not creating needless crud methods.  Don't you agree that most crud methods are going to

a) Accept an incoming Object or ID in order to update or insert a new record to your DB?  Is creating a CRUD method waste in this case that simply accepts the most commonly used parameters you see in pretty much all applications generic enough regardless of the "business requirements now or later".

Lets face it, you're gonna need them and usually you're passing in an ID or object.  Plain and simple.  Why wouldn't you stub out 2 crud methods for that.  Waste?  I don't see how that is waste.  They're pretty generic meaning it's not like you are expecting an ID, CreateDate, or some other specific domain fields here.  It's something that is and will be reused probably 99% of the time.  Then you can create your domain specific methods outside the initial Basic CRUD methods you genereted

Big deal, so maybe you don't use 3 out of your 10 methods that you created for your initial base CRUDs.  Big frigging deal.  Wow, so you multiply 3 x lets say 20 database tables (custom object per table).  Wow I have 60 methods that are waste.  But they all have the same design pattern, same type of signature (they expect and ID or object).  Ok so if you want to unit test them, fine.   But your unit tests will also be pretty much the same minus a few tweaks for those initial CRUD methods you subbed out.  Big deal!  And we know not to add custom methods inside your code-gened methods so your unit tests for those generated CRUDs aren't gonna change much in the future either.

So your argument about waste and maintenance is so minor.  It's not even a huge deal if you even have any waste to begin with and if you are smart when you stub out your CRUD methods to be methods that usually you see in almost every application's DL, then it's not waste.  It's using the Code Generation smartly.  Again, you're only created commonly found CRUDs before your domain specific methods (the methods you create maybe in your own partial class off the main generated class).  What's wrong with a hybrid approach.  Domain specific custom methods and database driven CRUDs that you don't touch but use 99% of the time.

I think this argument goes way too etreme on your side.  There is waste but then this is kinda ridiculous.  What waste have we made when having to create CRUDs on every table in the database.  That's a waste of TIME.

# August 7, 2008 1:35 PM

jdn said:

BTW, I just noticed this.  Next to this post is the 'our sponsors' box (well, next to all posts), and one of them is Iron Speed Designer.

A code-gen tool.

Just thought that was funny.

# August 7, 2008 5:53 PM

Brian said:

@Paul - I never said interfaces are just for testing.  Interfacing are for exactly what you said they are - what I said was putting in interfaces, just for testing, is adding extra moving parts.

If you need them in your application, you need them - if you're putting it in just for your testing framework then you're adding extra moving parts.

# August 7, 2008 5:55 PM

Dave Schinkel said:

>>>think the code gen'd by a typed dataset

oh man, don't get me into that because right now I am forced to use typed Datasets at my new place.  That's lousy code-gen by Microsoft because you have to deal the the management of not only a designer file but all that comes with it.  Sure added "convenience" but at a huge cost (non-flexible architecture, hard to create a BL off this sh** and so fourth).  

Then you have to deal with the damn data adapter and then that with it's internal table relationships in a large object all because you want convenience...not very smart architecture design.  Then you have to deal with all the issues that arise with a typed dataset, work arounds, etc. for what you could do better or at least easier meaning flexibility with custom objects.  The work to set that up is more but you have a lot less crap and more important true separation of concerns and ability to create the layers you want in an application for future growth because you have that separation.

Then there are the "hokie issues" with offline data stores and this typed dataset crap...old school way to use ASP.NET where you have to tightly couple your damn DL with typed datasets straight to your PL...you can just think of how weak your architecture and rigid that is.   So that's a very bad example of code gen but you proved a point.  That Microsoft code gens stuff so code gen is not all that bad right?  

Isn't that the point here?   If Code Gen was so bad, then why would Microsoft ever do that?

# August 8, 2008 1:28 AM

RedGreenRefactor said:

We use a self build codegen witch generates a complete ASP.NET application based on UML class model's instead of the database. This way we can start projects with the model in mind and not the DB. The DB is created through hbm2ddl. Through this we have a solid base for the application and can focus on behaviour instead of plumbing and simple CRUD. The unit tests for the generated code are also generated. I'm not really sure why people are so reluctant to codegen maybe if it's generated they don't trust it or it's the 'It's not build by me' syndrom. Whatever we are happy with. Look for a good experience with.

# August 8, 2008 11:19 AM

Lucas Goodwin said:

The problem with CodeGen isn't just the "waste" aspect (which can be a significant amount.  If you've had to maintain large applications with dramatically shifting requirements over the period of a few years you experience this pain point), but the forced architecture.

Code-gen tools/templates make an assumption (Very big assumption) of how you want to build your software.  Not all domains need 3 tiers.  Some domains need parallel 5 tiered pipelines, etc.  Perhaps you're going with a strict DTO/Value Object interface between each tier...  You get the point.

And datasets aren't codegen.  They're an abomination born by the devil himself.  Just try changing your DB schema or the dataset schema and feel the tendrils of pure evil wrap around your soul.

# August 9, 2008 12:37 AM

Keith said:

As a small ISV I love code-gen, it prevents expressing myself twice, three times and four time.

I agree it is ugly, but there is no way that I'm writting my DDL for Oracle & SQL Server, My Hibernate Mappings, my DataObjects, I feel my time is at waste here.

As for un-used methods as an ISV we often write functions that no-one uses, why people by the software because it has this bell or whistle but never use it.

I agree with your comments to some extent but please, religion with-in moderation my friend.

# August 9, 2008 3:29 PM

Link Post Sunday 08/10 | Mr Sun Studios said:

Pingback from  Link Post Sunday 08/10 | Mr Sun Studios

# August 10, 2008 12:01 PM

Gates VP said:

<i>re-creating massive amounts of code is expensive and time consuming</i>

Umm... no. If codegen is expensive or time-consuming, you're doing it wrong. If members of the team have a difficult time using code, you're doing something wrong.

You're simply attributing the problems to the wrong source. Godegen is clearly not the issue here. The issue is implementation and training.

So you come up with this as a substitute:

<i>Code you create now, but do not have a direct, immediate need for NOW is waste.</i>

But the NOW timeline is really short-sighted.

Here's a classic. We've rigged our generated entity code to have special handling on any columns named "CreatedDate" and "ModifiedDate".  Of course, lots of the primary entity tables we created simply didn't have these columns.

Now, to start with, we don't have a reporting interface or any business logic associated with these columns, so according to your logic adding these columns (i.e.: adding code) is a waste.  And of course, that continues to be true until a problem arises that is solved by having these columns (except that they don't exist).  I can't now go back and add these columns and suddenly get the data, but hey at least I didn't waste any time, right?

The problem with only handling immediate needs is that it opens the door to ignoring common failures.

Take my example. I know from experience that having these columns on specific tables <b>will</b> be useful. Maybe not now, but definitely soon. And we're not talking about full table-auditing, just a couple columns. We can get that information for a time usage so small that it's basically free and you're telling me that it's a waste because we're not going to use those columns now?

As always, good judgment and experience must be applied when making decisions about what code and features to build. I've spent a lot of time "paying for" mistakes that were wrought from the "we don't need it now" mentality.

In the case of our two dates (Created and Modified), we had to fight through support issues that relied on the non-existent data. A year ago, our product didn't have a support team, so nobody put them in, we didn't need them NOW.  That cost us time and money for what should've been a "free" feature.

Turns out we'll likely need a full change history on a couple of the tables.. That's fine, we can't get that "for free", so it's OK that we didn't "waste time".

And what about features that don't get used? If I build 5 features and only 1 gets used, is that waste? Technically it is, but realistically, not every feature is going to be a hit. In fact, it's generally acknowledged that failures are a very important component of success. Maybe it just takes the implementation of 5 features to find one that "sticks", all of that "unused code" may be a "success" in some people's book.

I think you can get my point here, waste is not as simple as defining code that does or does not get used. You also have to factor opportunity costs for the code that is written and the "timing of the time". Hours are not equal, the hour when your datacenter is down has a very different value than the hour I spent writing this post.

Calling unused code the "Worst of the wastes" is difficult to swallow without a little deeper comparative analysis. But given the difficulty of even analyzing the value of unused code, I think you'd be in for a challenge there.

# August 11, 2008 1:31 AM

Dave Schinkel said:

>>>I agree it is ugly

Why?  I think that depends on how you code gened it and what tool you used.  The code that architects I have worked with code genened some of the cleanest (simplest patterns) code that works and is simple across the board with little waste and I can prove it by telling you that most methods we have used in every class that was code gened.

# August 13, 2008 10:03 PM

Dave Schinkel said:

>>>Code-gen tools/templates make an assumption (Very big assumption) of how you want to build your software.  Not all domains need 3 tiers.  Some domains need parallel 5 tiered pipelines, etc.  Perhaps you're going with a strict DTO/Value Object interface between each tier...  You get the point.

What is prohibiting you from stubbing out additional layers if you use Code Smith for example.  I don't agree or see your argument.

>>>>And datasets aren't codegen.  They're an abomination born by the devil himself.  Just try changing your DB schema or the dataset schema and feel the tendrils of pure evil wrap around your soul.

That one cracked me up.  Totally agreed.  DataSets are pure hogs and there is a lot of shit in them to manage.

# August 13, 2008 10:06 PM

jdn said:

Although, in the interest of fairness, I will point out that while fixing a bug, I just deleted 10 lines of code, only because they weren't used anywhere.

# August 15, 2008 12:44 PM

Dave Schinkel said:

What's more of a waste.  Deleting 10 lines of code or having to take time to stub them out.

# September 8, 2008 4:39 PM

Derik Whittaker said:

@Dave,

I will say this very, very slowly just for you.

Every line of code you type that is NOT of immediate business value is waste.....

Is that clear enough :)

# September 8, 2008 4:45 PM

jdn said:

In this particular case, the 10 lines of code were originally typed because we thought they would be needed.  Minor change of requirements later, turns out they weren't, so when I came across them again (even later), I nuked them.

# September 8, 2008 5:37 PM

Predict the Future For Me | Ekinoderm said:

Pingback from  Predict the Future For Me | Ekinoderm

# September 30, 2008 3:20 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Derik Whittaker

Derik is a .Net Developer/Architect specializing in WinForms working out the northern suburbs of Chicago. He is also believer and advocate for Agile development including SCRUM, TDD, CI, etc.

When Derik is not writing code he can be found spending time with his wife and young son, climbing on his bouldering wall, watching sports (mostly baseball), and generally vegging out. Check out Devlicio.us!

Our Sponsors

Proudly Partnered With


This Blog

Syndication

News