Saturday, May 25, 2013

Limiting the Impact of Class Explosion in Dart

‹prev | My Chain | next›

I am considering refactoring the Dart code in the ICE Code Editor. So far, so good with extracting dialogs and sub-menus out of private methods and into classes. I started with the extracted class in the same file as the original class. The full.dart file contains:
part of ice;

class Full { /* ... */ }
class ProjectsDialog { /* ... */ }
_hideMenu() { /* ... */ }
_hideDialog() { /* ... */ }
As the “part of” directive at the top indicates, this is part of the library's main file, ice.dart:
library ice;
// library import statement...
part 'editor.dart';
part 'store.dart';
part 'gzip.dart';
part 'full.dart';
I am inclined to make the ProjectsDialog class part of the full.dart code:
part of ice;

part 'full/projects_dialog.dart';

class Full { /* ... */ }
That will not work, though. Dart files can only be part of libraries, not other parts. Even if they could, I would still effectively be importing the ProjectsDialog class in to the main library.

I suspect that I may want to split the ICE package into not one, but two libraries. The first would be for the full-screen version of ICE and would be imported into other code as import 'package:ice_code_editor/full.dart'. The second would be the embedded version and would be imported as import 'package:ice_code_editor/embedded.dart'. Both libraries could then share things like the underlying Editor, Gzip and Store classes.

Still, I am unsure if that is necessary and I have not even started on the embedded version of the code, so I will wait to do that another day. For now, I still need to figure out how to organize things and how to keep the ProjectsDialog hidden from the outside.

I move the ProjectsDialog into a new file: full/projects_dialog.dart, which is part of the main ICE library:
part of ice;
class ProjectsDialog { /* ... */ }
Then, in ice.dart, I complete the part/part-of pair:
library ice;
// other imports here...
part 'editor.dart';
part 'store.dart';
part 'gzip.dart';

part 'full.dart';
part 'full/projects_dialog.dart';
And, since full.dart and full/projects_dialog.dart are both part of the same library, the Full class can still use ProjectsDialog as before.

That seems fine, but how can I hide ProjectsDialog from the outside world? I suppose that I do not need to prevent access from the outside world—it does not need to be private. Maybe it is sufficient to keep it out of the public documentation:



That can be fixed with an internal tool, tool/dartdoc, that generates specialized documentation:
#!/usr/bin/env sh

dartdoc \
  --package-root=packages \
  --exclude-lib=js,js.wrapping,meta,metadata \
  lib/ice.dart

mv docs/ice.html docs/dev.html

cat docs/dev.html | \
    grep -v Dialog.html | \
    grep -v ice/Ace \
  > docs/ice.html
With that, I have a simple solution for de-publicizing my internal classes:



That seems a reasonable approach. I can now extract as many menu and dialog classes as I like without polluting the documentation.

Day #762

No comments:

Post a Comment