Monday, February 6, 2012

The Difference Between Getters and Properties in Dart

‹prev | My Chain | next›

I am making good progress on my MVC framework written in Dart, so tonight I take a break for something that is more worrisome. Compiling my MVC Dart code into Javascript has been throwing some errors that I have so far ignored. Tonight I investigate.

So I frogc my main entry point:
➜  scripts git:(mvc) frogc main.dart
Collections.Comics.dart:15:5: warning: cannot find "on"
    on = new CollectionEvents();
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Collections.Comics.dart:16:5: warning: cannot find "models"
    models = [];
    ^^^^^^^^^^^
Collections.Comics.dart:21:5: warning: cannot find "models"
    models.forEach(fn);
    ^^^^^^
Collections.Comics.dart:50:7: warning: cannot find "models"
      models.add(new ComicBook(attrs));
      ^^^^^^
Collections.Comics.dart:53:5: warning: cannot find "on"
    on.load.dispatch(new Event('load'));
    ^^
Views.Comics.dart:8:10: warning: cannot find "el" on "Comics"
    this.el = document.query(el);
         ^^
Views.Comics.dart:9:10: warning: cannot find "collection" on "Comics"
    this.collection = collection;
         ^^^^^^^^^^
...
There are many more such errors and the resulting Javascript is nothing more than:
➜  scripts git:(mvc) cat main.dart.js 
throw 'Sorry, but I could not generate reasonable code to run.\n';
Not cool. Not cool at all.

I will try, first, to address the errors in Collections.Comics.dart, which describe a collection of my comic books, er... graphic novels. The relevant section of the class is the first 18 lines:
#library('Collection class to describe my comic book collection');

#import('dart:html');
#import('dart:htmlimpl');
#import('dart:json');

#import('Models.ComicBook.dart');

class Comics {
  var list;
  var get on;
  var get models;

  Comics() {
    on = new CollectionEvents();
    models = [];
  }
//...
}
The errors are coming from the Comics() constructor, which looks perfectly OK to me. Except...

Why on earth did I declare the on and models properties as getters? They are properties of any instance of Comics. Getters make functions look like properties, there is no need to make properties look like properties. They are already properties.

With that stunning revelation out of the way, I solve my first two compiler errors by declaring the properties of Comics thusly:
//...
class Comics {
  var models, on;

  Comics() {
    on = new CollectionEvents();
    models = [];
  }
// ...
}
(it turns out that the list property was not needed at all).

After making similar changes in two more files, I have a compiled Javascript version of my comic book application:
➜  scripts git:(mvc) ✗ frogc main.dart
/home/cstrom/local/dart-sdk/lib/htmlimpl/htmlimpl.dart:18155:12: warning: type "dom.FileReader" is not assignable to "html.FileReader"
    return new dom.FileReader();
           ^^^^^^^^^^^^^^^^^^^^
➜  scripts git:(mvc) ✗ ls -lh main*
-rw-rw-r-- 1 cstrom cstrom  438 2012-02-05 22:51 main.dart
-rw-rw-r-- 1 cstrom cstrom 356K 2012-02-06 21:52 main.dart.js
That dom.FileReader looks to be a simple unmapped dart:dom concept in dart:html. Since I am not doing any file reading, I think it safe to ignore. For now.

Just to be sure, I check things out in Firefox and, indeed, I can add and remove comic books from my collection:


It is a bit odd that Dartium let me get away with my getter properties. I tend to think that frogc was right. Even if Dartium was correct, getter properties just seem like bad form, so good riddance.

That was a relatively minor and easy fix. What is crazy is that I had been avoiding it because I was honestly scared that it was a rabbit hole. Sometimes it really is just the proverbial molehill. I need to be better about working the thing that scares me the most. I really cannot afford to be comfortable.


Day #288

2 comments:

  1. Another good article Chris.

    My OO brain is kicking in here and telling me to encapsulate, which might look something like below. Behaviour is identical, but we have the option of controlling how our properties are retrieved or changed. You also have the option of making the setter private and effectively make a property read-only.

    class Comics {
    var _models,_on;

    var get on(){
    //control access to on
    return _on;
    }
    void set on(var p1){
    //control, validate...
    _on = p1;
    }
    var get models(){
    //control access to models
    return _models;
    }
    void set models(var p1){
    //control, validate...
    _models = p1;
    }

    Comics() {
    _on = new CollectionEvents();
    _models = [];
    }

    ReplyDelete
    Replies
    1. Thanks! There is a good chance that I may end up trying your suggestion. The current implementation is the simplest thing that can possibly work, so it has its virtues. But I can definitely see a need for something like your control/validation trick.

      Delete