The world of .NET from a Connected Systems MVP & INETA Speaker

Writing Maintainable Code


Writing Maintainable Code Cross-Posted from CB Blog

Some very exciting and necessary discussions have broken out in the community about writing maintainable code and the different trade offs in projects. The discussion originated with Ayende's Maintainable, but for whom? post which had the section

I am okay with that. Because my view is that having the developers learn a better way to build software is much less costly than continuing to produce software that is hard to maintain. In simple terms, if you need to invest a week in your developers, you will get your investment several times over when they produce better code, easier to maintain and extend and with fewer bugs."

To which I agreed with on Its So True Post

Especially pay note to the statement: having the developers learn a better way to build software is much less costly than continuing to produce software that is hard to maintain. That's been my experience the last 18 months with our team and elsewhere. Don't punt the ball for someone else. We made that investment in our developers a year ago and it has paid for itself ten times over.

Very thoughtful comments by JDN and Frans Bouma, in both places have provided valuable discussion. I would like to take several of my comments in both places and offer them up here for a wider audience as this is a topic I am very passionate about and one that I believe our current project has achieved some significant gains in. First of all about the "perfect" world versus the "real world":

> In a perfect world, you can build a better architecture, teach people along the way, etc.

I am on a 2 million dollar large software product. I would call that the real world. A year ago, 6 out of the 8 developers had never heard of TDD, DDD, O/RM, Continuous Design, or even programmed in C#. They were used to banging out stuff in a previous version using VB6. We decided to do right from the get go. We did teach people along the way, first doing 1/2 sessions every day, where we made all the developers draw pieces of the software on the white board and taught them code smells and the like. We made it a decision that we all agreed to do everything in pairs. The two of us who were experienced made sure we paired with everyone else to teach TDD, and everything else. A year later, all 6 of them can do it, we have 2,000+ real world unit tests.

All I ever hear you saying jdn is you can't, you can't and how all of us who have worked our butt off to get here are elitist and not in the "real world." You blame everyone else. But the fact of the matter is none of us are smart, we just keep working hard on it and make it happen even when it was real tough with management. You are smart too. You are reading this stuff. You can learn it too as all of us did.

Then on whether TDD and other practices contribute to more maintainable code

Frans,

Thanks for your well expressed comments and you are absolutely right then it isn't about "technologies" but what you do INSIDE the code that will either make it less or more maintainable.

>You all miss the point. The point isn't about focusing on >technicalities: 'what's O/R mapping, what's an IoC etc.'... that's >reading some manuals and you're done. Knowing these doesn't >make the software suddenly maintainable, THAT'S the key mistake >you all make.

But IoC and things like that are PRINCIPLES, not technologies that lead to code that is able to be extended or continuously evolved without ripping up major pieces. Which O/RM one chooses may be a technology choice but O/RM in itself can and should be discussed as one of the things one can do to write cleaner code.

>The key to maintainable software is knowing why a piece of code is >written the way it is written, i.e.: why algorithm A is chosen and why >alternatives B and C are ignored, and why the feature is kept simple >and thus the design kept simple and why the design of a feature >didn't take into account some more flexibility for extension.
>A software maintainer needs answers to these questions so s/he >can make the proper decisions where (!) to make changes. This has >nothing, absolutely NOTHING to do with the usage of e.g. o/r >mapping or IoC.

I also made this comment to your comment on my blog. I am sorry if we gave you the impression that TDD was everything. It helps on the OUTSIDE but its is just ONE out of 12 practices that we follow in Extreme Programming. They have to be done together to have any benefit. We also develop the INSIDE of the code, the algorithms and such in a Continuous Design manner constantly refactoring the code looking for simplifications and making it cleaner. When we talk about this and say the code is "extensible" its not so things can be plugged in, its so the maintainers can come in and make changes 2 years later without ripping everything apart. If you don't introduce code rot into a system and you continually work against, it isn't there in the future. 18 months into our project, 2 new people came in from the outside with hardly any skill sets and although its been hard for them, they are able to look at BOTH the unit tests and the well factored code as well as pair to understand the INSIDE as well.

I hope this helps, I think this is an excellent discussion. If there is something I am not explaining well or you think I am not not considering, I am happy to talk about it. Thanks.

Frans seems to have made the claim on my blog that that TDD doesn't do anything for maintainability, or just wonders what in the world it does do for maintainability to which I said

Frans,

Thanks for your well written comments. I think, for me, its a combination of things: there is more than unit tests. There is code developed in pairs that is highly refactored. When people talk about the code being maintainable and "extensible", it's not that we have plug-ins. Its evolving the INTERNAL implementation of the code continuously and constantly refactoring it to be simple and maintainable. I do contend that the code developed this way is more maintainable and possible of future growth without ripping everything apart and starting over. Let's put it this way: I can be away from our code base for a month and with the unit tests and the well factored code, i can find whats going on in minutes.

and

>How it works INSIDE the routine, that's the field where the maintainer will work, s/he has to know how the code works INSIDE the routine, which classes interact with eachother and WHY. TDD doesn't teach the maintainer WHY, it only teaches the maintainer HOW the code works from the outside. A nice thing to have, don't get me wrong, but not by far the full set of information the maintainer needs to do maintenance on a piece of software.

I'm sorry if you feel that TDD is the only practice we talk about. Of course it doesn't. But Extreme Programming is 12 practices that have to all be done together to really have effect. The unit tests are the OUTSIDE. But the INSIDE is developed with well refactored code, constantly looking for ways to make it simpler and more maintainable. I do contend that code developed this way is more maintainable than code that is not developed this way. I know maintenance is not sexy but where do I disagree with that? I am always working to make my code INSIDE the most maintainable and extensible to do that. I do think its a greater effort than what I did in the past.

and

>Your remark suggests that the developers who weren't >there when the app was written are able to very easily >adopt the code and how the system was written, in say 2 >years after release and everyone left. I definitely don't buy >that. I

Yes, I do contend that software that is developed with a continuous design approach as written about in Jim Shore's paper are able to have changes made 2 years in versus not developing the code this way. Developing the code the traditional ways has resulted in brittle, unmaintainable but especially unchangeable code. We have had people come in 18 months into our code base and be able to make changes in the first week.

>n the last decade or so, a lot of scientific research has >been spend on maintainability of software. You what's >funny, Sam? TDD isn't mentioned as a cornerstone of >getting maintainable software. Do these researches have >it all wrong? I don't think so

They don't have it wrong because they are measuring traditional approaches :) I totally agree that the studies show a huge problem in the software industry but there are also dozens of studies, going back to Kent Beck's original graphs that support the notion of flattening the change curve. That isn't TDD. That's Agile, thats good software practices, no matter what you call it, it is all about minimizing both the risk and cost of a change to the software 6 moths, 2 years, 4 years down the road. Doing it the other way with everything up front has been proven to fail as all your studies show. Some of the studies are still being done but you can flatten the change curve by keeping the INSIDE code

1) Simple

2) Free of code smells

3) Constantly refactored

4) Expressing the domain it is representative of

5) Well tested with unit tests, and business level tests

Jeremy reinforces these points with his excellent Train of Thought post

He's got a solid point on documentation to describe the "why" of a system's design.  It certainly helps to understand why a system arrived in the state it's in, and I'm very much in favor of the entire development team understanding the why.  Granted, I've got an almost knee jerk reaction to disagree with Frans on almost anything related to software development, but I'd still prefer a much stronger emphasis on the "what" and "how" a system is put together than I would the design documentation. 

You'll notice in all of the writing I've done on maintainable software that I didn't say anything about documentation in regards to maintainability.  It's not just because I hate writing documentation (I do of course), I just think it's much more important to focus on writing good code that is easy to understand.  Some documentation is obviously valuable, but given the choice between:

  1. Copious documentation about poorly written code
  2. Minimal documentation on solidly written code

I'd pick number #2 in a heartbeat.  You can't maintain badly written code under any circumstances.  I don't really care so much "why" it was written that way, only what it is.  And by solidly written code I mean code that I can understand by looking at that readily accepts change.  Besides, I've never seen a long technical document that was entirely useful.  Time and manpower is finite.  I'd rather sink more energy and resources into better, cleaner, well-structured code than comprehensive documentation because I think the payoff is higher.

Meanwhile, Tomas has also has contributed significantly to the discussion

And the whole "other developers might not get it" is, in the end, a red herring and tends to obscure the real reasons and motives behind it.

Why is it a red herring? Because it is usually a sign of the "we want to have a few highly skilled developers and lots of unskilled, cheap developers for the 'easy' stuff" mentality that pervades a lot of the companies in our profession, and it's just one I can't agree with. It's not that everyone should have 10 years of experience building extremely complex applications, but rather that everyone should have the opportunity to do their work to their best of their abilities.

 and

For example, some people have mentioned MVP/MVC, ORM and TDD as important aspects in achieving maintainability, which some people have reacted a bit against.

From my point of view, the problem here is that we're mixing practices with tools. For example, TDD is a practice, and one that indeed is (imho) very important in facilitating the creation of maintainable code. But by itself it is no silver bullet (my friend Sam, for example, always talks about using the full set of 12 practices proposed by eXtreme Programming, not just TDD).

On the other hand, ORM and MVP/MVC are tools (yes, patterns are just design/coding tools, in the end), and sure, they can significantly help in producing maintainable code. But they are just tools, and you have to evaluate their impact and usefulness in each case.

and

This means many developers don't really learn about the value of writing maintainable software because they it's easier to justify to yourself the writing of poor code when you think "I'm not going to maintain this later on, so why should I care?". This is not only a very egotistical point of view (and easy to fall on) but also ethically challenged. But what's worse is that it is a complete fallacy: you're still maintaining your code, and every day you write poor code in a project it's more code you have to maintain. It's just a lot of people seem to think otherwise and lie to themselves as a defense mechanism against the pain their going though every day on their project.

So, in the end, its up to you and no one else. You are the one responsible not only for learning how to write maintainable code but also to go and do it in your projects to help make this a better industry. The discussion is ongoing at Ayende's post.

 

» Similar Posts

  1. Goodbye CodeBetter and ALT.NET
  2. Getting Annoyed at Agile Correctness
  3. It's Up To You

Comments are closed