Last year, I was reading a number of booking about language structure and grammar, in an attempt to address, what I consider, a deficiency in the Queensland Education system and a further pursuit of my own interest in linguistics. I highly recommend avoiding these types of books unless you are really (really!) interested in the area because most of them tend to be quite boring.
The reward of finishing these, rather dull, books is the discovery of a few interesting facts about languages. The most interesting (ok, ok, bear with me) and relevant one I found is the topological classification of the English language according to sentence composition. In this category of languages (English, German, Chinese), a majority of sentences are composed using the Subject-Verb-Object (SVO) predicate (e.g. John walked the dog). In contrast, the Japanese language uses SOV (As for John, The Dog He Walked), and Yoda used OSV (The dog, John walked).
I suppose my interest in this area is its relevance to my ability of writing clearer code that communicates better intent. One of the touted benefits of Object Oriented Programming (OOP) is its easy mapping to the natural description and interactions between real world things, and our ability to express code our ideas closer to the language we use everyday (for me, English). I’m convinced that if I learn how to write better (learn how to structure proper sentences, apply proper terms, etc) even in basic articles or entries on this blog, then I should have also improved my ability at working out code that communicates more.
Take these two simplistic (and not necessarily ideal) blocks of code:
// Block A<br />public void triggerSpecialNotification(ExecutionResult resultOfExecution) {<br /> if (ALERT_CODE.equals(resultOfExecution.getCode())) {<br /> dispatchAlarmNotification(resultOfExecution);<br /> }<br />}<br />// Block B<br />public void triggerSpecialNotification(ExecutionResult resultOfExecution) {<br /> if (resultOfExecution.getCode().equals(ALERT_CODE)) {<br /> dispatchAlarmNotification(resultOfExecution);<br /> } <br />}
Based on the proper SVO paradigm, although Block B is more susceptible to NullPointerExceptions (and probably why Block A is typically written), Block B is consistently more readable because the resultOfExecution is maintained as the subject for the entire method.
Maybe here is a better example (I’m still floundering to find a good one):
// BLOCK A<br />public void doSomeWorkAndTriggerNotifications() {<br /> ...<br /> ExecutionResult resultOfExecution = runCommand(someCommandObject);<br /> someMessagingService.triggerSpecialNotifications(resultOfExecution);<br /> ...<br />} <br />// BLOCK B<br />public void doSomeWorkAndTriggerNotifications () {<br /> ...<br /> ExecutionResult resultOfExecution = someCommandObject.run();<br /> resultOfExecution.triggerSpecialNotificationsVia(someMessagingService);<br /> ...<br />}
Although the end result is something that could be achieved via a number of other xDD (x Driven Design/Development) approaches, I think this focus on grammatically correctness may help some improve the readability and design of their own code. In fact, it’s almost as if there is an opportunity to build a design tool reviewing code based on standard grammar correctness based on an a given vocabulary (domain specific nouns, verbs and adjectives perhaps described through annotations?). My ideas are still pretty raw, but maybe it has potential…
ExtractMethod your friend is.
Extract the pieces that give you gramatical problems out to their own methods. So…
if (ALERT_CODE.equals(resultOfExecution)) becomes if (alertRequiredFor(resultOfExecution))
Don’t feel worried about extracting apparently “trivial” pieces of code. One example of readability I saw proclaimed once was a piece of test code written by Ward Cunningham. I forget the exact details, but it was like he’d written a method called nextWednesday() to return the appropriate date.
In the extracted method, you give the parameter a name that makes better sense. 🙂 Or perhaps you don’t worry about it anymore; there isn’t any other “signal” in the method to cause interference.
In general, the more comfortable you are with reading the code, the better you will understand it. This will lead to fewer defects.
Oh, and for an _interesting_ grammar book, read “Eats, Shoots, and Leaves”.
Robert, I agree that “Eats, Shoots and Leaves” is a very good read (it’s in my library thanks to Pam), and I agree that the standard “Extract Method” refactor is a useful way of improving readability, but tends to lead to excessive procedural programming, making it far too easy for developers to forget about better object encapsulation, design or responsibilities. Proper refactoring probably would have turned the first method into something more like
resultOfExecution.isAnAlert()
.Perhaps I wasn’t clear enough about what I was trying to state, but this entry wasn’t so much about the surrounding block of code calling that equals method, but structuring the implementation such that wherever it ends up (in
alertIsRequired
, orisAnAlert()
, or in the current method), that the correct ordering is just as readable, following what English structures are most correct. So regardless of where the code lies, instead of code that readsALERT_CODE.equals(resultOfExecution.getCode())
, keeping the proper SVO means having something likegetCode().equals(ALERT_CODE)
for readability.Within an object, code is procedural. The question becomes: should the object be aware of the procedure, or does it live elsewhere?
In this example, if the execution is responsible for knowing an alert status, then it _may_ well be appropriate to ask it if it is alert, or get it to do something that is suitable for alert. Or it may not be.
OO is really about responsibility, and responsibility alignment. The fact that the executor has returned a result code (or thrown an exception, for example) indicates that the executor does not have the responsibility to handle the result. Thus it is acceptable for the caller to handle it as needed; it is what is aware of the requirements. The very fact that the caller is doing something with the result code (even if it is passing it off to something else) indicates that it is the caller’s responsibility to do so.
Having assumed the responsibility, the caller can either do fulfil the responsibilty directly, or delegate it. Either will smack of procedural code somewhat, and both have the possibility that the caller will fail to fulfil the responsibility (just go around reading some C code and see how many times the error code returns are ignored)
As an alternative: give the executor an AlertHandler. This means that the caller has the responsibility to construct a suitable executor and a suitable handler, but no longer has the responsiblity to handle the result. This would, in turn, be less error prone; the signature of the method would indicate “Hey, this needs a handler” in a way that a ResultCode return type does not. The caller could itself be an AlertHandler (via implementing the interface) making it a simple callback, but that would be an indication that the responsibility is accepted.
Personally I find no difference between ALERT_CODE.equals(result.getCode()) vs result.getCode().equals(ALERT_CODE), save for the potential NPE; to me, maths training kicks in over grammar rules and I recognise the transitive nature of equals(). Everyone’s standard of readability is dependant on their own background.
This isn’t a SVO construction, BTW: equals is not a verb, but a relationship (a different gramatical construct), and both ALERT_CODE and result.getCode() are the subjects. If treating ‘result.getCode()’ as a subject is a problem, than it’s time for the ExplanatoryVariable refactoring instead. 🙂
Sheesh, I tend to ramble. 🙂
All talk about OO design and Standard Refactorings aside (this is not what the original post was about), if you don’t find any difference between the two statements, then perhaps I didn’t communicate well enough the subtle differences I see between them. Yes, from a mathematical sense, equals is transitive (and by the way, equals is a verb) and can be read from either side of the relationship.
Read as a single sentence, all of this is okay, but if you imagine the method as a paragraph, with the focus of that paragraph being around the
result
, and when you read the first sentence in that paragraph, finding that the initial “subject” for the sentence is something else, I find it lessens the readability of the method as a whole.What I was trying to say is that when we write code, and even when we refactor, each statement (or sentence) might make perfect sense on its own. My interest with the grammar/linguistics/whatever you want to call it is more to do with ensuring that each sentence by itself should make sense, but more importantly, the flow of the paragraph in which those sentences are formed should be maintained as well (because it’s these continuous micro-context switching which affect readability and cost someone some time). Refactorings and proper OO design are techniques for improving it, this technique is more to do with highlighting what might need improving.
Looks like I tend to ramble too 😀
Catering more towards the “I prefer it when people write correct English” topic – here’s an awesome site that addresses many “Common Errors in English”.
Someone needed to break up the OO banter! 🙂
Thanks for the good resource Gerrod. Looks good. I better go back and check some of my older posts… 😉
Patrick, check out Simon Harris’ stuff on readable code; he and James Ross are trying to write code that makes sense when read back via speech to text.