Saturday, August 31, 2013

At this point I have no less than 7 active Dart projects and libraries, most of which rely on the dart:json library to one degree or another. Unfortunately, dart:json is going away, replaced by similar functionality (but different APIs) in dart:convert. Since I want to continue to use my 7+ dart libraries and projects, I need to convert them… to dart:convert.

Actually, I think it makes sense to use the option #2 for most of the packages—at least in the first change. Option #2 is the Dart folks trying to make our lives a little easier in the transition. It breaks out a JSON package that supports the same API as the old dart:json library. This should make for fewer code changes, which I appreciate.

So I find all mentions of dart:json in Dart files that are contained in those 7 projects:

With that, I am ready to try things out. Thankfully, I have decent test coverage in most of my Dart code, so I can be reasonably confident that the json package is being exercised and is working as desired:

That approach works fine for each of my packages. I am curious about the dart:convert option, I so switch to that in Hipster MVC. I remove the newly added json package from the list of dependencies for that package:

That works just fine. All of my tests pass and all of my code passes dartanalyzer analysis. Still, the decode/encode names combined with the newness of dart:convert lend an air of not-fully-baked to this change. I will leave it in place in Hipster MVC, but I am in no rush to make the change in my other packages. And I have the feeling that I will stick with the json package and its familiar stringify() and parse() functions in new code—at least until dart:convert has been around for a good long time.

Friday, August 30, 2013

I finally pushed my “real fake” Dart testing server, affectionately know as plummbur-kruk, out to GitHub and Dart Pub. It is in good enough shape that I think it is ready for use to support many of the browser code samples in Dart for Hipsters and in Hipster MVC (the library from the book).

I have published many a package to the http://pub.dartlang.org/, the primary package server for Dart, so that all went smoothly. I wrote up a nice README for the packages, mostly based on usage in Hipster MVC as I replaced previous testing solutions with plummbur-kruk. And it all went smoothly… until I tried to actually use it.

The pub package tool is pretty brilliant. I got Hipster MVC working with plummbur-kruk with a local path dependency in the pubspec.yaml file:

Well, this turns out to be one of the hazards of local development. I had manually created a symbolic link in the lib directory of my local development copy of plummbur-kruk. If I remove that and switch Hipster MVC back to use the local path dependency, then I get the same error.

The symbolic link is, in fact, invalid—the lib top-level directory in a Dart package should not link to the packages directory. As the name suggests, the packages directory contains all of the packages on which a Dart application or packages depends. It also includes a link to itself:

Thursday, August 29, 2013

After mucking a bit with system processes in Dart yesterday, I think today will be a “step back” day. Even though Dart currently lacks a hook to run code when the Dart VM exits, there is still plenty of power in the current Process class. Nevertheless, my initial assumptions when I first started on processes have been proven wrong, so now is a good time to take a look at what I really want to accomplish.

I need scripts that start, stop and (probably one to) clean up by-products of running my “real fake” web server for testing Dart HTTP clients. Rather than thinking of these in terms of how I might accomplish those scripts in the confines of a single Dart process, how might I accomplish them from a Bash script? More importantly, how might I accomplish doing so from a Bash script that is running plummbur_kruk (the name of the “real fake” library) as a package included in another package or application?

In the plummbur_kruk test suite itself, I have a similar Bash script that starts the server with:

dart test/dummy_server.dart &

I can then grab of the process ID of the forked Dart server so that I can kill it later.

That works inside the plummbur_kruk package, but I am going to need to run this from other packages, which means that I need to have my server start/stop/cleanup scripts directly in lib so that I can run them as:

dart packages/plummbur_kruk/server.dart &

And this is where the step back comes in—do I really need to require that programmers using plummbur_kruk start the Dart VM to perform these actions? On the one hand, any Dart developer will have access to Dart, so this is a little more platform independent. On the other hand, does platform independence matter in this case? I think not. I think that the primary use-case of plummbur-kruk is as part of a continuous integration script, which currently runs best on services like drone.io—services that run continuous integration in a Bash script.

So instead of mucking with processes and file system work in Dart, I think Bash is the better tool for this case.

Even though these will be Bash scripts in my Dart package, they will need to reside in the lib top-level directory, which is normally reserved for Dart code. Once installed in another project, only the lib directory is visible (at least presently). To access these scripts from within plummbur_kruk or from another package, I can invoke packages/plummbur_kruk/start.sh.

And that seems to work fairly well. Those scripts even ought to work if copied into another project's test or script directory should a programmer dislike the idea of running Bash scripts from plummbur_kruk's lib directory.

And in the end, I cannot say that I am thrilled with running Bash scripts plummbur_kruk's lib directory myself. But it does beat mucking with managing processes between Dart scripts and still reads fairly well. I will sleep on it, but this seems like a reasonable working solution.

Wednesday, August 28, 2013

I have been trying to keep my “fake test” HTTP server in Dart clean. Not just the code, but the filesystem. The fake test server persists data in dart dirty, which creates a store on the filesystem. I added an onClose callback (callback?!) to the server's listen() call:

In the test runner, it would be OK to manually remove the file. But this is intended to run as part of other test suites. Other test suites should not need to know how to clean up my mess.

This proves exceptionally difficult—at least my first pass at getting this to work does. There seems to be no way to listen for interrupt signals to the Dart VM (at least currently). So my option seems to be forking a process, waiting for it to be killed, and then doing something when it exits. Even that proves tricky in the confines of my test library.

I create a process.dart file as a wrapper to server.dart, which contains the current web server. In there, I use Process.start() to fork the server, then wait for the exit:

When I run that in a separate script that invokes the main() method, I keep getting 255 exit codes:

died with 255

This turns out to be due to the lib in Dart Pub packages lacking a package directory of their own (because typcially this is where package symbolic links point to). For the time being, I manually add a packages subdirectory.

The ‘died’ message comes later—after the server process was killed (but not the parent process). So, in there, I ought to be able to perform and DB / file system clean-up that I need to perform. But that feels awfully hacky. I think it best to call it a night here and ruminate on this approach and the actual use case.

Tuesday, August 27, 2013

I wound up investigating the @proxy code annotation in Dart last night. In a testament to how easily distracted I am, I was looking in the documentation for the @deprecated annotation. In fact, I am about three distractions away from my original intent, which is updating Dart for Hipsters. But I am making progress. Really!

I was investigating the @deprecated annotation as a potential means to deprecate some callbacks in dart dirty. Who needs callbacks when there are Futures around? Well, no one, really, which is why I am deprecating them in methods like close():

It is just as easy, if not easier, to return a Future from that method. Programmers that need to perform an action once file I/O is closed can wait for the Future to complete, then() perform whatever action they desire.

The implementation is just as concise as the old way with the added benefit about being specific when documenting that the Future will complete with a File instance. In addition to being “Dartier,” this will be cleaner to use:

db.close().
then((f) {
// Do something with the DB file here...
});

It is really a no-brainer to switch to Futures. The only question is how to deprecate a single argument.

But that is of no use in this case. I do not want to deprecate the entire method, just the old callback.

Also, if I am relying on dartanalyzer to catch potential static typing and other issues, then I am out of luck with deprecations. As far as dartanalyzer is concerned, there is nothing wrong with calling deprecated methods:

Still, I want to be a good package maintainer, so what are my options?

Realistically, I doubt that many people are using dart-dirty. Even if they are, few would much care for the old callback approach. So I could just change it. I may opt for that approach, but I would like to see what is possible.

If a callback is called, I would like to output a warning of some kind—preferably a scary looking one—indicating that the callback will be going away very soon. But, as a good package maintainer, I still want to call the callback. Most importantly, the return value of close() should be a Future containing a File object.

I opt to modify close() so that it cascades after the Future containing the File object:

The double dot cascade will return its receiver—the result of the previous then() call, which is the Future<File> that I want. The cascaded method will still be invoked and that _deprecateCallback() private method can do what I need it to—print out the obnoxious warning message and call the callback:

To make the message look as scary as possible, it ought to look like a stack trace. It is not possible to directly create stack traces in Dart, but it is possible to throw Errors, which have a stack trace property:

It would have been nice if the context of the original call was included in the stack trace, but alas, futures. Still, this should be sufficient to help library users to understand what needs to be fixed.

After converting any tests that used to rely on the old callback, I run my test suite to verify that no functionality is broken and, more importantly, that dartanalyzer is satisfied that I am not up to any shenanigans:

PASS: new DBs creates a new DB
PASS: writing can write a record to the DB
PASS: reading can read a record from the DB
PASS: reading can read a record from the DB stored on the filesystem
PASS: removing can remove a record from the DB
PASS: removing can remove keys from the DB
PASS: removing can remove a record from the filesystem store
PASS: removing removes from the list of keys in the filesystem store
PASS: removing can delete the DB entirely from the filesystem
All 9 tests passed.
unittest-suite-success
dartanalyzer lib/dirty.dart
Analyzing test/dirty_test.dart...
No issues found.
Analyzing lib/dirty.dart...
No issues found.

That may be a touch of overkill. Then again, I do want to be a good package maintainer, so hopefully this exercise at least puts me in the right frame of mind. But the most important takeaway is that I will never again use callbacks in Dart code.

Monday, August 26, 2013

I need to stay away from the Dart mailing list because there is so much exciting stuff coming out that it is distracting me from what I need to do in order to finish up the next edition of Dart for Hipsters. That said…

Ooh, shiny! There is a new constant in the meta package: @proxy. The purpose is to indicate to tooling like dartanalyzer and the Dart Editor that a class is a proxy class. I believe that this comes primarily from js-interop proxy classes, which can wrap a whole bunch of JavaScript methods and properties in a fairly empty class.

The js-interop package make calling JavaScript from Dart very nice. But is seems to confuse dartanalyzer to no end. I make extensive use of js-interop in the ICE Code Editor to wrap classes from the JavaScript-based ACE code editor (sorry for the name similarity—I had not heard of ACE before I settled on ICE). The result of wrapping those classes is a barrage of dartanalyzer warnings:

➜ ice-code-editor git:(master) dartanalyzer lib/ice.dart
Analyzing lib/ice.dart...
[warning] There is no such getter 'ace' in 'Proxy' (/home/chris/repos/ice-code-editor/lib/editor.dart, line 226, col 16)
[warning] The method 'setFontSize' is not defined for the class 'Proxy' (/home/chris/repos/ice-code-editor/lib/editor.dart, line 295, col 40)
[warning] The method 'setTheme' is not defined for the class 'Proxy' (/home/chris/repos/ice-code-editor/lib/editor.dart, line 296, col 38)
[warning] The method 'setPrintMarginColumn' is not defined for the class 'Proxy' (/home/chris/repos/ice-code-editor/lib/editor.dart, line 297, col 44)
[warning] The method 'setDisplayIndentGuides' is not defined for the class 'Proxy' (/home/chris/repos/ice-code-editor/lib/editor.dart, line 298, col 46)
[warning] The method 'setValue' is not defined for the class 'Proxy' (/home/chris/repos/ice-code-editor/lib/editor.dart, line 300, col 40)
[warning] The method 'getValue' is not defined for the class 'Proxy' (/home/chris/repos/ice-code-editor/lib/editor.dart, line 301, col 31)
[warning] The method 'focus' is not defined for the class 'Proxy' (/home/chris/repos/ice-code-editor/lib/editor.dart, line 302, col 27)
[warning] The method 'getCursorPosition' is not defined for the class 'Proxy' (/home/chris/repos/ice-code-editor/lib/editor.dart, line 307, col 33)
[warning] The method 'gotoLine' is not defined for the class 'Proxy' (/home/chris/repos/ice-code-editor/lib/editor.dart, line 309, col 13)
...
26 warnings found.

In dartanalyzer's defense, the proxy class really does not define these methods, so the warnings are correct. On the other hand, each of these methods is callable once the proxied JavaScript code is ready. Enter the @proxy annotation.

Then, to get back to the specific versions, I pub lish the package even though I have no intention of actually publishing. Instead I publish to get the pre-publish warnings, which include the correct version ranges:

I suppose that is about the same as the proposed @proxy so I will plan on switching over once it is fully baked.

The lesson learn tonight is that I must avoid the Dart mailing list. No wait, that's probably not a good idea. Bah, there is probably no lesson to be learned. Bleeding edge features sometimes are not quite ready, but are still fun to play with.

Sunday, August 25, 2013

Last week on the Dart mailing list, I learned that words like "pants" and "scissors" that have no singular form are called "pluralia tantum." The exquisite Bob Nystrom laid that one on us along with the news that Dart Pub supports both assets and bundles its own web server. Wha?

Saaay. I could use both of those things. In the ICE Code Editor, we have a bunch of example files that we serve with a very simple app.dart server that is also included in there:

I need them in lib so that, when the ice_code_editor packages is installed, the web server will have access to them. Before these recent changes to Dart Pub, only files in lib were visible outside of a package. This seems to be changing, but is is ready for my needs yet? There is one way to find out…

I move all of those non-dart assets into the asset top-level directory:

I am getting excited here! My codebase is all kinds of cleaner because of this. I no longer need the app.dart mini-server. My example pages are still contained in a reasonable place. My CSS, JavaScript, and HTML—my assets—are no longer cluttering up the lib directory of my package. Now lib contains only Dart code and I have a working, well-named placed for assets to go.

Of course...

This is not the real use-case for placing my assets in lib. The reason that all of those assets were in there was so that that they could be visible when served from a static web server (on GitHub pages). And there, I think that my luck runs out.

Symbolic links are a no-no on Jekyll/GitHub pages, so I use a Bash script to de-cache them (the current built-in pub actions do this, but only in other use-cases). If I am already doing that, might I also check for the existence of an asset directory in each package and install that as well?

By way of proof-of-concept, I manually copy the assets from ICE into the GitHub pages ice-beta site:

There are no network errors in the Developer Console and the ICE Code Editor looks to be running perfectly well. It is fairly encouraging that it was so easy to adapt the new assets strategy to my GitHub pages sites.

Even so, this is not a fully baked solution. Some of the work that we have been doing in ICE recently is to allow for more re-use. It does no good to make it easier for other folks to use ICE only to implement an assets solution that requires some post-processing. I may include an internal tool for doing just that. Or I may stick with the web directory only solution for now and await future changes in Pub.

Regardless, I am eager for the next improvements in Pub. And hope that the next announcement will come with similarly useful tidbits of information.

Saturday, August 24, 2013

This may seem an odd confession, but I struggle with operator precedence at times.

I think this is because I don't have a background in computer science and/or have not played extensively with abstract syntax trees, which are a way of representing code in a data structure. It is also due to my obsession with “clean looking” code.

Tonight's adventure started simple enough. I wanted to return a future from the close() method of dart dirty that sent a File object:

/**
* Close the database, including the underlying write stream. Once invoked,
* no more data will be persisted. If supplied, the callback [cb] will be
* invoked with no parameters.
*/
Future<File> close([cb()=_default_cb]) {
return _io.close()
..then((_) => cb())
.then((_) => _db);
}

I cannot simply convert the method cascade (the double dot operator) into a regular method call and return it. The Future returned from _io.close() returns a RandomAccessFile instance (since _io is a RandomAccessFile). So I added the second then as a regular method that would return _db, which is a File.

My thinking above is to cascade the first then(), the result of which is the Future from _io.close(). In my mind, the last line ought to send another then message back to that same future from _io.close(). Now, there are better ways to accomplish what I am trying to do here, but I am setting those aside for a moment because it puzzled me when I tried to use the above code to delete the file in a test:

db.close().
then(expectAsync1((f) {
f.deleteSync();
}));

This failed because the Future contained a RandomAccessFile, not the plain-old File from the last line of my close() method:

In Dart, the method operator (the single dot .) has a much higher precedence than does the method cascade operator (the double dot ..). In my obsessive pursuit for clean code, I am unintentionally giving the impression that both operators have the same precedence:

return _io.close()
..then((_) => cb())
.then((_) => _db);

I have never given this sort of coding behavior much thought. In the other languages that I split method calls onto separate lines (JavaScript, Ruby) there is only a single method invocation operator. Most (all?) other reasons that I would split lines in those languages involve parentheses (multiple parameters, lists, hashes, etc), making the precedence obvious.

I stand by the need to write one method per line. I like to think of this as a 60 character limit on the width of code. However, you phrase it—60 characters wide, one method per line, one concept per line—the idea is the same: do not try to bury complexity in a single line. As deceiving as the above code it, at least it attempts to convey intent. Putting it all on one line is almost intentionally misleading:

In case it wasn't obvious the above is a way to solve my problem. Of course it is not obvious since there is so much information buried on that single line!

The fix above is to reverse the order of the then calls. The first then() is the future that I want—it contains _db, which is the File object that I have declared as the return type of my close() method. Next, I use a method cascade to call the optional cb() callback function. As a method cascade, its return value is its receiver, not its result. In other words, it returns the _db / File future.

If I am to retain this functionality, the question is then, how do I split my method calls across lines so I adhere to the one-concept-per-line rule? I suppose the best way is to further indent the cascade in an attempt to visually indicate precedence:

That is not entirely satisfactory. The diagonal indent is so strange that it catches the eye for the wrong reason.

Really, what my code is trying to tell me is that it is silly to accept a callback and to return a future. I need to deprecate the callback and switch to a future-only solution:

Future<File> close() {
return _io.close()
.then((_) => _db);
}

In the end, I have learned two lessons. First, the one-concept-per-line rule remains inviolate. There is never a reason to break it and if I find that it is hard adhering to it, then there is some refactoring that my code it telling me to do.

The more immediate lesson is that I will never, never, NEVER split lines on different operators. The chance of introducing non-obvious bugs skyrockets. Methods cascades in Dart make it easy to perform many similar operations on a single receiver. If the messages being sent vary significantly, I am breaking the spirit of cascades—and quite possibly some of the precedence rules as well.

Friday, August 23, 2013

I enjoyed exploring function signature parameters in Dart yesterday. It seemed pretty powerful stuff, with just one bit that did not work quite as expected. There was one case in which the dartanalyzer tool was unable to identify a mismatched function parameter. This did not bother me too much, but Kasper Lund asked that I file a bug report. Those folks are pretty intense about getting everything tracked so it can be fixed.

Bug reports really are a simple thing. If you supply every last detail, then you have done a good job. The trick about bug reports is making sure that every last detail amounts to very little information. In other words, boil bug reports down to the simplest case in which the bug can be demonstrated (if possible).

My explanation from last night is an example of a poor bug report. It was little more than, "when I write a method with a function signature parameter, then dartanalyzer does not correctly identify non-function arguments." The example call that I gave is a good example of being the opposite of helpful:

db.close(' *** this is not a function *** ');

It provides no clue as to the context in which it was called (it was of a test) or the manner in which the db variable was created. Now, I could spend a lot of time explaining all of this and describing the changes to dart dirty that were necessary to create the problem, but that is a lot of work for me. As much work as it is for me, it is compounded significantly for the project. Someone has to read it enough to triage it. Someone else will have to read it to fix it. Someone else will have to give the LGTM signal on the fix. And there are probably others.

So instead, I try to boil it down to the simplest version of the bug for submission. I never really tried my problem with a function, so I start there. In a new file, I define a function with a function signature parameter and call it with a non-function:

In the main entry point, I call the doSomething() function three times with different arguments. The doSomething() function accepts a single, optional parameter (square brackets around parameters are one way to mark parameters as option in Dart). The empty parentheses in the cb() parameter indicate that this optional parameter needs to be a function that accepts zero arguments.

The second call to doSomething() in the main entry point is an example of calling it with a callback function with the necessary zero parameters. When the first call is made, only the “something” string in the doSomething() function prints. When the second call is made, both the “something” string from doSomething() and the “callback” string from the supplied callback are printed. The output of the first two function calls is then:

something
something
callback

When doSomething() tries to “call” the string supplied by the third call, the code blows up with a runtime error. The cb parameter was assigned the value of " *** this is not a function *** " which makes no sense when called as cb().

Now, if this this the simplest version of the dartanalyzer bug that I found yesterday, then dartanalyzer will not be able to tell me that there is a problem with the third doSomething() call:

Interesting! So dartanalyzer is able to find these kinds of problems after all. Why then, was I not seeing warnings yesterday?

It turns out to be manner in which I declared objects whose methods contain function signatures. Again, I setup a simple test case, this time a class with a single method accepting an optional method signature:

I find that, if I declare instances of the Thing class with the var keywords (as I did yesterday), then dartanalyzer does not warn me about problems. But, if I declare the object with the explicit Thing type, then dartanalyzer can identify the problem. By way of example, if I change the main entry point to:

main() {
var var_thing = new Thing();
var_thing.act(' *** this is not a function *** ');
Thing known_thing = new Thing();
known_thing.act(' *** this is not a function *** ');
}

Then dartanalyzer will find fault only with the second of the two calls:

Even though the objects are instantiated exactly the same way and the methods are invoked identically to each other, dartanalyzer only does its work if the variable is declared with an explicit type.

To which I say, bleh.

I love the power of dartanalyzer to find problems in my code, but I'll be darned if I am going to start writing all of my code like:

Thing thing = new Thing();

Or even worse:

Thing thing = new ThingFactory().thing;

In my mind, readability trumps tooling, so I am going to stick with

var thing = new Thing();

The redundancy of “thing” is already too much for me in that final example so I would usually take some time to see if either the class or instance needs a better name. I am not going to then turn around and introduce yet more redundancy into my code—even if it does buy me some admittedly useful type analysis.

I admit that an argument could be made that, since I am declaring thing as a variable with the var keyword, I am, by definition, stating that my variable can change type. I would argue that this is almost never a good practice and is worthy of a dartanalyzer warning. Now that factory constructors must return types of the enclosing class, I would further argue that it always possible to infer the type of any new assignment.

Regardless, if the concern in dartanlyzer is that the type is variable when declared with var, what about replacing it with final? If I declare a final_thing, the type will, by definition, not change:

main() {
final final_thing = new Thing();
final_thing.act(' *** this is not a function *** ');
final_thing = 42;
}

In this case, both the call to the act() method with the non-function and the assignment of a final variable should draw the ire of dartanalyzer, right?

So in the end, I do not think that I have a bug on my hand. Last night's work on function signatures as parameters was correct.

Instead, I believe that I have identified a limitation of dartanalyzer. I would certainly prefer it work as I expected—inferring types from the new assignment—and hopefully someday this behavior will change. Until then, it is good to have a better understanding of the limitations of the tool.

Thursday, August 22, 2013

One of the hazards of reading through other people's code is coming across syntax that you do not recognize. OK, so maybe that is not so much a hazard as it is awesome…

One of the things that I found while reading some Dart code was a function parameter that looked very much like a function signature. I don't remember where I first saw it, but it looked something like:

doSomething([cb()]) {
// possibly some code here
cb();
}

As I said, this was new to me, but the intention seems pretty clear: this is a way to document that certain function parameters are themselves functions. Of course, I could be wrong. Even if this is correct, how far can I take this syntax? Can I supply a default function if none is supplied? Can I specify the arity of the callback function? Can I specify types?

It so happens that I need to modify some callbacks in the dart dirty package, so this seems an opportune time to explore some of those questions. I will concentrate on the close() method in dart-dirty, which closes the file in which the dart_dirty noSQL database is stored. Currently that methods looks like:

The square brackets around the cb parameter indicates that enclosed parameters are optional, in the order specified. In this case, there is only one optional parameter, the callback. Now that I look at that method, there is an obvious problem when no callback is supplied to the close() method. Hopefully I can address that here.

First up in my exploration of function signature parameters is to simply add the method signature to the method definition:

void close([cb()]) {
_io.close().
then((_) => cb());
}

The dartanalyzer tool, which performs type analysis on Dart code, thinks that is perfectly fine, thank you very much. If I call close() with a callback function that prints out a message:

db.close(()=> print("close!"));

Then the code runs and print out the message when the DB is closed:

close!

Interestingly, if I call close() with a string instead of a function, I get no warnings from dartanalyzer:

db.close(' *** this is not a function *** ');

Obviously, I get a run time error when I try to “call” the string, but there is no type analysis notifications. I would presume that, at some point in the future, there would be a dartanalyzer warning from this. For now, this seems to be just a convention built into the language.Update: this does work if I declare my db variable with an explicit type.

As I suspected, when I call close() without a callback, it blows up on me (treating null like a function). To fix that, I could add a conditional inside the method:

It is important that the default_cb function be defined outside of the class so that it is a function, not a method. With that, dartanalyzer is again happy, I can now call close() without any arguments, and there are no failures. If I had a suggestion for the Dart authors, it would be that specifying a function signature parameter automatically defaults to an empty function. Still, I cannot complain too much: that code is very clean.

The last question that I have tonight is about arity and types in the function signature parameter. It turns out that I can add types to the optional function signature:

Interestingly, both the type and the arity are enforced by dartanaylyzer in the default option, the actual callback function supplied and the invocation used. The above gives me errors because default_cb does not accept a parameter and because the cb() call does not supply a value:

I also have to update calls to close() so that they supply a callback that accepts a string:

db.close((message)=> print("close! $message"));

This results in the following output:

close! *** dart dirty ***

If the default callback is updated to accept an integer instead of a string (e.g. default_cb(int m){}) or the callback is invoked with an integer dartanalyzer complains about mismatched types.

So in the end, it seems that function signature parameters are supremely powerful. Part of the callback hell from JavaScript with which so many developers suffer is trying to remember the kind of object that is supposed to be sent at various points. If the code is self-documented, especially to the point that simple analysis can be performed, then we are significantly closer to callback paradise than callback hell.

Of course, this should be a fairly rare thing in Dart code since Futures are baked into the core language. In fact, the bulk of what I need to do with close() can be solved by returning the Future from _io.close() instead of fussing with callbacks. Still, it is great to know that these message signatures are there if I need them.

Wednesday, August 21, 2013

When I actually used my “real fake” HTTP test server (code-named plummbur_kruk), I found it wanting. Nothing too horrible, but it does need a few higher-level API methods. Since this is a server for running tests, I will, of course, write tests to verify the new features.

The new features include: (1) a way to create individual records, (2) a way to delete records, and (3) a guard to ensure that all data is removed when the test server restarts. All of this is possible already, but not easy. #1 and #2 are possible via HttpRequest calls. #3 is accomplished by simply removing the noSQL file.

Since all of this is done in Dart, I can immediately try out the results in code that is using my library—before I have even published it to Dart Pub. Dart rocks.

I am using the scheduled_test library here, which makes all asynchronous steps run in serial. In other words, it makes it much easier to keep track of what runs and when. In this case, I schedule the Kruk.create() call to create a JSON record, then I schedule a GET from the server, and finally, I schedule the response from the server (the server is started by the same Bash script that runs the tests).

Just like that, I have a nice Kruk.create() method to create records in my real fake server.

The test and implementation for Kruk.deleteAll() is nearly identical to Kruk.create(). The server supports this operation via a DELETE request to /widgets/ALL. I could have made this more generic to support deletes of individual records, but I do not want to support this unless I know that it will be useful.

Testing that the backing database is wiped in between restarts is a bit trickier. The methods in the Kruk class are all meant to be run in the browser. Code in the browser cannot access the file system, so I am relegated to placing the wiped test file into "dart:io" tests. Happily, I already have some of those, so I can just add this new test in there:

I am also using scheduled test in here. I have to create a number of schedules to start the server, write some data to ensure that the test database will exist, close the server, start up a new instance, and finally check that the database file has been removed.

Getting this to pass is simpler: I tell the server to removeDb() when it closes:

With that, I have the tests passing for the features that I hoped to add. This seems a good stopping point for tonight. Unless I have a problem integrating these features back into the codebase that needs them, I will move on to other topics tomorrow.

Tuesday, August 20, 2013

I think that my fake HTTP test server for Dart is ready to go. To be sure, I am going to try to replace some pretty awful mock HTTP request code that I have been using to test code in Dart for Hipsters.

The code in question is a main() entry point that makes an HTTP GET request of the /comics resource, parses the response as JSON, and uses a template function to populate an UL element:

It is pretty standard stuff that, accompanied by my typically wonderful prose, is easy to follow for existing and new web programmers interested in Dart. The problem, of course, is that MaybeMockHttpRequest junk that is pretending to be an HTTP request object. Before it goes in the book, I have to jump through several hoops to replace it with new HttpRequest(). Even if I did not have to jump through said hoops, this would remain an undesirable situation as I have no way to catch changes to the HttpRequest API.

By default, my fake HTTP test server, code named plummbur_kruk, does not have resources at /comics. Instead it has a REST-like data store at /widget. I have options with this, but I want to get this working first, so I change the GET request to include the server and /widgets path:

I need the SERVER_ROOT because my test is not loaded from the same server with /widgets. My test is loaded from the filesystem, so a root relative URL will not work, hence the need for the full http:// URL. Again, I think that I have options to get around this, but I will explore them once I get this working.

Dang it. This is item #1 that plummbur_kruk still lacks: the ability to easily create /widgets. I am going to need a library interface for this so that I do not have to remember the HttpRequest call every time that I want to do this. Mental note made.

For test teardown, I remove the comics-list UL element and delete all records from the /widgets resource:

(this is a bit of a lie because I also end up adding a slight delay before the expectation to prevent false-positive timing failures)

With that, I have my Dart for Hipsters test running against my “real fake” HTTP test server. But I still have two problems back in the original code: I do not want to include SERVER_ROOT because it unnecessarily complicates the discussion in the book and I want to point to the /comics resource.

The latter is already supported in plummbur_kruk. The Kruk.alias() static method will create an alias in the server:

The Future.wait() static methods waits for both futures—the /widgets population and the alias—to complete before it completes. And, since it is returned from setUp(), the subsequent test will wait until it has completed.

With that, I can rewrite the test to point against '${Kruk.SERVER_ROOT}/comics'. But that is only part of what I want to do. I also want to get rid of the need for the ${Kruk.SERVER_ROOT} in the code snippet. To accomplish that, I can play a trick in the test setup using BaseElement. The <base> element changes the URL root of all elements in a document. In this case, I use it to change the base URL for all URLs in my test:

Monday, August 19, 2013

I have been imbibing heavily as I have driven the development of the ctrl_alt_foo library. So heavily, in fact, that I can't quite remember how I got here. The last thing I remember, I was fiddling around with a library that supplied a test server and now I find that I have been working on a client-side library for keyboard events over the past week. It's so odd…

But I really need that test server library, so I am going to ease my way back into it by incorporating it into the test suite for the code from Dart for Hipsters. Thanks to the amazing power of Dart's pub packaging, that should be quite easy. Dart is just that powerful!

Must. Remain. Sober. In the face. Of overwhelming. Awesome.

Normally I will leave myself a failing test (they are all passing currently) or TODO notes (there are some but they seem done). So the best course of action really does seem to be to try it out in live code. If all goes well, I can publish the library. If not, I will have something to work on tomorrow. This also allows me to get back to the writing of the next edition of the book. Best of all, I can continue to drink of the sweet, sweet nectar of the Pub...

In the pubspec.yaml file for the Dart for Hipsters code, I include a path dependency for plummbur_kruk (the name of my fake HTTP test server):

With that, any changes that I make in the local copy of plummbur_gruk are immediately available to the Dart for Hipsters tests. It is a this point that I realize that I have already done some of this as well. I really need to lay off this stuff…

OK. I may have done that, but I do not have a test that verifies that the plummbur_kruk server is running. If it is down, it might take me precious seconds to realize what has gone wrong—SECONDS I say! So I write a test assuring myself that I will never want for those seconds while working with the Dart for Hipsters code:

And that fails! I am pretty excited because I have finally reached the boundaries of where I was working before I found myself in the pub. This test is failing not because the plummbur_kruk test server is down, but because the plummbur_kruk code is not checking for it properly.

The problem is that my tests are being loaded from the file system (in a file:// web page context), but Kruk.isAlive is trying to access a root relative URL:

I feel a bit like Socrates in Bill and Ted's Excellent Adventure here, because I cannot decide what I love most about San Dimas… er, Dart. Because, wow, do I love slinging them method cascades (the double .. in both code examples above), which invoke a method, but return the receiver, not the return value of the method. So nice for organizing code.

The last thing that I am going to do is be a good tester. I found that plummbur_kruk bug when trying to use it in the Dart for Hipsters application. I need to write a test in plummbur_kruk itself to ensure that I do not introduce regressions at some point down the line. Thankfully, it is not much work to Do the Right Thing™. I already have a Kruk group of tests back in plummbur_kruk. I add my is-alive test to the group:

I have tests that describe establishing those shortcuts and verifying that a generated keyboard event will result in calling the supplied callback method. What I do not have are tests that describe errors: incorrect modifier keys (Ctl+O), incorrect key names (Esca), incorrect formatting of individual shortcuts (Ctrl+O+Shift) and incorrect combinations (e.g. missing a comma in Ctrl+O, ⌘+O).

I believe that these fall under the heading of “errors” in Dart, rather than “exceptions.” The latter are used for runtime situations that are out-of-the-ordinary, but still to-be-expected. That is something of a weak definition as it is something akin to saying that exceptions are extraordinary and ordinary at the same time. Still, they are off the happy path of execution (out-of-the-ordinary), but still need to be handled in some way to prevent an application from crashing. Good examples of those are built right into Dart core: divide-by-zero, problems reading a file, etc.

Errors, on the other hand, are largely compile time problems that can only be addressed by the programmer changing code. A keyboard shortcut of Esca can only be corrected by a programmer changing the code to read Esc.

Complicating this way of looking at exceptions vs. errors in Dart is the FormatException class. It almost seems like it applies to my invalid shortcut keys examples even though it is an exception, not an error. But FormatException is really only meant to be thrown when user or file input is invalid—not when the program itself is invalid. At least, that is my assumption—feel free to correct me if I am mistaken.

In other words, I am not trying to catch invalid I/O or user input, I am trying to catch programming errors. The first error for which I want to test is invalid key names. For those, I test at the individual ShortCut level rather that the higher-level Keys interface that generates instances of Shortcut:

Unfortunately, there is no built-in test matcher throwsError—just matchers for subclasses like throwsNoSuchMethodError. This is why my test explicitly uses a try-catch, leaving it usable, but a little ugly.

As it is, that test actually passes, but for the wrong reason. Currently ShortCut will throw a noSuchMethodError at an obscure place, making it very difficult for programmers to figure out where they have gone wrong. Instead, I would like to throw a custom InvalidKeyName error, which I define in the same file as ShortCut as:

Here, I supply an anonymous function that creates an invalid ShortCut. The expectation is simply that it “throwsInvalidKeyName”. To make that work, I copy-paste-and-modify internal Dart matchers to get:

The instance of _InvalidKeyName and the throwsInvalidKeyName do not strictly need to be compile time constants, but this is the convention in the Matcher library. Besides, it makes little sense to use an ordinary, mutable variable for a matcher.

With that, I have a nice, clear test matcher to go along with my specific and semantically meaningful error. This seems a fine stopping point for tonight. Hopefully the remaining cases will be similarly clean. If not, I will pick back up with them tomorrow.