A lot of recent articles have raised the issue of complexity in software (here, here, and here). So why is this subject back again? Surely it's been done to death? Apparently not. When I carried out a quick straw poll of some developers recently, few of them actually thought about avoiding unnecessary complexity in their …
IMNSHO much complexity comes from struggling with overly complex languages. Java inherited a great deal of its complexity from C++. Smalltalk, on the other hand, is beautiful, simple and pretty much perfect. And has been for 30 years.
Blots on Programming
"These pressures can include the desire to produce some fun code or to “impress other programmers” with your skills." ...... for Victims of the Vain Gene Strain.
Poor programming practice either way
"On the project, I clearly remember trying to convince a very talented and skilled developer that using a set of binary flags within an int to hold information about the state of the system was not a good idea. I proposed the use a set of boolean instance variables to do the same thing - each with a meaningful name - within a State object."
You both failed to observe a cardinal rule of developing good Java code, since the actual implementation of the binary flags should never be visible to users of the class. The state of each flag should be exposed only through setter and getter methods. It then doesn't matter whether they are bits in an int or separate boolean variables.
Quite logical, really
Simple code that does the job = elegant code. When you put it like that it's obvious why there's so much bad code about - elegance is HARD.
Its very easy to assume that complex code is difficult to write, but in fact it's usually easier to do than simple code, but it comes back to haunt you. Sadly, deadlines mean that rubbish gets out into the wild all too often.
KISS & design
In order to keep a piece of software simple, you have to understand it. If you don't understand what you're building, how surprising is it that the code is complex and funky? If writing the code is the vehicle that takes you to understanding the design issues, the code will need to be rewritten once you understand the design.
I spent years taking a big piece of software from the "pretty much working prototype" stage to a production quality server with the same features. In the process I rewrote every module, and reduced the code to 20% of it's original lines of code. NOW the code is simple. It's performance is good. It never crashes.
My experience with my own code is that I have to rewrite an original program twice before it is really beautiful. I usually get the chance to rewrite code during the process of removing defects, improving performance, or adding features.
There is a traditional view that if you do enough analysis upfront, you shouldn't have to rewrite code. I partially agree with this view, but in practice you usually have much initial pressure to produce something, and much time to fix it later if the original code was successful. (Code in haste, repent at leisure...) As an industry our record of doing enough real analysis upfront is not good, which probably explains why management always wants us to hurry.
I don't know how to achieve simplicity on the first iteration. Anyone who can prove that they know how to do this is way beyond the general state of practice.
Lame advice to keep it simple by avoiding complexity is unhelpful. Test-first design is a little bit useful, because it helps you see what interface you need to implement. Really understanding your users' requirements is good, but very difficult. Same with analysis of the design. 20 years of practice is only moderately useful, probably because it helps with the other things I've mentioned.
Probably the best help is having a metric of how simple things need to be, so you know when you're done and when you still need another iteration or two.
My interface design goal.
Is one button that pushes itself
Complexity a result of maintenance in software products
I'm working for a company that sells a product that was written in the early 1990s - C/C++ WIN32 code. That's a source base that's been around for about 15 years.
1. Complexity is mostly a result of maintenance - the original code is often simple enough - the complexity comes as bug fixes and features are added.
2. Initial complexity is often a side-effect of customer requirements, particularly the need to interface with existing systems.
3. When a product has been around long enough, complexity is even due to requirements for compatibility with earlier versions of the product itself!
All these things can be over-come with suitable patterns, re-factoring, re-design etc, and all of those things will be constantly compromised by real world deadlines.
To state the obvious, product based development is very different from bespoke development. In fact, I'd say that they are almost different fields - they just co-incidentally involve programmers writing software.
New day... new life *
Nice Post, Kurt Guntheroth,
"I don't know how to achieve simplicity on the first iteration. Anyone who can prove that they know how to do this is way beyond the general state of practice." ....... Methinks they would also be a fraud as the Simplest of Code which deals in the Most Complex of Issues is always in a Change of Flux as IT has to deal with new Input every day. IT and its Software is in Constant Self Analysis. Jung and Freud, to name but two eminent thinkers would have been in Seventh Heaven on the Internet.......XXXXP Loring ITs Honey Traps and Bare Pits ...... which are Key Control Parameter to Mentor Mastery in for Access to the Heart of the Core and the Virtual Machine.
"Really understanding your users' requirements is good, but very difficult." ..... How much simpler to think the next step for users' requirement .....then you can deliver the future to them as has been consciously imagined for AI Better Beta rather than ...whatever the present Future Presentation arrangement are?
Certainly the Doom and Gloom Conflicting Scenarios is fast losing Credibility and Stealth Cover and with Robbers Unmasked will there be No Hiding Place.
* Is your today the same as yesterday ? Are you a robot? Can you be treated as one? Are you treated as one?
"I clearly remember trying to convince a very talented and skilled developer that using a set of binary flags within an int to hold information about the state of the system was not a good idea. I proposed the use a set of boolean instance variables to do the same thing - each with a meaningful name - within a State object."
Had you used C or C++, the argument would not have have taken place: using a struct with bitfields you would have had the same storage efficiency as with bits-within-ints, but with meaningful names and easy interface. It is strange that Java does not have a similar feature. This can actually be implemented in a very high-level way without requiring any bit-counting by the programmer: Do it like Pascal with its sub-ranges and packed structures and arrays, which require the compiler to figure out how many bits to use per item. 1970's tech...
Kurt Guntheroth's comment seems to contain more useful insight than the main article. (Or is this only because what the article says was already heard so often before?)
Someone has to maintain the class itself don't they? or is this a magical class that "just works", however you implement it?
"Someone has to maintain the class itself don't they? or is this a magical class that "just works", however you implement it?"
IT will Need ITs Trigger/Driver to work at All for All, David. The Crown Jewels in Vital NEUKlearer Codes for CyberIntelAIgent Control of Communications. C+++ Cracked Computer Codes.
IT is AIReality made Real Virtually..... which is QuITe Beautifully SurReal too. And for the Obvious Reason to Nurture One in Sanity, Best Played as such, rather than Pondering Unduly on the Enigma.
Manana....is Time enough to Waste on any riddle wrapped in a mystery inside an enigma.
Cardial Rule is actually Dirty Fix.
"You both failed to observe a cardinal rule of developing good Java code, since the actual implementation of the binary flags should never be visible to users of the class. The state of each flag should be exposed only through setter and getter "
So adding 30 lines of code and two methods per flag makes things simpler and easier to maintain ?
I never liked this getter/setter beans b***s. The language designers started well with the "public " modifier which nicely indicates wether the outside world can see an attribute but then they b***d it up by requiring a different syntax for actual variables and methods so you couldnt hide the implementation.
And as for J2EE -- well its an environment in which simplicity is just not possible.
Complexity is a relative term
The real problem is that 'complex' is a relative term. What may seem overly complex to me may be very straight forward to you. So, who decides what is complex?
simplicity is the hardest thing
Agree totally with both the article and Mr. Gunteroth. Beautiful code is simple code, in the same way that somebody once said: "I have only made this letter rather long because I have not had time to make it shorter". It takes time, rewriting, and domain knowledge to simplify code. But a defensive approach towards, and instinctive dislike of, code complexity helps too. Well-used, OO helps, a lot. Badly used, it makes complexity worse.
How little this is reflected in mainstream programming practice is amusing. Your Java boolean issue was a case of likely premature optimization. There is also quite a bit of premature patternization, where design patterns are slotted in for no other reason than because that sounds clever. Case in point: how to read a simple local text file in Java. Same with the getter/setter guy above - if your code is not facing towards an external consumer, what does it gain you to use a setter that just stupidly assigns the incoming variable to the instance? What is better, 'private setVar(ArrayList var)'. Or a package-accessible instance field of type Collection? Refactor, refactor, refactor, don't "objectify" without a reason.
Google up "Pace University Understanding Object Oriented Programming" to see a case where the procedural code is trivially simple and the object version is transformed into 'clever' rocket science. Which code would you rather work on, as a maintenance developer?