4 ms·
I learned something a long time ago. It's far, far easier to dismiss others' code as "complex", "unmaintainable", or "clever" than it is to try and understand
by j_baker 16y ago
I learned something a long time ago. It's far, far easier to dismiss others' code as "complex", "unmaintainable", or "clever" than it is to try and understand the code well enough to figure out whether that code was written that way for a valid reason. It's true whether you're new and approaching a codebase for the first time or whether you're reviewing someone else's code.
And no, I'm not saying that it's ok for code to be overly complex or unmaintainable. I'm saying that your first impression of code is probably wrong and you need to understand it before you dismiss it.
- rikthevik 16y agoI think really good high-level documentation would be a good place to start here. If someone looks at your code and immediately says "wtf", it seems like it would be good form to point them to a great piece of documentation. Without that, it seems unreasonable to ask your colleagues to dive into something well outside what they're used to seeing in that code base.
- Joeri 16y agoIt's always twice as hard to read code as it is to write code. For that reason alone, clever code is usually unmaintainable.
- raganwald 16y agoIt's always twice as hard to read code as it is to write code. True. For that reason alone, clever code is usually unmaintainable. How does this follow logically from the first statement? And more importantly, what alternative do you suggest? Are you positing that for a given problem, there is always some alternative solution that is "less clever" and "more maintainable?" If you've never seen folding and unfolding before, code that makes heavy use of "map," "each," "select," and so on looks clever. But in reality, it is simpler and less bug-prone than fooling around with for loops and off-by-one errors. To my eye, for loops are clever and unmaintainable. Moving up the scale, what about recursive combinators? https://github.com/raganwald/homoiconic/blob/master/2008-11-23/recursive_combinators.md https://github.com/raganwald/homoiconic/blob/master/2008-11-... They look very clever. But then again, rolling your own recursion from scratch every time you need it makes the person reading your code do a lot of work to figure out what you're doing. Is it "clever" to separate the concerns of how to implement recursive algorithm from the code that does something recursively? Or is it clever to roll your own code every time? WHat about parser combinators? Clever or not? How about rolling your own interpreter for a DSL? That's an official pattern from the GoF book. Can I do that and write maintainable code? Anyhow, I'm saying the same thing over and over. What is "clever?" Making use of a language feature or algorithm or well-known practice that someone else hasn't seen before and is too lazy to learn? And what is the alternative? Greenspunning the same functionality in an under-specified, bug-prone one-off way?
- rapind 16y agoI'd say clever is defined by your audience. If you're writing something that others on your team would consider clever, then you're responsible for making sure they understand it. Even if that means losing whatever time you saved by writing something clever (the advantage is still creating a smarter team though). Responsible developers write a lot less clever code because it means they feel obliged to comment the crap out of it and find the time to go through it with other team members. Unfortunately there's a lot more clever code that only one person really gets. If you're too clever for your team, then quit slumming it and find a smarter team. You're going to be toxic to a team that isn't as clever as you are unless you assume the role of mentor and all of the responsibility that comes with it... and the required patience.
- raganwald 16y agoYour response assumes that clever code exists to save time writing programs, and that for any problem there are a wide range of equally good solutions possible from "takes a long time to write but is easily readable and maintainable" to "quick to write but impossible to read and maintain by those who don't have doctorates in functional programming idioms." I don't dispute the existence of code that is unnecessarily clever, but I suggest that sometimes what appears to be "clever" for a given audience is in actuality the local optimum. Attempting to optimize it for readability without further study will worsen the code in some way, such as conflating concerns that have been carefully separated or introducing dependencies.
- rapind 16y agoI can agree with that. I'd add that if something seems clever you might want to make sure others on your team are aware of it too. At least that way you won't get blamed for being too clever, and more people will understand what's going on.
- raganwald 16y ago// Here be gryphons and scabrous wyrms
- stcredzero 16y agoFor that reason alone, clever code is usually unmaintainable. An entire application of "clever" for clever's sake is unmaintainable. This tricky sort of clever is sometimes exactly what's needed, but should be used sparingly, where it is most beneficial, and it should be well commented. On the other hand, clever directed at the goal of readability and maintainability can be wonderfully maintainable. Clever for readability's sake should be throughout the whole application. Accomplishing this is an iterative task, ideally throughout the whole life of the application. This is one of the most important purposes of refactoring. While it's much easier to brag about the 1st kind of clever and show it off to your coworkers, you'll benefit much more from the 2nd kind of clever. A tip from my experience: Managerial emphasis on the 1st "clever" is sometimes accompanied by a culture of coder showmanship. Managerial emphasis on the 2nd kind of clever tends to be more focused on sustainable results.
- raganwald 16y agoHere's one rule-of-thumb that just occurred to me. If there is "prior art" for code, the onus is on the person reading the code to show that it is "complex", "unmaintainable", or "clever." If there is no prior art for code, the onus is on the person writing the code to show that it is "simple," "maintainable," and "straightforward." Taking parser combinators as an example, if you write some code with parser combinators, simply document your choice as usual and include a hyperlink to http://en.wikipedia.org/wiki/Parser_combinator http://en.wikipedia.org/wiki/Parser_combinator. If I read your code and think this is overëngineered, it's up to me to show a better way, I can't simply wave it off as being too hard. That doesn't mean it gets a free pass, it could be that parser combinators for a custom DSL are too complex, perhaps the same problem could have been solved with JSON or something, but the default should be to accept it since it's a technique that is explained "in the literature." On the other hand, if I roll my own complex code and I can't point to a reference for the technique, then it's up to me to make the case that it's simpler than the alternative. For an example, Benjamin Stein and I wrote #andand for Ruby. It's related to the maybe or option monads, but it doesn't take the standard form so I can't really document it with a hyperlink. The onus is on me to show that in Ruby, #andand is simpler than testing for null, using the null object pattern, or organizing code such that there are no unexpected nulls.
- j_baker 16y agoI think you might be overgeneralizing just a little. I'm mostly talking about how you approach an existing codebase. When I'm new to a project, I have to fight the urge to call it overly complex because I know that it's easier to dismiss code than to understand it. The people who created the project put work into it and deserve effort to understand it. This is something I learned quite quickly as a programmer (I mean, the project maintainers will usually be more than happy to tell you that). A more recent realization is that this goes both ways. If someone submits code to my project, I owe them the same thing: an honest attempt to understand their code even though it's easier to label it overly complex and go watch House. It sounds like you're thinking more in terms of how you market a new project, which is a different problem that I'm far from being qualified to solve.