I may have jumped the gun on criticizing Dart's
part
operator yesterday. Some of the behavior caught me a bit by surprise, after which it was only natural to jump to the conclusion that its sole use would be for nefarious coding. It's also possible that I might still need to catch up on sleep after a bout with a stomach bug. Ahem.Anyhow, after some helpful comments in yesterday's post (and some G+ discussion), I think I have a better handle on parts in Dart. I also think I might have an opportunity to use them myself. First, let's make sure that I understand them.
In my
main.dart
file, I import the Greeter
class from a library:import 'greeter.dart'; main() { var standard = new StandardGreeter(); print(standard.greet("Bob")); }I use it to create a standard greeting and print out the result:
➜ code dart part/main.dart Hello, BobMy greeter library is so successful with a single class, I decide to add other kinds of greeters: the "howdy" greeter and the more subdued "hi" greeter. Clearly, it is going to be a maintenance nightmare to define all three classes in one file. This is the point of parts.
The original greeter library with the
StandardGreeter
class was defined in greeter.dart
as:library greeter; class StandardGreeter { greet(name) => "Hello, ${name}"; }It's a library. It is a class. The class has a method. Easy-peasy.
Now that I have a bunch of classes, I move them all into their own files:
standard_greeter.dart
, hi_greeter.dart
, and howdy_greeter.dart
. The greeter.dart
library file now needs to pull in each class, which it does with part
:library greeter; part 'standard_greeter.dart'; part 'hi_greeter.dart'; part 'howdy_greeter.dart';Last, but not least, each part has to declare itself the property of this library. These are not reusable code chunks. They belong exclusively to the library. This is where the
part of
directive comes into play. In standard_greeter.dart
:part of greeter; class StandardGreeter { greet(name) => "Hello, ${name}"; }In
hi_greeter.dart
:part of greeter; class HiGreeter { greet(name) => "Hi, ${name}"; }In
howdy_greeter.dart
:part of greeter; class HowdyGreeter { greet(name) => "Howdy, ${name}"; }Back in main.dart, the
import
statement is unchanged—I am still pulling in the greeter library. But now, thanks to the multi-faceted nature of that library, I have access to three greeter classes that can be used to greet Bob:import 'greeter.dart'; main() { var standard = new Greeter(); var hi = new HiGreeter(); var howdy = new HowdyGreeter(); print(standard.greet("Bob")); print(hi.greet("Bob")); print(howdy.greet("Bob")); }No output from the
dart_analyzer
means that I must be doing something right (or at least not horribly wrong). And, with that, I have my three different greetings:➜ code dart_analyzer part/main.dart ➜ code dart part/main.dart Hello, Bob Hi, Bob Howdy, BobI can very much see the utility of doing something like this. In particular, I can already see that this would help Hipster MVC. In the collection library, for instance, I am currently defining my collection class, event list class, event class, and more in a single file. This was tedious at times. I definitely plan on making use of parts to split those things out into smaller, more manageable files.
It still concerns me a bit that it is possible to extract a bunch of functions into a part as I did last night. A bunch of functions is the opposite of organization. It is the developer equivalent of the junk drawer. But I am happy to avoid the practice, especially if I have yet another way to make the rest of my code stronger.
Day #592
No comments:
Post a Comment