Category Archives: Uncategorized

The power of reflection

When I was at CppCon 2016 I overheard someone ask “Everyone keeps talking about  reflection, but why do we actually need it?”. A few years before that, I also would have had difficulty understanding why it would be useful. After years of writing D, it’s hard to imagine life without it.

Serialisation is an obvious use-case and almost always the first one anyone comes up with if pressed for an example. But there’s a lot more, like Design by Instrospection. It allows one to write a mocking framework. You start seeing applications everywhere. My favourite way to use it is to make the compiler write code for me.

Let’s say one wants to write a Python extension in native code. Each top-level Python function must have a corresponding C function (well, C ABI at least) that looks something like this:

PyObject* myfunc(PyObject* self, PyObject* args, PyObject* kwargs) {
    // ...
    return result;
}

There are a lot of details to take care of. There’s error handling, managing ref counts, and in all likelihood conversion from and to Python types since in most cases one is usually interested in calling existing pre-written code and make it available to Python. It’s tedious, and I haven’t even shown all the boilerplate to initialise the Python module and register the functions. The code for two simple functions ends up looking like this. Just thinking of clicking that link makes me sigh. Imagine what making calls into a real codebase would look like. We can do better:

import autowrap;
mixin(
    wrapDlang!(
        LibraryName("mylib"),
        Modules(
            Module("mymodule"),
            Module("myothermodule"),
        )
    )
);

The code above, when compiled, will generate a Python extension (shared library) that exposes every D function marked as “export” in the modules “mymodule” and “myothermodule” as Python functions. It’ll even convert their names from camelCase to snake_case. Any D exceptions thrown will become Python exceptions. D structs and classes become Python classses. If the original D functions take a D string, you’ll be able to pass Python strings to them in user code. Modulo bugs, this… works! The code shown above is the only code that needs to be written. Setting up the build system takes more work!

“Only” two D features are used here: the ability to do reflection at compile-time (and therefore to know which functions are in those modules and what types they take and return), and being able to mix in strings at compile-time. All the boilerplate is written for the user and inserted inline as if written by hand, but it’s the compiler that’s doing the heavy lifting.

Imagine now that your boss, pleased with these results, now wants you to also make the same D code avaiable to Excel users. The code changes not one bit, those lines above also work for Excel (the trick is telling the build system to depend on the autowrap:excel dub package instead of autowrap:python). Instead of snake_case functions, one now gets PascalCase as per Excel convention.

Same API, same functionality, different implementation. And no code to write for the user. The curious can see how it’s done on github.

 

Good programmers are humble

The best engineers I’ve worked with all shared the same trait, and unsurprisingly, one that all of the least performant seemed to lack: humility.

By that I don’t mean that they lacked confidence or that they weren’t sure of what they could do. On the contrary, with them I learned that the right attitude when faced with a question of the form “Can we do X?” is always “Of course we can, but is it worth the time/energy/money/…?”.

They were humble in a different way: they were more conscious of their limitations. They assume their code contains bugs, which is why nearly all of them advocate for writing automated tests. They’re ok with not knowing something and admitting that in a meeting, instead of hopelessly wasting everyone’s time.

The ones I’d rather not work with again, on the other hand, think they can write code without bugs. That they can write thousands of lines of C without memory bugs or leaks. That they know where performance bottlenecks are without using a profiler (they didn’t actually know what a profiler even was). That kind of thing.

Good programmers know they’re bad. So they mitigate their awfulness with code reviews, automated testing and tools, tools, tools.

If you think you’re a good programmer, you’re probably not.

CppCon 2017 videos so far

I didn’t get to go to CppCon this year (I was there the previous two years), and now that some of the talks are up on youtube I’ve been checking them out to keep up-to-date. It’s been a little disappointing.

I don’t know if it’s because of the types of talk that I like, if I’ve learned a lot over the last few years or if the standards for admission have gone down. What I do know is that just today on my lunch break I dismissed quite a few talks after watching them for 5 minutes. Some might say that’s not enough, but I think I’m pretty good at evaluating a if a talk would be worth my time in that period.

So far, the only talk I’ve liked is the first one about IncludeOS. For me that’s not surprising, I think it’s a really cool project and have been interested in unikernels from the first time I heard about them. It helps that it happened when I was working at Cisco and learned that the project I worked on then was faster on class Cisco IOS (a monolithic kernel) than on the newer operating systems.

I might have to play around with IncludeOS now. I’m just afraid I’ll start getting ideas about writing a unikernel in D or Rust…

Arch Linux – why use a Docker image when you can create your own?

It seems silly in retrospect. I’d never have considered building an Arch Linux based Docker container in any other way but starting with one from the registry and a Dockerfile. But… it’s Arch Linux, you install this distro into a directory and chroot into it. Why settle for someone else’s old installation?

The script used to bootstrap an Arch install, pacstrap, even lets you exclude some packages from the default install or add things you need. So I ended up with a bash script that installs Arch into a directory, chroots into it and runs commands as required, then bundles the whole thing into a docker container. Repeatable, checked in to version control, and not wasting layers of AUFS.

Who needs a Dockerfile?

Dipping my toes in the property based testing pool

I’ve heard a lot about property-based testing in the last 2 years but haven’t really had a chance to try it out. I first heard about it when I was learning Haskell, but at the time I thought regular bog-standard unit testing was a better option. I didn’t want to learn a new language (and one notoriously difficult at that) and a new way of testing at the same time. Since then I haven’t written anything else in Haskell for multiple reasons and it’s always been something I’ve been wanting to try out.

I decided that the best way to do it is just to implement property-based testing myself, and I’ve started with preliminary support in my unit-threaded library for basic types and arrays thereof. The main issue was knowing how to write the new tests. It wasn’t clear at all and if you’re in the same situation I highly recommend this talk on the subject. Fortunately, one of the examples in those slides was serialization, and since I wrote a library for that too, I immediately started transitioning some pre-existing unit tests. I have to say that I believe the new tests are much, much better. Here’s one test “on paper” but that actually runs 100 random examples for each of the 17 types mentioned in the code, checking that serializing then deserializing should yield the same value:

@Types!(bool, byte, ubyte, short, ushort, int, uint, long, ulong,
        float, double,
        char, wchar, dchar,
        ubyte[], ushort[], int[])
void testEncodeDecodeProperty(T)() {
    check!((T val) {
        auto enc = Cerealiser();
        enc ~= val;
        auto dec = Decerealiser(enc.bytes);
        return dec.value!T == val;
    });
}

I think that’s a pretty good test/SLOC ratio. Now I just have to find more applications for this.

Am I a Mockist now?

I’ve always considered myself on the classicist side of using test doubles. It just clicked with me I guess, and it didn’t help that I’ve not had good experiences with using mocking frameworks. The first time I tried it in Python I ended up asserting different functions were being called in such a way that my test started mirroring the production code, and at that point I stopped. It was clearly the wrong direction, but I at least I noticed. I had the displeasure once to review a test like that once and had to convince the authors it was a bad idea.

I recently bought and read Jay Fields’s Working Effectively With Unit Tests and was finally exposed to how a mockist goes about writing their tests. I was a bit of an eye-openener: the examples and explanations actually made sense, and I started thinking that maybe mockist thinking wasn’t so bad. What was really surprising to me was that using mocks was described as testing behaviour instead of state: I’d always thought that the downsides of mocks were that they tested implementation instead of behaviour. I started realising that well-written mockist tests just get to the same destination by a different way. I’d just never seen well written tests with mocks before.

Coincidentally, just after I’d finished that book I listened to a podcast interview with J.B. Rainsberger of Integrated Tests are a Scam fame. I heard him say something I’d never heard before: “Don’t mock types you don’t own”. That was also eye-opening: everything that made mocking bad in my eyes suddenly disappeared. If you’re only ever mocking types/functions under your control, then testing implementation isn’t such a bad thing, you can always refactor the implementation of the code you own without tests breaking. No more brittle tests and no more writing test doubles by hand.

I tried it out recently at work and I was actually pleased with the result. Am I a mockist now? I don’t know. Even though I used mocks I ended up with a hybrid approach for some tests, so I guess I’m just trying to use the right tool for the job. Which is always a good thing, right?

Prototyping is useful after all

Python is said to be a great prototyping language, I guess because types don’t have to be written down explicitly. I’ve never really gotten why someone would want to do that. Even after reading Code Complete I felt like it sounded like a good idea but also maybe… a waste of time?

I think I’ve just changed my mind. I’ve been struggling at work for a couple of weeks now with some new C code. It’s not just that it’s in C, there’s also some infra I’d never used before to work out as well. I felt like my head was clouded by implementation details that I had to consider at every step, so I tried something different: write it all, from scratch, in D.

Why D? Two reasons. First, it’s my favourite language. Second, the syntax is similar enough that a translation of the solution to C should be straightforward. One hour later I’d not only implemented everything I wanted, but now knew exactly what I had to do in C-land. Which, of course, will take much longer than an hour.

Still, I’m now wondering why I took so long to prototype my solution. It could’ve saved me two weeks of mostly unproductive work. The problem is too hard to solve in your current environment? Solve it somewhere else where it’s easy and translate later.

The Reader monad is just an object

I found myself writing some code like this a week or two ago:

string testPath = ...;
func1(testPath, ...);
func2(testPath, ...);
...

I thought it was annoying that I had to keep repeating the same argument to every function call and started thinking about ways that I could automatically “thread” it. By just thinking that word I was taken to the world of Haskell and thought that the Reader monad would be great here. I even thought of implementing it in D, until I realised…  that’s just an immutable object! I don’t need a monad, just a struct or a class:

struct Foo {
    string testPath;
    func1(...) const;
    func2(...) const;
}

In most OOP languages I don’t need to pass anything when func1 or func2 are called, and they both implicitly have access to all the instance variables, which is exactly what I wanted to do anyway. In D I can even get something resembling Haskell do notation by writing the client code like this:

with(immutable Foo()) {
    func1(...);
    func2(...);
}

(as opposed to):

auto foo = immutable Foo();
foo.func1(...);
foo.func2(...);

I can’t believe it took me this long to realise it, but the Reader, Writer and State monads are just… objects. Reader is immutable, but I just showed how to get the same effect in D. It’d be similar in C++ with a const object, and the lack of the with keyword would make it more verbose, but in the end it’s very similar.

DConf2016 report

DConf 2016 happened last week in Berlin. As usual it was really cool to be able to attend and talk to so many great developers from around the world.

There weren’t really any earth-shattering announcements. The only thing that comes to mind is for-now anonymous donor offering the D foundation half a million dollars as long as there’s a plan to spend that money. That’s great news and I’m looking forward to hearing what that money will be spent on.

The talks were great, of course: they should be available soon enough so the details aren’t really needed. My favourite was probably Don’s talk on floating point numbers. I’ve read the IEEE spec and I still learned a lot.

And there was my lightning talk. I only found out about the schedule an hour before, which was the amount of time I had to write it. After a stress-filled hour passed, I learned that they didn’t have a VGA cable and had another cortisol spike as I tried to figure out some sort of solution. In the end I ssh’ed from a German Mac into my laptop, to sometimes hilarious consequences, with me ad-libbing with no brain-mouth filter for a few minutes. I need to see the video once it’s available to see how well I did…

Some code you just can’t unit test

My definition of unit tests precludes them from communicating with the outside world via the file system or networking. If your definition is different, your mileage on this post may vary.

I’m a big unit test enthusiast who uses TDD for most code I write. I’m also a firm believer in the testing pyramid, so I consider unit tests to be more important than the slower, flakier, more expensive tests. However, I’ve recently come to the conclusion that obsessing over unit tests to the detriment of the ones higher up the pyramid can be harmful. I guess the clue was “obsessing”.

In two recent projects of mine, I’ve written unit tests that I now consider utterly useless. More than that, I think the codebases of those two projects would be better off without them and that I did myself a disservice by writing them in the first place.

What both of these projects share in common is that they generate code for other programs to consume. In one case, generating build systems in GNU Make or Ninja, and in the other converting from GNU Make to D (so, basically the other direction). This means writing to files, which as mentioned above is a unit test no-no as far as I’m concerned. The typical way to get around this is to write a pure function that returns a string and a very small wrapper function that calls the pure one to write to a file. Now the pure function can be called from unit tests that check the return value. Yay unit tests? Nope.

Add another section to the output? Your tests are broken. Comments? Your tests are broken. Extra newlines? Your tests are broken. In none of these scenarios is the code buggy, and yet, in all of them N tests have to be modified even though the behaviour is the same. In one case I had passing unit tests checking for code generation when the output wouldn’t even compile!

If your program is generating C code, does it really matter what order the arguments to an equals expression are written in? Of course not. So what does matter? That the code compiles and has the intended semantics. It doesn’t matter what the functions and variables you generate are called. Only that if you compile it and you run it, that it does the right thing.

Code that generates output for another program to consume is inherently un-unit-testable. The only way to know it works is to call that program on your output.

In my GNU Make -> D case I was lucky: since I was using D to generate D code, I generated it at compile-time and  mixed it back in to test it so I had my unit test cake and ate it too. Compile times suffered, but I didn’t have to compile and link several little executables to test it. In most other languages, the only way forward would be to pay “the linker price”.

Essentially, my tests were bad because they tested implementation instead of behaviour, which is always a bad idea. I’ll write more about that in a future post.