So, I actually have around 24 years in IT now. I usually cut down on this like some chump not wanting to spook their much younger date. Seen a few changes, lots of new whatevers that are going to change the world blaah. You have your own list of these.
But we never seem to address the key issues: most people writing software don’t know how to. They’re techies that luxuriate in a complex ‘if’ statement, that fantasize about shifting a few bits in a gloriously complex nested statement that also predicts the day of the heat death of the universe.
What they write ain’t simple.
So there are plenty of pages here that discuss the ways that code should actually be written but AFAICT not a one page, executive summary.
So can I propose this. Five Magic Rules that if followed will automagically make your code sweet. That, without using an IOC container, will make your code more flexible and attractive to countless high flyers with long tanned legs.
Here we go:
-- Chris Brooks
Chris - I observe that with the wisdom you possess and are kind enough to share, you should find it easy to learn how to format things in this wiki. I ask that you do so, so your advice is easier to read, and easier to concentrate on. I've no doubt kacked your advice about and may have shifted the emphasis inappropriately. I apologize if that's the case, but I found the original unreadable.
DomainSpecificLanguages by themselves won't "save the world"; their use and design is subject to the very same rules as other common programming constructs - especially APIs, framework, and library design. Many of your rules certainly apply. But EmbeddedDomainSpecificLanguages have real potential to reduce programming complexity (AccidentalComplexity). It is well observed that no single paradigm seems to work well in all programming cases, especially if the goal is to separate policy from implementation. Sometimes you need reactive programming, sometimes workflow programming, sometimes imperative, sometimes logical or relational, sometimes service oriented, and sometimes a combination of all the above. Access to powerful metaprogramming facilities to create (and interleave) task-related languages can make the efforts of Greenspunning a solution more natural and much more efficient (via partial evaluations and sharing of the optimizer).
You mention several rules above related to testing, CouplingAndCohesion, etc. Other rules to pay attention to are OnceAndOnlyOnce, DoTheSimplestThingThatCouldPossiblyWork, YouAintGonnaNeedIt, RefactorMercilessly, RulesOfOptimization, and PickTheRightToolForTheJob. All this 'one class one task' stuff often starts breaking down when faced with common issues of logging, optimizations, and concurrency management.
I suggest you wikify your above advice. Links to CouplingAndCohesion, UnitTest, etc. are appropriate.
Hmm, the DSL comment was intended flippantly, as was most of the advice that appears to have offended some (or maybe one I haven’t been tracing the changes) Point I was endeavouring to make is you don’t need DSL’s to manage complexity you do that by writing simple code.
You mention valuable stuff, though some isn’t related to code structure. You’ve either succumbed to YAGNI or you haven’t. Doesn’t so much affect the structural simplicity of what you have written.
I’d be interested in some examples as you why the OneResponsibilityRule doesn’t work, seems to work for me. (Ooer, does that sound smug?) Also as a rule is the separation of policy and implementation to be scorned? Or followed unless doing so is not the simplest thing the could possibly work -
instead of going across to the model class and creating a new method, ie
if (model.hasTaskDefinition())
which is what he should have done before he started typing. IMHO anyway...
Anyway, excuse me while I go and reformat some unreadable code, opening braces demand a new line in my bible!
You have 2 rules listed that, though both good, are hard for inexperienced programmers to apply simultaneously.
In the case of nested loops, I like to recommend collection-based programming for smallish loops or filters for very long ones. To unstack complex if statements, one can replace conditional logic with method dispatch, store intermediate Boolean results in intermediate variables, or allow condition clauses to be repeated in multiple branching clauses.
See also: TwentyFiveOrSoRulesToBuildSoftwareThatWorksAndWhichIsEasyToMaintain