Enough about recruitment, let’s get back to code. This article is (more or less) going to be a continuation of Rock SOLID Code. I’ve talked about five principles forming letters in the SOLID acronym, now I’m going to talk about further set of well known (hopefully) programming (and not only) concepts.
(K)eep (I)t (S)imple, (S)tupid
“Everything should be made as simple as possible, but not simpler.” Albert Einstein once said. KISS acronym was coined by Kelly Johnson, U.S Navy engineer in the sixties. Basically, simple thing doing the same job as complex thing is better. It’s easier to understand which means being less error-prone, easier to maintain, cheaper and more efficient. Always try to come up with simple and intuitive solution to the problem. Sometimes it might be more difficult than coming up with difficult one! There are people who are proud to invent overly complicated and “smart” solution that only they can understand. They should burn in hell. Every time when I see a class name containing “smart”, my inner warning light turns on. Why the author had to use word “smart”? Is there a nasty hack somewhere there? Is there a dirty non-standard solution? Does he need to prove that he is smart by constructing something incomprehensible to others? Where does he live if I had to track him down? Tick… Tock… Tick… Tock….
(D)on’t (R)epeat (Y)ourself
“Every piece of knowledge must have a single, unambiguous, authoritative representation within a system“ as formulated by Andy Hunt and DaveThomas in The Pragmatic Programmer. Violation of this principle is called (W)rite (E)verything (T)wice, or (W)e (E)njoy (T)yping. The idea is that every piece of information in the code, be it data or algorithm, should be written once. This way we avoid verbosity, copy-pasting and risk of inconsistencies and errors. It is strongly connected with The Abstraction Principle which states that we should aim at finding common characteristics of fragments of code and abstract them, thus reducing code duplication. However there should be balance between avoiding duplication and over-complication of the system. I was once the developer who couldn’t stand looking at one duplicated line of code, and tried to abstract it as much as possible, which sometimes lead to overblown class diagrams or myriads of too small methods. But I’m cured now. There is also a rule, somehow relaxed, called Rule of three mentioned by Martin Fowler in book Refactoring, which says that code can be copied once, but if it is used three times, it should be extracted to separate procedure, class or whatever. There is no silver bullet here, use your judgement.
(Y)ou (A)ren’t (G)onna (N)eed (I)t
“Always implement things when you actually need them, never when you just foresee that you need them” said Ron Jeffries, co-founder of Extreme Programming. It emphasizes writing as much code as needed to complete the feature or task at hand. In times of agile development, rapid prototyping and ever-changing requirement, it’s often risky to assume much about future. Expectations change, technology changes, ideas change, market changes. Sometimes you conceive a brilliant framework for your application that will take two months to develop and at the end turns out to be useless because client changed his mind, the scope got reduced or something similar happened. This doesn’t mean of course that you should dump creating elegant, abstract and flexible solutions over loathsome copy-pasted pile of crap. Just start simple, with what is needed to achieve goal of story or sprint, increment, refactor, experiment and shape suitable abstractions as complexity grow. That’s called emergent design, and it works providing you are disciplined to refactor stuff.
“Coupling is the manner and degree of interdependence between software modules” reads dear old Wikipedia. Loose coupling is desirable property of application modules, since it makes them easier to reuse, easier to test in isolation and less likely to break down after modifications. Introducing changes to tightly coupled systems tends to have a ripple effect, where new feature causes shitstorms (or solid-waste-atmospheric-disturbance, if you like) in random places, often remote from where the change originated (sounds familiar?). Often though reduction of coupling comes at a performance cost related to message transmission / translation / interpretation. Sometimes, for some critical points of the system, trade-offs have to be considered. You may think of low coupling of modules in high-level terms as good encapsulation. In modules, much as in classes, it’s good to hide implementation details and only expose clean and elegant interfaces.
“Cohesion measures the semantic strength of relationships between components within a functional unit” or, simply put, refers to the degree to which the elements of a module belong together. High cohesion is good, because it improves code readability. When stuff is where it is supposed to be, and fits well together with its neighbors, it’s easier to understand. Cohesive code is likely to be easier to reuse. There are several types of cohesion, going from the worst to the best: Coincidental, Logical, Temporal, Procedural, Communicational, Sequential and Functional. While coupling problems are easy to detect automatically via static code analysis, cohesion is much more elusive, subjective and difficult to assess, thus requiring human insight.
That’s it for now. In the next episode I will continue the topic and dig into some less known and more informal principles of programming.