Showing 10 most recent posts. Older posts are in the archive.

I used to think commenting code extensively was vital to code readability. I no longer think that is true. There are far better solutions for making code more readable.

When you start practicing Test Driven Design, you start to pay more attention to refactoring. Refactoring is a key activity in TDD because the goal is to pass the test as fast as possible without thinking too much of the elegance of the solution. When the tests pass you refactor. The purpose of the refactoring is to avoid taking huge technical debt so that at any given moment the code is as extensible and readable as possible.

Code commenting does the opposite. It makes the code harder to modify. Comments won't survive the refactoring because you have to remove or edit them to match the new implementation. Then the worst happens and you make a mistake in a comment. This mistake is never caught by the compiler or the runtime. Comments are bound to be incorrect.

While reading about Donald Knuth's literal programming in Coders at work I came to realize how different literal programming and TDD are. In some ways, Literal programming is the opposite of TDD. Knuth describes how he doesn't extract subroutines into real subroutines, but merely comments some parts of bigger subroutines. In TDD we add comments after we've tried to make the code as readable as possible by refactoring. A comment is the last resort to make the code more readable. In literal programming, commenting is the main tool for achieving readability. In TDD we write the test, code and then add a possible comment. In literal programming you explain yourself first with comments, then write the production code. (Knuth didn't even write the code on a computer, instead he wrote the whole program [TeX] on paper first.) Literal programming can increase readability, but it's the arch enemy of refactoring.

Code readability is very important. In fact, it's one of the Rules of Simple Design. How do we increase the readability of our code then, if not by commenting? We use the programming language itself. Modern programming languages like Ruby and Python allow you to write very expressive code. Create small methods, no longer than a few lines and use descriptive names. Use Extract Method on a commented block of code and you're much better off. Additional method calls hardly have any performance impact. I guarantee your bottlenecks are somewhere else.

Certainly there is a place for comments. When should you add a comment? Code that justifies a comment is one that is not tied to the implementation, one that survives trivial refactoring. Such place could be a particularly nasty Regular Expression or a data structure that is an important part of the architecture (such as Domain objects). In general: if you just cannot express your intent with code, consider adding a comment.

Old post by Michael D. Hill on the XP mailing list. These are also some of the reasons I like XP. It keeps things real, while at the same time embracing good engineering practices. Read the whole thing.

  1. Unbelievably complicated unit testing frameworks: You don't need them. You need the ability to write a test function, add it to a list of test functions, and call them. How long will it take you to write that code? Four hours? Six? Write it. Over time you may see other things that will be handy, but you don't need them now.

  2. Corner cases you've invented where the XP method seems to have contradicted itself: You don't need them. If you really encounter them in the field, which for the most part I seriously doubt you ever will, here's how you solve them. 1) Pick one interpretation or the other. 2) Implement it. 3) Try it. 4) If you don't like it, change it until you do. 5) If you can't change it enough, pick the other interpretation.

  3. Unbelievably-difficult-to-unit-test classes you've created: You don't need them. If it can't be unit-tested, it can't be a stable central part of your code, so throw it away. Divide one staggeringly complex object into thirty dead simple ones. Unit test them.

  4. Umpty-nine-levels of inheritance and abstraction with private inner reverse-schreck semiotic slipsoid sub-class interactivity devices that make your design impossible to even describe, let alone debug: You don't need them. I am truly staggered to hear how many folks are using the arcana of their programming environments rather than the mainstream.

  5. The generic solution to all problems having to do with a generalized and abstract class representing XXXXX's: You don't need it. You need a class representing XXXXX's AS SEEN BY YOUR CUSTOMER'S USER STORIES. Code one. Forget about dividing the world up into philosophically correct hierarchies. Divide the problem into pragmatically correct ones.

  6. Unit tests that are designed to prove that your object will survive a thermonuclear blast: You don't need them. Unit tests should be renamed object tests, an argument I'll take up later. Write a unit test to test ONE object, not all that objects that one talks to. If you cannot find a way to do it, your object is almost certainly too complicated. Simplify it, and try again.

  7. Unit tests that are really functional tests: You don't need them. The functional tests prove that everything works together to satisfy the customer's stories. The unit tests do not exist to prove that your program is correct. They exist to make your work faster and easier. Pretend your object is floating in a petri dish, not in a live cell. Test it without testing its neighbors. If you can't, re-write until you can.

  8. Paint-scraper programs that capture and test screen output for form-based apps: You don't need them. De-couple all program functionality from UI functionality. Unit-test it. Write generic client-controls that use generic data-servers. Unit-test them. Derive concrete data-servers connected to your model. Unit-test them. Build forms by connecting clients to servers. Unit-test them for tab-order and screen-layout. Get your functionals to 100%. Ship. Wait for stock options to mature.

2010 11 04PHP and assertions

I want to make Sham itself to throw Exceptions. Currently you need to use whatever testing framework you are using for asserting. This means that for example with PHPUnit your assertions will look something like this:

$this->assertTrue($stub->calls('method', 'param 1')->once());

This is too verbose.

To integrate with PHPUnit correctly I would need to throw PHPUnit_Framework_AssertionFailedError exceptions. This would make Sham assertions report correctly as failures, and not as errors. However, I don't want to integrate only with PHPUnit, I want Sham to be as simple and generic as possible.

What we need is an AssertionException class in PHP's itself. This small addition would make testing tools play nicely together. PHPUnit would extend AssertionException and so would Sham. We would all have the same meaning for a failing test.

This kind of thing would be easy to implement in PHP, but as far as I know there is no way of implementing anything in PHP that would be included in PHP. That is, all the SPL classes are implemented in C.

Assert

Taking this a bit further, there should also be something in PHP that would throw these AssertionErrors. For this I propose the assert keyword. The assert statement would look like this:

assert <expression>;

If the expression evaluates to false, an AssertionException would be thrown.

Yes, there's assert(), the function, but it's hideous.

Maybe I'll pick up my dusty Extending and Embedding PHP someday and whip up a patch. Until then, any takers?

Io is amazing. Here's a (naive) JSON interpreter in Io.

JSON := Object clone do(
    curlyBrackets := method(
        call message arguments foreach(msg,
            self setSlot(
                call sender doString(msg name),
                JSON clone doMessage(msg next ?next)
            )
        )
        self
    )

    squareBrackets := method(
        call message arguments map(a, JSON clone doMessage(a))
    )
)

JSON clone do(

    {"key" : "value",
     "list" : [1, {"nested" : 42}],
     "nest" : {"key2" : "value2"}}

) slotSummary println

As you can see, the JSON within the do() block is not a string, it's literal JSON which is valid Io syntax.

$ io json.io
 JSON_0x383220:
  key              = "value"
  list             = list(1,  JSON_0x2b1020:
  nested     ...
  nest             = JSON_0x2d12e0

Here's a little project I've been working on. It's a debugging/profiling console for Solar applications. I call it Starburst_Debug_Console. It displays a console on top of your website which shows you your SQL queries, logs and $_SERVER vars.

SQL Profiler for
Solar

You can download it by clicking here. There's install instructions over at the project page. Yep, that's git, go ahead and fork it!