Computer Science Canada

Small differences

Author:  wtd [ Sun Nov 19, 2006 11:08 am ]
Post subject:  Small differences

Small differences... or are they?

It's perfectly reasonable to say at some point, "we need to stop bickering over small differences and focus on the big picture."


After all, otherwise you lose sight of the forest for the trees, right?

Well, those platitudes aside, sometimes we overindulge that part of our brains. I'm going to look at just one case of a small difference, and I'm going to do it in the context of two popular "mainstream" languages. I'm not going to do this because I like these languages, particularly, or I think the point I'm demonstrating is particularly more important than other issues that might arise, but rather because I want to keep this concise, and relevant.

So, anyway, before I babble on further, two utterly unremarkable classes.

code:
class Foo {
   private int bar;

   public Foo(int bar) {
      this.bar = bar;
   }

   public int getBar() {
      return bar;
   }

   public int setBar(int bar) {
      this.bar = bar;
   }
}


code:
class Foo {
   private int bar;

   public Foo(int bar) {
      this.bar = bar;
   }

   public int Bar {
      get { return bar; }
      set { bar = value; }
   }
}


Java and C#, respectively, for those who have not yet determined that.

In many ways, though, this is about the getter, though, so let's trim that down.

code:
class Foo {
   private int bar;

   public Foo(int bar) {
      this.bar = bar;
   }

   public int getBar() {
      return bar;
   }
}


code:
class Foo {
   private int bar;

   public Foo(int bar) {
      this.bar = bar;
   }

   public int Bar {
      get { return bar; }
   }
}


So, what's the difference? Utterly insignificant, you'd probably say.

code:
Foo f = new Foo(42);

System.out.println(f.getBar());


code:
Foo f = new Foo(42);

System.Console.WriteLine(f.Bar);


The C# code looks a little bit nicer to the eye, due to the extra parentheses in the Java example, but anyone in their right mind will tell you the difference is too small to be significant in any meaningful way.

But then, so too was this example utterly insignificant, contrived as it was.

Let's add another class into the mix.

code:
class Foo {
   private int bar;

   public Foo(int bar) {
      this.bar = bar;
   }

   public int getBar() {
      return bar;
   }
}

class Baz {
   private Foo qux;

   public Baz(int bar) {
      qux = new Foo(bar);
   }

   public Foo getQux() {
      return qux;
   }
}


code:
class Foo {
   private int bar;

   public Foo(int bar) {
      this.bar = bar;
   }

   public int Bar {
      get { return bar; }
   }
}

class Baz {
   private Foo qux;

   public Baz(int bar) {
      qux = new Foo(bar);
   }

   public Foo Qux {
      get { return qux; }
   }
}


And so, now...

code:
Baz b = new Baz(27);

System.out.println(b.getQux().getBar());


code:
Baz b = new Baz(27);

System.Console.WriteLine(b.Qux.Bar);


But that Java looks ugly, so a good Java programmer, interested in "readable" code would probably do something like the following.

code:
Baz b = new Baz(27);
Foo f = b.getQux();

System.out.println(f.getBar());


Wow... suddenly we're doing more work. We have more variables to keep track of. Why? The two pices of code are functionally identical. We're forced to do so because following parens with a dot looks bad.

A small difference suddenly becomes less small.

A piece of code I recently saw on this site contained this piece of code:

code:
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension d = tk.getScreenSize();

setLocation((d.width - w.getWidth()) / 2,
            (d.height- w.getHeight()) / 2)


Let's imagine we have a C# binding to Swing.

code:
Dimension d = Toolkit.DefaultToolkit.ScreenSize;

SetLocation((d.Width - w.Width) / 2,
            (d.Height- w.Height) / 2)


Is this not significantly better?

Author:  md [ Sun Nov 19, 2006 7:18 pm ]
Post subject: 

While I agree that the C# code looks a bit cleaner, I see nothing wring with
c++:
monkey m = foo.baz().zip()->monkeys[2];
Sure it has some extra parentheses in it, but does it make a big difference? To me all it says is that baz() and zip() are functions, the first returning a structure or class, the second a pointer.

Author:  wtd [ Sun Nov 19, 2006 7:48 pm ]
Post subject: 

To some people. The vast majority, though, in my experience, see such a thing as being a sign that they're doing something wrong.

This in many cases arises from the ability of a return value to be a null pointer rather than a valid object reference. Intermediate assignment is seen as necessary in order to check for this.

In reality, good practices void the need to do this the vast majority of the time. But the practice persists, because, especially amongst those educated using statically-typed languages in the Pascal tradition, "safety" is viewed as being of paramount importance.

Other languages that are less strict about this and deal with such issues on a "deal with it when it becomes a problem" basis tend to have followers much more apt to agree with you, md.

There is an additional stylistic issue. When using methods with "getX" type names, despite the fact that there is a return value, the method name is verb. Chaining onto this kind of name leads to the code not reading very well.


: