Metaphysical Developer

Quality of Code

Posted in Software Development by Daniel Ribeiro on April 20, 2009

Just the other day I was skimming through a list of topics to post here that I had crafted, and just realized that several of them had a very common, yet simple, motif: improving quality of code. This can sound quite sensible and simple to a lot of people, yet its an idea as powerful as it is controversial. And when I speak of quality of code, it is important to stress that this is the code for humans, as a machine doesn’t really care about it. Setting up this theme, Martin Folwer’s statement feels quite appropriate:

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
-Martin Fowler et al, Refactoring: Improving the Design of Existing Code, 1999

This statement is almost a Quality of Code Manifesto. More precisely, it is about readability, but both concepts are very intertwined. Readability is essential to write code with good internal quality (quality as measured by the programmers). Kent Beck, on Extreme Programming Explained, also mentions how high external quality (quality as measured by the users) can’t be maintained with a low internal quality:

Temporarily sacrificing internal quality to reduce time to market in hopes that external quality won’t suffer too much is a tempting short-term play. And you can often get away with making a mess for a matter of weeks or months. Eventually, though, internal quality problems will catch up with you and make your software prohibitively expensive to maintain, or unable to reach a competitive level of external quality.

Martin Fowler explains these interactions on a article called Technical Debt. Summing it up, code with poor quality is hard to maintain, hard to change, and therefore, costs a lot more in the long run than code with a good internal quality. Not to mention that it lacks transparency, and this can go really bad even outside software programming.

Donald Knuth also made his statement about quality of code on his work with Literate Programming, which had an impact on Kent Beck’s work.

This is such an old issue, that I felt a bit insulted when I read the following (from this post): Java (the programming language) is Turing complete so no new language feature can enable us to solve a problem with Java that would be unsolvable without the language feature.

All of this sounded me absurd, since languages are tools to express code. If being Turing complete was enough, C would be all everybody needed, regardless of being a terrible language to express intention, and therefore, to make readable code. However, the author continues: Therefore any new language feature is at best a convenience to those reading and writing the code. Such features of convenience are not to be lightly dismissed, as they allow developers to increase the signal to noise ratio of our source code.

Therefore, in order to create good code, several practises, tools and concepts were created to helps or warn us: design patterns, DSLs, peer review, object orientation, functional programming, architectural patterns, agile methodologies, refactoring, pair programming, encapsulation, inversion of control, automated tests, code generation, anti-patterns, continuous integration, logic languages, fluent code….

And several of these topics are to encompass this metaphysics.

Advertisements
Tagged with: ,

Fluent Code

Posted in Languages by Daniel Ribeiro on April 12, 2009

Fluent style of coding is quite important on internal Domain Specific Languages (DSLs) on languages that support OO. One of the key aspects of a fluent interface is method chaining, which allows the developer to reduce noise (the amount of repeated text) on the code by invoking several methods on the same object, one after the other. Just as in the good old fashioned Don’t Repeat Yourself (DRY) spirit, less noise.

However, fluent code is not only appropriate for DSLs. It can greatly improve code readability and intention revealing even on simple tasks, such as building a complex object.

For instance, let’s take a simple example of configuring an email. You can do lots of things to it, such as configure the sender, the subject, the body, and so on. In Java, such code would become:

new Email()
    .from("me@gmail.com")
    .subject("metaphysics")
    .to("everybody@gmail.com")
    .cc("CIA@usa.gov")

Instead of the usual, full of noise:

Email email = new Email();
email.from("me@gmail.com");
email.subject("metaphysics");
email.to("everybody@gmail.com");
email.cc("CIA@usa.gov");

A problem arises when the class you want to use method chaining on classes that are not already fluent and you do not have write access. Maybe you are using it from a library or from a Framework you have to use. On languages with static typing such as Java, the only solution is to create yourself a static wrapper (more specifically, a proxy) around it, and just delegate the methods to the real implementation.

On languages with support for method lookup alteration and interception, such as Ruby’s missing_method and Smalltalk’s doesNotUnderstand:, you can make such wrapper a general one. Example of such in ruby:

class Email
  attr_accessor :to, :from, :subject, :cc
end

class Wrapper
  def initialize(wrapped)
    @wrapped = wrapped
  end

  def method_missing(m, *args, &block)
    setter = m.to_s + '='
    if @wrapped.respond_to?(setter)
      @wrapped.send(setter, *args, &block)
    else
      raise NoMethodError
    end
    return self
  end
end

mail = Email.new
Wrapper.new(mail).
  from('me@gmail.com').
  subject('metaphysics').
  to('everybody@gmail.com').
  cc('CIA@usa.gov')

The beauty is: Wrapper is general. You can take any object of any class you like and, just like that, use a fluent interface around it. You can do this in Smalltalk as well, but Smalltalk is naturally fluent, because of the semicolon:

email <- Email new
        from: 'me@gmail.com';
        subject: 'metaphysics';
        to: 'everybody@gmail.com';
        cc: 'CIA@usa.gov';
        yourself.

Regarding Java language, even though you cannot make a fluent universal wrapper as you can do in ruby (dynamic proxies can’t change the interface, neither can Aspectj), there are some good perspectives ahead:

  • Chained Invocations on methods that return void. Unlikely to make the cut into the jdk 7
  • This Type: which just makes it clearer that a interface is fluent. Also, eases up the fact that subclasses will return its type on fluent methods defined on the parent.
Tagged with: , , , ,

Welcome

Posted in Uncategorized by Daniel Ribeiro on April 11, 2009

…the moment you open your mouth to say one thing about the nature of reality, you automatically have a whole set of enemies who’ve already said reality is something else… Writing a metaphysics is, in the strictest sense of the word, a degenerate activity.
Robert Pirsig, Lila

 

Edit Apr, 2017: Rest in peace Robert