What is maintainable?
Frans Bouma left the following in this post, which I found quite interesting:
The person who spend a lot of time inside the code base obviously finds it logical and knows his way through the codebase and where to make changes what to avoid etc. For that person, the codebase is maintainable. It is different for a person who's new to the codebase. If that person has to spend a lot of time figuring out where what is and most importantly: why, it's already a sign things aren't as maintainable as it should.
I have to say that I disagree quite strongly with this definition.
Maintainable is a value that can only be applied by someone who is familiar with the codebase. If that someone find it hard to work on the codebase, it is hard to maintain. If someone with no knowledge of a codebase find it hard to work with it, tough luck, but that doesn’t say anything about the maintainability of a code base.
A codebase is more than just a code sample, it is conventions, ways of doing things, overall architecture and a sense of how to do things.
Now, there is a separate value, related to how easy it is to bring someone up to speed on the codebase, but that does not relate directly to maintainability.
Comments
Hi
I think that it is maintainable if the most part of the persons familiar with the code base manage find it easy to work with the code base.
Having (only) one person is not enough as it can use a special "mental model" that would make the code difficult to understand for the most part of the developper familiar with the code.
Further more, "easy to work with the code base" can have different definitions, imho sustainability and predictability are important for delivering value, at least in the enterprise.
Cheers
--
Dom
I agree with you. If I has read that article myself, i don't think i would've noticed what you did.
If you extend that analogy to maintaining a car's a/c, one could say a layman does not know enough of how the a/c works in order to maintain it. On the other hand, the a/c mechanic knows how it works, and is thus maintainable for the mechanic.
Each to their own, but I have to agree with Franks post (with a few qualifiers).
After all, if you know the code well enough a dog-breakfast can be maintainable. I've seen plenty of code which has been an abomination, but the person whom wrote it can still maintain it with no difficulty.
The only true measure of maintainability is when the author and other familiar people step down and someone else tries to maintain it. If that's not feasible, then the code will have to be abandoned sooner or later. That in my definition is a prime example of code with low maintainability.
Of course if the person in question has to be a fairly good programmer for their view to hold any water.
I agree with you. If I has read that article myself, i don't think i would've noticed what you did.
If you extend that analogy to maintaining a car's a/c, one could say a layman does not know enough of how the a/c works in order to maintain it. On the other hand, the a/c mechanic knows how it works, and is thus maintainable for the mechanic.
Btw, on my first try posting this comment, the following error occurred:
Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.
Details: Error parsing near '
I completely agree. For example, if I approach a reasonable sized Python application, I would have trouble maintaining it. Over time as I learned Python, its idioms and conventions, then I might be able to maintain it if it were written in a manner that a decent Python programmer would find maintainable.
However, even in a language I know such as C#, the same principle can apply. For example, the Scottish, the Irish, and Americans all speak the "same language" but it can be very hard to understand each other when there are thick accents and regional dialects. Heck, I sometimes find understanding an American with a deep southern drawl.
It takes time to get familiar with a foreign codebase with its own conventions, dialects, etc... Even if you follow "standard" conventions, it takes time to understand the domain (I don't know anything about avionics systems for example). However, the amount of time it takes to get up to speed on these issues is not 100% related to how long it takes to make a change to these systems once you're up to speed.
There's a difference between the inherent complexity of the domain and the accidental complexity of a poorly written codebase.
I think maintainability is mostly about familiar person maintaining the code, but in this case a new word is needed to describe that a new person who has the same overall level as you can maintain the code reasonably fast. Understandability?
One good sample of maintainability to others is Castle.Windsor. I am sure it's architecture allows for simple addition of a new functionality, when you know how to do it.
On the other side, I have made a simple resolver that resolved service arrays, and all worked well until I wanted to it to report circular dependencies instead of crashing on stack overflow. I should have shot myself instead, after an hour I had still no idea how to do it correctly so it does not crash with some hardly understandable errors.
IMO, maintainability is about how much risk there is to the system when changes are made by a person already familiar with the code base. Can you make a change and be confident that you will not break anything unrelated to the change? If so you have a maintainable system.
Learnability is a different metric.
I agree with John above.
Frans is right.
Applications are mirrors into the mind of the developer; even the most nightmarish collections of anti-patterns make perfect sense to the original authors. The person who wrote the code and knows it inside-out will always know exactly how and where to make changes.
For those in doubt, read a few random stories from www.thedailywtf.com
Oren - Interesting distinction. Well said.
Disagree. I would call your definition as robustness or something else - but maintainability definitely has to include all costs involved in maintaining the codebase - speed at which a newcomer can be productive with a codebase, ease with which the codebase accomodates changes, documentation etc.
You might be interested in Scott's article on Relearning which I think relates to this. He uses the word "soluble" to describe code that is written in an intention revealing and easy to understand manner.
blog.scottbellware.com/.../...problem-that-we.html
Andrey,
Windsor should never crash with StackOverflow, if it does, it is a bug, and it is not your job to fix it. It is mine.
The reason that you find it difficult is that it is difficult.
I think a few things go towards keeping a maintainable system:
Picking the right architecture
Logical, Consistent and Intuitive Structure
With the right code-architecture you can then employ good strategies to ensure your code is kept maintainable, i.e. low-coupling, dependency injection, bind to interfaces, logical group components, divide and conquer, etc.
The best signs I find in a maintainable system is one where I don't need to know about how the whole system works in order to implement new functionality, and when adding new features the location and name of classes is naturally predictable in that if a similar feature already exists in the system it would have a similar name and reside in the same locations.
I agree with Bouma. What you say advocate that a developer has to remain familiar with every line of code he wrote or he has been familiar with. This is not possible. I tend to forget about code I wrote more than 2 weeks ago. But thanks to componentization, structuring, layering... all these things we disagree on, I organize code in such a way that I can forget about it and re-discover it quickly at whim.
Concerning conventions, I formalize them with some CQL rules verified automatically as often as possible. When one violates conventions, he's quickly and automatically warned.
Learnability and Maintainability represent the same metric. They both say in essence that assets in a code based are independently partitionned and can be developed, refactored, tested, dicovered, enhanced in isolation. This is the divide and conquer principle. Not respecting this essential principle just doesn't scale on large code base. Not respecting this principle is simply the main pain of sufficiently large IT organization.
I'll go back to the car and mechanic example. A car is considered maintainable if any mechanice can maintain it. A ferrari is less maintainable than a ford because you need a specialised mechanic.
Software in general should follow the same line. Software is maintainable if any developer can maintain it. The problem with this is that all software is not equally complex and all developers are not equally skilled.
I work on a large enterprise system with many interrelated projects. The least maintainable projects always have to be maintained by a fixed "expert/contractor" who know the code base. While other more maintainable projects can have different developers drop in and out making changes safely.
What is the context?
Can I grab a dev of the street and have him start working on a system?
My point is that a system can only be called maintainable or not after the familiarization phase.
Ah, a lot of people are trying to rehash what software engineering research has dug up in the last decades or so. I didn't post a 'definition', I tried to describe briefly what the crux is of maintaining software. that's not the how, as that's in front of you, it's not the where, that's also in front of you or determinable with profilers/coverage tools, it's the 'why'. that's not in the code, it has to be reverse engineered if the original programmer isn't available to produce the 'why'.
No, I am saying he should be familiar with the _system_, something totally different.
Just to give you an idea, here is the breakdown of the last change date in Rhino Mocks:
2007: 24
2008: 36
2009: 30
What that means is that 2/3 of Rhino Mocks hasn't been touched this year.
Rhino Mocks is a highly maintainable system, we keep getting matches on a regular basis and the main contributers are not the original authors.
Nope. Learnability cover how one learns the SOP in a system, Maintainability is how someone who is already familiar with SOP
Ayende, I not really disagreeing with you. The isssue is in some companies/projects the familiarization cost affects overall maintenance cost more than others.
In your project "Maintainable is a value that can only be applied by someone who is familiar with the codebase" might be valid but I do not think you can use this as a general rule.
For example: We have about 10 developers working on 30+ solutions/businsess projects. If a defect or enhancement comes in for solution 1 we look to the pool of available development resorces. Developer B is working on low priority stuff so we would like to assign them. As B has not worked on the solution before there is a familiarization cost. In the case of a bug fix this could be longer than the time to fix the bug itself.
As developers move between solutions as defects/enhancements come in this familiarisation cost can become a signifant part of the overall cost.
In practice we find that developers find some solutions much easier to become familiar with than others. I would consider these solutions to be more maintainable.
I disagree...
Think of the classic example of having an extremely messy room as a child. You knew where everything was but that doesn't take away from the fact that it was in fact a mess. IMO, maintainability can be measured by how easy it is for someone unfamiliar with the code to pick it up and easily understand and make changes to it.
Shaun, I disagree with your example. If I were to walk into a very tidy room with lots of closets, it still takes me a long time to find something.
"Applications are mirrors into the mind of the developer; even the most nightmarish collections of anti-patterns make perfect sense to the original authors."
I disagree. Generally, anti-patterns that I encounter written by other developers do make sense to me as well--the good in them is obvious. What makes them anti-patterns is something not obvious--either there is a hidden pitfall, or a solution exists that is better in every way--which is why anti-patterns happen.
I think we can estimate maintainability apart from who is working on the code by looking at things like coupling, cohesion, and how well one can learn what the code does and how to use it via the interface and documentation (i.e. without stepping through the code).
Learnability is different from maintainability because difficulty of a domain factors into learnability. However, other factors of learnability do matter for maintainability, so the metrics are similar and related.
If maintainability of a system is determined by how easily someone who is already familiar with the codebase can change it, then what happens when that person is no longer available? The organization then has made the person/team a liability and increased the risk of the project. Is the system more/less maintainable?
The more depenedent on particular resources, whether human or not, the system has more risk and is less maintainable. That is not to say such a system is "bad", or poorly constructed. Personally, I think it just means the system may be more complex. And note the use of the word "may".
I like how Patrick defines maintainability and i think it makes sense perfectly.
If I may add one more thing, I don't see a reason why any run of the mill business application cannot be "learnable" by any developer off the street, if it is written to be "maintainable". Only the specialized domains might require the sort of the experts/heroes - NASA perhaps?
Mel,
I would agree with you on that.
My problem is with the sentiment of: "a dev off the street"
I was recently brought on to a system that is highly learnable but has poor maintainability. The general approach for creating a new feature involves copying/pasting/modifying large blocks of code. It is very easy to see what is going on because the code is very linear and the architecture is very simple. I don't think I need to go into the obvious pitfalls of this type of codebase though. This is not a system that I would consider maintainable in the least.
I agree 100%
Can't you BOTH be wrong? :)
Maintainability should not be a metric that is dependent on the developer. For the reasons listed already, if it depends on a developer already familiar with the system, then when that developer leaves, is the system no longer maintainable until a new developer becomes familiar with it? No, clearly not.
Similarly, just because a developer can ramp up very fast on the system and learn it doesn't mean it's maintainable, also for the reasons listed.
Finally, we can't base the metric on whether or not a new developer coming onto the project can start making changes right away - while this would seem to be valid, in fact it depends entirely on how good or bad the developer is, invalidating any hope of a real metric based on developers.
The relativity of the developer strength makes it a terrible basis for a metric. I would prefer to define maintainability as:
1) Localized changes can be made in the system without affecting every part of the system - this one is pretty obvious.
2) Changes to the overall design of the system do not invalidate every single unit test. It's reasonable to expect some unit tests to have to be fixed. However, if every single one has to be fixed, then it indicates that the design is extremely viscous.
3) There is little or no duplicated code - for the reasons Phil mentioned
4) Inheritance hierarchies are kept to a minimum - systems which have long chains of inheritance often lead to highly-coupled, dangerously unchangeable systems.
5) The design is explicit - if the design has implicit factors to it, those become difficult to maintain. Conventions are one thing, but hiding a business concept without having a business object encapsulating it is highly unmaintainable. (I recently ran into this, and it nearly killed me.)
Can anyone else think of any other good ideas to add to the list? Remember, the metric is used to measure the maintainability of the system, not how to have a maintainable system. The above points are not a prescription or a set of rules, but concrete ways of pointing to when a system is unmaintainable. Also, keep in mind that we should be taking into account only what makes a system unmaintainable - this kind of metric can only really be discussed in that way, I think. I'm just asserting this, though. So, am I missing anything?
I think we definately need an exact distinction here.
Complexity
domain complexity
"accidential complexity"
The more complex the domain, the harder to bring in new team members. Domain compleyxity can't be influenced.
Accidential Complexity however, that is:
Leaky abstractions
unnecessary abstraction vs. missing abstraction
Leaky abstractions is pretty obvious, the last one however is one of the "it depends kind".
When i say "unnecessary abstraction vs. missing abstraction" i mean the following: Each "abstraction point" in code should have a corresponding "abstraction point" in the domain. In ayende's favourite domain, the prison :-), that means i might have prisioners of different kind (normal, very bad guys etc.). The abstraction is pretty obviously a basic prisioner. So far thats pretty basic OO.
The same applies to areas in the domain, that are likely to change. If i do introduce abstractions here, change will be made easier.
If my domain however is ORM, it is very well defined. Areas of change are SQL dialects/databases. NHibernate provides the nescessary abstractions here. But the session is no area of change in the domain, it's behaviour won't need to change in a foreseeable time. Do i need to provide abstractions then? IMHO not.
The next point that was brought in here is manageability.
Manageabilty, that is:
The first to are obivous. They are closely related to conventions (be it use of infrastructure or componentization or code structuring) and their consistent use. I cant underline how important consistency is relating to this manner.
Manageability influences maintaineabilty. The introduction of new team members is part of it. However, all the other points do influence that in reverse (@Patrick: another bad circular dependency :-) )
I thought of a good supporting analogy for my argument: The length of a piece of wood does not depend on the measurer's ability to see the meter stick.
Johannes, I don't think you're dead on here. I don't think complexity necessarily affects the maintainability of the system. It's hard to say that, though, because it would seem to clearly affect it. However, a system can be complex and still require very little effort to put out a new future, change a current feature, or fix a bug. Again, I have to say that ramping up new team members and such should not play a part in the definition.
If maintainability is to be an objective metric, then there's no way we can have something like human developers ability to pick up the system be involved. It still sounds ridiculous to me, but intuition sometimes fails. :)
Kyle,
Exactly. If 'maintainability' is as much about people as it is about code then it is highly sensitive to context. You can never say 'this is maintainable code' you have to say 'this is maintainable code given my level of experience, expectations, assumptions and those of my co-workers, and those of my organisation'. In other words it would be pointless to have a public discussion about it because all of those things will be different for any given individual.
Kyle, i think you got me a little bit wrong.
Of course does domain complexity affect the ability to pull in new developers which slightly affects maintainability.
However i was more concerned with domain complexity in relation to code complexity.
Put simple, a more complex domain consists of more problems. The famous sentence, each problem in computer science can be solved by introducing another level of abstraction applies.
We certainly can meassure the complexity of code, but we always need to compare it to the complexity of the domain.
Tools like nDepend (never used it myself) might help to meassure this complexity and enforce conventions (as patrick stated somewhere here on the comments, might be worth an interesting blog post on his side :-) ).
Kyle, the length may not depend on the measurer's ability to see the meter stick, but the MEASURED length does depend on the measurer's ability and the meter stick.
In my opinion most people here are not discussing maintainability, but how it's measured, which does get influenced by all sorts of things, like beliefs.
To me 'maintainability' is a result of code that uses good principles, patterns, and practices.
SRP. LSP, DI
If the code doesn't follow this, if it's spaghetti code, if it's C# written with functional programming techniques vs. object oriented.
Then, does it have tests? Is is 'self-documented'.
Is it easy to build and setup.
ie. If I want to use the IoC of Rhino Mocks do I have to get 30 other projects to build to get it to build ?
All of this to me are 'indications' of a maintainable system.
Just yesterday a friend showed me Grails/Groovy. He fired up Cygwin, typed a few lines and showed me how it created a 'Model', a 'Service' and a 'Controller'.
He opened it up. All in Ruby syntax, yet, all was DDD - I didn't have to know a single thing about Ruby, everyone was ordered in a manner that was following a DDD pattern.
It was highly recognizable, and outside of syntax, I found it to be 'very maintainable'
I still think that the code complexity does not necessarily affect the maintainability of the system. A complex system does not entail an unmaintainable system, nor vice-versa.
Frank, I'm using maintainability AS the measure. I'm sure there's some kind of joke here about "is-a" versus "as-a" versa "has-a", but I don't want to be the jerk to think of it. :)
John, I think you misread my analogy (or maybe it wasn't clear enough?) - my point is that if we want to define maintainability as a metric, then we can't base it on human contexts - this muddies the metric and makes it a moving goalpost for measurement purposes. I think it's probable that we can use maintainability as a metric for measuring a good design. High maintainability, in addition to the other metrics we have (coupling/cohesion, etc) tend to mean a solid design, whereas not having one or more of those tends to make us think the design could be better.
Does that make sense?
Kyle,
That was my point as well. I was agreeing with, or I was trying to at least. :)
This is easily the most hair splitting debate I have ever seen.
Regardless if "maintainability" is objective or subjective the outcome remains the same, it is very rare for developers to 100% adopt, maintain, and respect other developers' code. Whether it is a divide in skills or more religious architectural opinions, "maintainability" is a scapegoat term for "I'm having friction and it's not my fault".
Hi
I've never looked at maintainability from Ayende's perspective before, but I can't agree more with his argument. It should be from the point of view of the developers currently working on the code base.
When you find that a simple change becomes too hard, or breaks everything else, then maintainability becomes poor. It would probably be a good idea to refactor or re-design.
For new people looking at the codebase, there will always be a steep learning curve to get up to speed. Isn't that why new starters typically get assign to bug fixing, which is a great way to understand the architecture, code design, business rules, frameworks, and get a good feel for the application.
Great post. Very though-provoking.
Seems to me folk are talking about two separate things here:
Maintainability: how easy it is to make a change to a system? This is determined by how well isolated that change can be and is driven by encapsulation, DRY, etc. (As well as the nature of the change, obviously.)
Accessibility: how easy is it to understand what the code is doing and why.
There's obviously a difference between the two. Maintainability could theoretically be measured by the minimul number of lines of code required to implement a change. The only way to talk about accessibility is to know or assume who your target audience is.
Reading Frans' comments on the original post, sounds like he's talking primarily about accessibility, but arguing that poor accessibility implies poor maintainability.
Which sounds plausible, but ultimately the only useful metric is how easy it actually is to make changes. From what Ayende says, it sounds like the people who are actually working on NHibernate don't have a problem.
John - oh, sorry, missed that. :) For some reason, I always assume that everyone is arguing with me, myself included. It makes for interesting train trips on the way home.
I think it's more important to enumerate the qualities of good code bases than to quibble over what we call them.
This is rediculous! Now you guys are fighting with definitions? Don't you guys have some real work ? It looks to me all of you are just for individual product promotions and and creating noise to get attention. All of you (Ayende,Patrick,Frans). I think we have more important work then to debate over literary definitions. Neither Ayende or Frans or Patrick has any right to decide defintions, it all depends on situations...
Dinesh-"I think we have more important work then to debate over literary definitions"
You are basically saying we do not need definition. Strange ! We need definition to speak about the same thing. Just imagine someone using class instead instance, . would you be able to understand something ?
In your "real" work you are also defining what you have to do ! It is called specification, user story isn't it ?
"Neither Ayende or Frans or Patrick has any right to decide defintions"
you are perhap's right on that point but thanks to them to publicly express their opinion. If no one starts to give a "definition" we will never have one :-).
And I think it is because of the lack of formalism lack of definition this lack of education that our industry is not an industry. Yes we are just craftsman.
My comment here - mdpopescu.blogspot.com/.../maintainability.html
In short, I'd go not with the current developer, not with the random one, but with an aggregate. Not a fan of democracy here, but in this instance it's closer to what I believe maintainability to mean :)
Comment preview