Saturday, May 31, 2008

News on Assessments

What can happen when you feel good and happy is amazing...

First, I was happy already because today I nixed my first segfault of the 64 bit VM. Moreover, I was on a roll fixing detail after detail, test after test, etc. All this made me get into that state...

So I went for dinner and brought my laptop over thinking I'd so some Assessments work. Here is a summary of what happened.

  • A third way to do file logging emerged. A dose of the usual, strong mandatory refactoring ensured that no code was duplicated anywhere.
  • In order to support the debugging tools (and also some absolutely fantastic items in the to do list) I needed classes that I could not put in any hierarchy. So I employed the technique I used in the Hash Analysis Tool, by which one creates a class the instances of which behave like the classes one would like to have. With just a handful of methods, I created the (more or less) equivalent of virtual TestCases.
  • Once those were done, then I did a bit of refactoring to refine the way in which Assessments evaluates check lists. Now it can run checks to failure (the [run to error] button in the test runner), and also pop up a debugger right at the beginning of the test (the [debug] button in the test runner, only skipping all the evaluation machinery and running into its own stack).
  • Obviously, there are check lists for all of that, and therefore Assessments assesses itself.
Then I decided to run some metrics to see how I was doing. At that point I was thinking that code quality was very very high, both because of how the code looked and also because of the ease with which modifications like the ones above just fit in without making a mess. But you never know because of the usual objections to our own subjective measurements, so...
  • 394 methods in 74 classes and 3 class extensions, or slightly over 5 methods per class / class extension on average.
  • Tbe fileout is less than 135000 bytes long, which translates into under 350 XML fileout bytes per method on average.
While I didn't see a one minute way to count lines per method, I did find this interesting expression.

assessmentsClasses inject: 13 @ 3 into: [:t :x | t x + x selectors size + x class selectors size @ (t y + 1)]

This gives 394 @ 77, the numbers featured in the statistics above. Sorry about the variable names t and x... on the other hand it's what I use for throw away code.

More to come...

Friday, May 30, 2008

Assessments does file logs

I have been under the weather and having to spend time doing pretty much nothing, waiting patiently to feel better... sigh, what a waste of time...

Now that it's over and I am back being able to think, I did a bit of work on Assessments. Now they do file logging too, and I am happy to report that the design strategy allowed this to happen without causing any major modification to the framework. In fact, this is so much so that Assessments supports two logging policies: a fast one in which the file is kept open while the checklists are evaluated, and a hardened one in which the file is opened then closed for each line written to it.

Needless to say, attaching things like Toothpick to this is child's play and doing such a thing would not entail any overrides or forceful changes to the implementation of Assessments at all.

Next up, I need some tools. More news to come.

Sunday, May 25, 2008

About layout engines

Michael put up this post in his blog. In it, there is the assertion that several ways of doing widget layout are incompatible with each other. In particular,

So what is the end result of these four different layout models [fixed, stack/grid, constraints, flow]? Well, for one, they're all completely incompatible with each other.

I beg to differ. Back in 2000 while at Exobox I wrote a layout engine for Morphic which, based on a tree of nodes which affected how their children would be laid out, was quite capable of doing fixed, stack/grid and constraint based layout (plus arbitrary coordinate geometry), all in the same UI. It did not do flow because it was not a requirement and as such it never came up.

As an example of what this layout engine can do, one of the demos was managing a spreadsheet of 64x32 cells, each of which had its own text morph, supporting columns and rows of variable size by changing the width/height of the header cell only, and all of this using quad trees embedded in the layout tree so as to avoid Morphic work when cells were outside the viewing area. No problem at all.

Therefore, in my opinion, these models are not incompatible with each other. The proof of this is an actual, working example driving production applications.

In more abstract terms, the interesting cases of layout problems are solved in a finite number of operations, and as such the individual operations are in a well ordered set. Once they are in a well ordered set, putting them in a tree that respects the order of evaluation (perhaps having nodes / leaves appearing in the tree multiple times) is more or less straightforward because each node of the tree could be a representation of a distinction made by us regarding the layout algorithm (this part, that part, etc).

The simplest way to do this would be with a 1-level deep tree in which the root node has leaves each of which represent each particular step (taken to extremes: a root node with a single leaf representing "do everything").

As a side note, integer linear programming problems are NP (one such problem is the Minesweeper Consistency Problem, which is NP-complete). As such, I suspect that some layout problems can be NP-complete as well (mod rounding the solution to a general linear programming problem).

See also Vassili Vykov's post here for more references regarding UI layout.

Saturday, May 17, 2008

More on Assessments

Heh, I just realized that by its very design, Assessments will run the checks in random order without even explicitly meaning to do that. Too funny...

Progress on Assessments

The other night I was working on Assessments and something that was bothering me about their implementation. The thing is that for the sake of simplicity I did the reference implementation using exceptions to notify the assessment engine that a check had passed. Running that through a profiler showed me once more that exception handling is comparatively expensive.

In other words, raising an exception should be something truly exceptional, for otherwise the performance hit associated with handling it can be quite stiff. This clearly shows up in profiler runs, particularly when the code being wrapped in exception handlers executes quickly. In these situations, exception handling can easily dominate the execution cost.

One of the design goals of Assessments is to allow a lot of flexibility in how assessments are evaluated --- or, in SUnitesque, how test cases are run. So I thought a good measurement of whether the implementation was actually as flexible as I had meant was to address the performance issue by having a different way to evaluate assessments to coexist with the original one.

The implementation passed the stress test successfully. The change involved a new class and providing a refinement of 3 methods. What's best is that the existing assessments for Assessments itself could be easily refined to test the new evaluation mechanism too with minimal change to the testing code thanks to inheritance and the use of parallel equivalent test hierarchies (see Chapter 3 of the mentoring book). This is good because the fact that the same assertions are being made allows to prove that both evaluation mechanisms behave in exactly the same way, despite the fact that they handle passes quite differently.

Proper implementation of the tests are just as important as proper implementation of the feature.

Saturday, May 10, 2008

About comments

Once more, I found a questionable code comment of the irritating variety. Basically, I ran into a method like this.

    "The code should do this"
    self butTheCodeTurnsAroundAndDoesSomethingElse.

Now that is helpful... so I just fixed it by deleting the comment and having the code do what the comment was suggesting, which was the appropriate thing to do in the first place.

However, imagine for a moment that you do not look at the code and just look at the comments --- such as when you look at some API documentation for which you are not given the actual implementation. So you read "the code should do this", and then you get the idea that it really does. Wrong!

If you do not have the code to check, well that is unfortunate and it has to be dealt with. But what if you do have the source code? Wouldn't you look at it? After all, what if the comment is wrong? Or what if the code has a bug?

This is where comments start losing their appeal to me. We developers are supposed to be well trained in reading code. What is this business of choosing not to look at code but instead looking at some commentary that may or may not be an accurate description of what the code is doing? And, if after you read the comments, you go look at the code anyway... what was the benefit of reading the comments?

Seriously: if you have available source code, and nothing is funny about it (e.g.: choice of magic constants), why look at comments at all? Or, more strongly perhaps: why would developers, of all people, choose not to look at code?

So... if programmers avoid reading code, then who is supposed to do the actual programming instead?

Progress on Assessments

It had been a while since I last worked on Assessments, and today was the day when I got back to them. What's funny is that I had forgotten what the code looked like, so I was quite gladly surprised to find code nuggets I didn't remember. I chuckled a number of times at some beautiful methods, hehe :).

I just finished the feature tests for Assessments, written in Assessments. I am happy about this, because it means that now I can start building tools for it. Also, something I have in mind is an SUnit bridge so Assessments can run SUnit test cases without needing to make any modification to the existing TestCase hierarchy. After that, I will also make Assessments run SUnit VM test cases, including SUnit Based Validation and SUnit Benchmarks code. Hopefully all will go well.

To be continued...

Saturday, May 03, 2008

More stuff done

I just finished chapter 3 of the fundamentals book. The draft currently has 110 pages.

As it turns out, the draft had reached 102 pages last weekend. This means I did 8 high quality pages, plus some polishing to what I had written last time, in about 3 hours. While it's not the fastest I've written (the record is 15 pages in 4 hours), it's not bad either...

Thursday, May 01, 2008

New month, more work

Last weekend I predicted the fundamentals book draft would reach 100 pages, and indeed it go to be 104 pages long. And, all of a sudden apparently, it has become the month of May. With it, comes yet another deadline that will take time away from the books for a while.

I should hire staff so I can delegate the fluffy work...