Category Archives: Uncategorized

cppcon 2015: day one

The first day of the conference is over, and the highlight for me was definitely Bjarne talking about GSL and statically verifying that there are no dangling pointers.

I have to say I’m sceptical: if a C++ library solution can do the job, why does Rust exist? It sounds like too much of a free lunch to me, but I guess I’ll have to wait until the tool he talked about is ready and use it.

I also learned that I’m doing a lightning talk tomorrow on Emacs as a C++ IDE, which means that now I have to actually write that talk! I’ll have another blog up tomorrow about day 2.

Haskell: unexpectedly making it harder to unit test

Surprised by the title? So was I.

Haskell is a pure functional language devoid of side-effects that gets work done by instead describing those side-effects. All of the code that deals with the outside world is tainted by IO in the type system, forever to be shunned, a pariah with regards to the rest of the program. This is touted as one Haskell’s strengths, and rightly so. But recently, it got in my way.

My go-to task to learn a new programming language now is to implement an MQTT broker. That was in fact, the subject of my very first post. So that’s how I attacked learning Haskell. Some time later, I had a nasty bug and concluded that my problem had been too much logic in the IO monad. I started refactoring like mad, writing new unit tests and making sure most of the program logic was in pure code. It took a while to realise… I couldn’t.

I went fancy in my testing endeavours and almost wrote a blog post about it. I abstracted away how bytes were to be acquired and wrote a function with this signature:

replyStream :: (Monad m) => a -> (a -> m BS.ByteString) -> Subscriptions a -> m [Response a]

The reason for that ‘a’ type parameter is that in production ‘a’ is a Handle to read from, and in tests, ‘a’ can be any type I want, just to check the logic (I used Int). The part I was proud of was the second parameter: a monadic function that maps a handle type to a bytestring in a given monad. In production, the monad would be IO, in tests, I used the State monad and fed it the “packets” I wanted. My idea was to construct an infinite lazy byte stream for each client, feed it to a function that would produce an infinite lazy list of MQTT messages by calculating where the byte boundaries were and in turn give it to replyStream, which would get more bytes from the passed-in function. Code reuse! Abstraction! No IO!

But then… I tried making this work with the existing networking code, at which point I realised I couldn’t. Not if I wanted the server to work as it should, anyway. My approach would have worked if only there wasn’t any global mutable state in the MQTT protocol, but there is. What one client sends affects what the other clients might receive. Which means I can’t just use State to thread what the subscriptions are from message to message in the stream, since every message might have to change the global state, which alters how the server processes messages from different clients. The streams aren’t independent.

What’s a Haskell programmer to do? As far as I know, the Haskell options for global mutable state are IORef, MVar and TVar. If there are other options, please let me know. And here’s the kicker: no matter which one is chosen, they all require the IO monad to get any work done. Which meant whatever code I wrote to process messages would be IO-tainted and therefore, not testable in a pure way.

I’m sure there’s more than one way to skin this particular cat. I considered using TVar and two monads for replyStream so that in production it could be STM returning IO, but that just seems unnecessarily complicated. I already dislike the fact that I made my functions generic on the handle type, and using two monads, monad transformers or what-have-you is just too much complication and abstraction in production code and all “just” for testing. I gave up, moved the logic to the IO portion and called it a day.

For once, this would have been easier in run-of-the-mill imperative language. Handle type? Just cast from int in tests. Unit testing without side-effects? Easily done in the D version. How? Regular global mutable state. No hoops, no monads, just easily readable code.

Haskell: you’ve let me down. It may well be there’s still an idiomatic way to accomplish what I wanted to do. Even then, it isn’t obvious at all and that would also be a failure.

Published my first ruby gem

All in all, it was a lot less painful than my experience with PyPI. Especially since the gem showed up soon afterwards. I think PyPI took days…

Here’s hoping someone will use it!

C is not magically fast

I always wonder why people think there’s a mystic quality to C that makes it insanely fast. It’s just assumed to be true by many people, and I really can’t understand why in the face of vast amounts of evidence to the contrary and well, logical reasoning. Just last week a blog post expressed surprise at a benchmark they’d conducted themselves because (paraphrased) “in theory, the C implementation should be faster”.

There are so many problems with this belief. First of all, the fact that Fortran has been beating C since… before C existed, given that Fortrain is the oldest language still in use (depending on your definitions of “old” and “in use”). I guess some people don’t know Fortrain is still important in HPC today?

Secondly, there are languages that are a superset, or close enough, of C, such as C++ and D. Even if somehow, like red vehicles, C were always faster, all one would have to do is rewrite the bottlenecks in C syntax. The AST would be the same, and if using the same backend (gcc or clang, say), why would the assembly output be any different?

Thirdly, and much more importantly, the lack of measurements to accompany that belief or ignoring existing ones. What else can you say?

Maybe part of it is the fact that writing C is so slow and painful. There has to be a reward for it, right? The truth however, is likely to be much closer to doing crunches: annoying, time-consuming, and won’t even give you abs.

On debuggers and printfs

I, like pretty much every other human on the planet, like to over-generalize. In keeping with tradition, there seems to be another schism amongst programmers, which is the ones that use printfs to debug and the ones that use debuggers.

Debuggers are magical things, they basically give you a REPL for natively compiled languages that don’t have one. I think every programmer should get acquainted with them, to least know what they can do. Write printfs if you want or must, but at least be aware what’s on offer from “the other side”.

As much as I like debuggers however, sometimes I find it easier to do log-based debugging. Sometimes it’s even necessary. The last one I worked on at work was a timing issue; breakpoints aren’t going to help with that.

Line coverage isn’t as important as most people think

Controversial, I know. Let me start by saying this: I think line coverage tools are useful and should be used. But I think most people get a false sense of security by shooting for what I think are meaningless metrics such as achieving x% line coverage.

One of the problems is coupling: good tests aren’t coupled to the implementation code and one should be free to change the implementation completely without breaking any tests. But line coverage is a measurement of supposed test quality that is completely dependent on the implementation! If that doesn’t sound alarm bells, it should. I could replace the implementation and the line coverage would probably change. Did the quality of my tests change? Obviously not.

Another problem I’ve seen is that code coverage metrics cause people to write “unit tests” for utility functions that print out data structures. There are no assertions in the “test” at all, all it does is call the code in question to get a better metric. Is that really providing a stronger guarantee that the software works as intended? Beware the cobra effect, and, as nearly always, Dilbert has something to say about the danger of introducing metrics and encouraging engineers to make them better.

Last week at work I encountered yet another real-life example of how pursuing code coverage by itself can be fruitless endeavour. I wrote a UT for a C function that was something like this:

int func(struct Foo* foo, struct Bar* bar);

So I started out with my valgrind-driven development and ended up filling up both structs with suitable values, and all the test did was assert on the return value. I looked at the line coverage and the function was nearly 100% covered. Great, right? No. The issue is that, in typical C fashion, the return code in this function in particular wasn’t nearly as interesting as the side effects to the passed-in structs, and I hadn’t checked those at all. Despite not having tested that the function actually did what it was supposed to, I had nearly 100% line coverage. By that metric alone my test was great. By the metric of preventing bugs… not so much.

So what is line coverage good for? In my opinion, identifying the gaps in your testing. Do you really care if no test calls your util_print function? Probably not, so seeing that as not covered is ok. Any if statement that isn’t entered (or else clause) however… you probably want to take a look at that. I tend to do TDD myself, so my line coverage is high just because lines of code don’t get written unless there’s an accompanying test. Sometimes I forget to test certain inputs, and the line coverage report lets me know I have to write a few more tests. But depending on it as a metric and seeing higher coverage in and of itself as a goal? That’s not something I believe in. At the end of the day, code with 100% coverage still has bugs. The important thing is to identify techniques for reducing the probability of writing buggy code or introducing them into code that worked.

If you’re interested in a thoughtful analysis of code coverage, I really enjoyed this article.

Binary serialisation made even easier: no boilerplate with Cerealed

I abhor boilerplate code and duplication. My main governing principle in programming is DRY. I tend not to like languages that made me repeat myself a lot.

So when I wrote a serialisation library, I used it in real-life programs and made sure I didn’t have to repeat myself as I had to when I wrote similar code in C++. The fact that D allows me to get the compiler to write so much code for me, easily, is probably the main reason why it’s my favourite language.

But there were still patterns of emerging in the networking code I wrote that started to annoy me. If I’m reaching for nearly identical code for completely different networking protocol packets, then there’s a level of abstraction I should be using but failed to notice beforehand. The patterns are very common in networking, and that’s when part of the packet contains either the total length in bytes, or length minus a header size, or “number of blocks to follow”. This happens even in something as simple as UDP. With the previous version of Cerealed, you’d have to do this:

struct UdpPacket {
    ushort srcPort;
    ushort dstPort;
    ushort length;
    ushort checksum;
    @NoCereal ubyte[] data; //won't be automatically (de)serialised

    //this function is run automatically at the end of (de)serialisation
    void postBlit(C)(ref C cereal) if(isCereal!C) {
        int headerSize = srcPort.sizeOf + dstPort.sizeof + length.sizeof + checksum.sizeof;
        cereal.grainLengthedArray(data, length - headerSize); //(de)serialise it now
    }
}

Which, quite frankly, is much better than what usually needs to be done in most other languages / frameworks. This was still too boilerplatey for me and got got old fast. So now it’s:

struct UdpPacket {
    //there's an easier way to calculate headerSize but explaining how'd make the blog post longer
    enum headerSize = srcPort.sizeOf + dstPort.sizeof + length.sizeof + checksum.sizeof; 
    ushort srcPort;
    ushort dstPort;
    ushort length; 
    ushort checksum; 
    @LengthInBytes("length - headerSize") ubyte[] data; 
    //code? We don't need code 
}

That “length – headerSize” in @LengthInBytes? That’s not a generic name, that’s a compile-time string that refers to the member variable and manifest constant (enum) declared in the struct. The code to actually do the necessary logic is generated at compile-time from the struct declaration itself.

Why write code when I can get the compiler to do it for me? Now try doing that at compile-time in any other language! Well, except Lisp. The answer to “can I do ___ in Lisp” is invariably yes. And yet, not always this easily.

Cerealed is on github and is available as a dub package.

CppCon 2015

I submitted a talk proposal to CppCon for this year’s conference but unfortunately I won’t be speaking. According to the reviewers, my abstract was too vague so I guess I’ll have to detail everything next time around.

I was going to talk about how to leverage C++14 for unit-testing legacy C code. You could use C to unit-test C code, but C++’s near-perfect backwards compatibility and its many, many features make writing the test code a lot easier.

I’m going to try to go to the conference anyway. Maybe I’ll get a lightning talk in presenting my Emacs package for C and C++ development.

The importance of setting a good example

Most developers will pay just enough attention and do just enough work to get their current task done. To that end, and to reduce mental burden, whatever patterns the current codebase does are copied/extended/emulated. After all, most development work consists of changing existing code to do something else as well as whatever it did before.

As I mentioned to a colleague once, “code cruft happens little by little, never in one fell swoop”.

So it’s important to set a good example by not doing things the hacky way. Or, at least, by not leaving the code hacky by the time the next developer looks at it. The other day at work I implemented a proof-of-concept by modifying my carefully designed pristine code and, because it was easier, added a global variable to get the job done. It was a quick hack, I knew it was a bad idea and I could always fix it later, right?

Fast-forward a few weeks and 2 other developers had been working on this code. Now we had a dozen global variables. The two other devs aren’t bad at what they do; but having had a global there in the first place caused new ones to grow. Bad ideas are infectious.

So be sure to try and do things the right way. Other people will copy the patterns you write, whether good or bad.

My DConf 2015 talk: Behaviour-Driven Development with D and Cucumber

Here’s my DConf 2015 on testing and BDD for D applications using Cucumber:

Behaviour-Driven Development with D and Cucumber

As usual, I talked a lot faster than normal and finished with plenty of time to go. I think it went well though, my super-tired-eyes-because-of-jetlag notwithstanding.