Welcome to my web log. See the first post for an introduction. See the archive page for all posts. (There is an english language feed if you don't want to see Finnish.)

Archives Tags Moderation policy Main site

Me on Mastodon, for anything that is too small to warrant a blog post.

All content outside of comments is copyrighted by Lars Wirzenius, and licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License. Comments are copyrighted by their authors. (No new comments are allowed.)


I made a poll on the fediverse yesterday.

In an international context (e.g., company that works around the globe, or a free software project with participants from several continents), what's the right date format?

The options and results:

  • 80% — 2019-12-13
  • 11% — 19 December 2019
  • 9% — 13/12/2019
  • 0% — 12/13/2019

The one with the name of the month is a different date than the others. That was a typo; mea culpa. Nobody commented on that, though, and I doubt it affected the results.

Here's my commentary. It was a bit of a trick question. Sorry. The first two options are both unambiguous as to which part is day, month, and year. The last two are entirely ambiguous, and require contextual information to interpret correctly. Thus, even though the third option is closest to what I'm used to from my own culture, I think it's utterly unsuitable in an international context.

My own preference is to express the month as a word, or abbreviation, but in many cases being all numeric is easier.

The most important bit is to be clear and unambiguous. Sometimes that means getting used to an unfamiliar notation.

Posted Fri Dec 13 10:38:00 2019

I want to develop free software with people who lift up each other, and aren't arseholes.

A year ago I left Debian. The process is called retiring in Debian, and it's not final: if you do it in an orderly manner, you can come back again, and be re-instated as a Debian developer with a faster, more lightweight process than is used for entirely new developers. This was the third time I retired. The reasons were different than previously.

The first two times I retired because I was pursuing other passions, and did not feel I could give Debian even the minimal attention and effort required to keep a few minor, leaf packages maintained. This time, I retired because Debian was not fun; it was in fact becoming awful, and I didn't want to participate anymore.

Debian had stopped being fun for me in several ways. One was that the tools, file formats, and workflows Debian uses are getting a little archaic, and generally sub-optimal. Even mundane, everyday tasks involved much more friction than they should. Another is that making any large changes in Debian is too much of an effort, these days, partly because of inertia, partly because it involves so many people.

All of that could have been tolerable, if not for the people. Some of the nicest, most competent people I know work on Debian. It has been a privilege and a joy to work with them.

A few of the other people in Debian I don't want to be associated with in any way, any more.

Debian has some vocal people who treat other people in ways that I don't want to accept. I don't want to go into specifics, or names, because that's not going help me move forward.

This is of course not a new thing. Debian has had problems with people behaving badly for years. I may have contributed to that, passively if not actively. However, as I get older, the friction from dealing with abrasive people is sanding off what thick skin I may have had when younger.

As I get older, I am also learning that some of the things I thought were OK when I was younger, are in fact harmful to other people. I don't want to harm other people, and I don't want to participate in a project where some of the people insist on what I think is harmful behaviour, because they feel it's their right.

Long after I left Debian, RMS managed to collapse the reality distortion field that's been surrounding and protecting him for many years. The triggering event for this was comments he made in a context involving Jeffrey Epstein. The comments caused a public uproar, and as a result RMS resigned from role of president of the Free Software Foundation, which he founded. He is currently still the leader of the GNU project. A lot of people are religously defending RMS and attacking his detractors. I find this to be problematic.

LWN has an excellent article on the topic. RMS has been behaving in problematic ways for a long time. He's not been publicly confronted about it before, at the scale he has been now.

RMS has done some awesome things that he should be honoured for. He started the GNU project and gave it, and the world, a vision of being able to use computers whose entire software stack is free, and inventing copyleft, a legal tool to protect software freedom, as well as writing large amounts of the initial code in the GNU project. He has worked hard and long to help drive the vision of freedom into reality. For this, he shall always be remembered and revered.

That doesn't excuse bad behaviour, such as insisting on abortion jokes, making women feel unwelcome in the GNU project, or various other things. I'm not going to make a list of his shortcomings, because this isn't a critique of RMS specifically. The problem I want to discuss isn't RMS or his personal behaviour.

The problem I do want to discuss is that almost everywhere in the free and open source development communities there's a lot of harmful behavour, and tolerance of it.

Harmful behaviour comes in many forms. Some people, for example, say outright that they don't want women involved in free software development. Others attack gay, lesbian, trans, queer, black, old, young, Christian, Muslim, atheist, any other other group of people identified by whatever attribute the attacker happens to dislike. Yet others are more subtle, not attacking directly, but not giving people in the group they dislike the same chance to participate, learn, grow, and generally be the best person they can be in the context of free software development.

This doesn't just harm the groups of people being targeted. It harms others, who see it happen, and think they might be targeted too, later, maybe for some other reason. It harms reaching the vision of software freedom, because it shoves large parts of humanity outside the software freedom movement, robbing the movement from many voices and much effort. This makes it harder to achieve the vision.

Excluding people from the movement for irrelevant reasons also harms humanity in general. It propagates the hate, hurt, and harm that is emblematic of life and politics around the world. While the software freedom movement can't solve all of those problems, we can and should at least not make it worse.

What should we in the software freedom movement do about all this? I've come to a few conclusions so far, though my process to think about this is ongoing.

  • Most importantly, we need to stop being tolerant of intolerance and bad behaviour. It's time for all project, groups, and organisations in the movement to have and enforce at least a minimal level of civil behaviour. We are a movement consisting of many communities, and each community may want or need their own norms, and that's OK. Some norms may even be in conflict. That's also OK, if unfortunate.

    Some people react to this kind of suggestion with hyperbolic claims and conspiracy theories. I don't want to debate them. It's possible to discuss community norms in a civil and constructive way. I know this, because I've seen it happen many times. However, it requires all participants to at least agree that there's behaviour that's unwelcome, and not reject the notion of community norms outright.

  • I am by nature averse to conflicts. I will try to confront bad behaviour in the future, rather than slinking away and going elsewhere. I will at least speak out and say I think something is unacceptable, when I see it.

  • I think the era for dictatorial models of governance for large free software projects is over. For small projects, it's unavoidable, because there's only one person doing any development, but when a project grows, it doesn't work to have one person, or a small anointed group, making all decisions. It's time to have more democratic governance.

    There are technical decisions that probably can't be done well by letting everyone vote on them. However, every substantial project will have other decisions that the whole community around the project should have a say in. Voting on how to fix a bug may not be workable, but voting on the minimum criteria for determining if a bug fix is acceptable is. Should the project require adding a regression test for any bug found in production? Should any such test and bug fix be subjected to code review? Should such bugs and their fixes be documented, even announced, publicly or kept secret? How should security problems be handled?

    In Debian, one of the guiding principles is that those who do, decide. It seems time to involve those who use in the decision making process as well.

I can't force all communities in the software freedom movement to agree with me. Obviously not. I won't even try. I will, however, in the future be wary of joining dictatorial projects where bad behaviour is tolerated. I'm hoping this will have at least some effect.

What about you?

(My blog does not have comments, but you can respond to this fediverse thread: https://toot.liw.fi/@liw/103080486083100970.)

Posted Sun Nov 3 09:43:00 2019 Tags:

Measuring test coverage by measuring which parts of the code are executed tests is not useless, but it usually misses the point.

Tests are not meant to show the absence of bugs, but to show what aspects of a program or system work. (See my previous rant.) If your automated tests execute 90% of your code lines, is that good enough? It doesn't really tell you what is tested and, crucially, what isn't. Those using the software don't care about code lines. They care about being able to do the things they want to do. In other words, they care about use cases and acceptance criteria.

The 10% of code not covered by your tests? If users never exercise that code, it's dead code, and should probably be removed. If those lines keep crashing the program, producing wrong results, causing data loss, security problems, privacy leaks, or otherwise cause dissatisfaction, then that's a problem. How do you know?

Test coverage should be measuring use cases and acceptance criteria. These are often not explicit, or written down, or even known. In most projects there are a lot of acceptance criteria and use cases that are implicit, and only become explicit, when things don't work the way users want them to.

A realistic test coverage would be how many of the explicit, known, recorded use cases and acceptance criteria are tested by automated tests.

Use cases are not always acceptance criteria. Acceptance criteria are not always use cases. Both need to be captured during the development process, and ideally recorded as automated test cases.

Code coverage is most useful when the main user of a piece of code is a developer, usually the developer who writes or maintains the code. In this case, coverage helps ensure all interesting parts of the code are unit tested. The unit tests capture the use cases and acceptance criteria, in very fine-grained details.

Posted Sat Oct 12 16:20:00 2019 Tags:

Some irrelevant personal history follows, skip to the next heading if uninterested. I first learnt to touch type on a portable, mechanical typewriter in my early teens. It was a somewhat painful process: when I hit a key a little wrong, my finger would plunge between the keys into the internals of the typewriter, which was full of sharpish metal edges. I lost some blood to gain typing skills.

Typing on computers is a joy in comparison. However, there's big differences between different keyboards. Over the decades I've learnt to prefer some types over others. Overall, my preference is for keyboards with mechanical switches over more rubbery ones. I type better and faster and more accurately when my fingers can sense that a key has been pressed.

For some time I'd been using gaming PC keyboards with Cherry MX red switches. These are a joy to type on, but are quite noisy. I've also been curious about split keyboards. Earlier this year I heard of the Keyboardio Model01 keyboard, which started as a crowdfunded project. I was curious.

However, it's expensive, for me, and quite different from anything I'd ever used before, so I was hesitant to get one. Luckily, I was introduced online to one of the founders of Keyboardio, who said they'd enjoyed the book I wrote for the Linux Documentation Project in the 90s, and would like to donate a keyboard for me. Joy!

Review

I've been using the keyboard for some weeks now. Initially, I only used it to learn to touch type all over again. Not only is the keyboard different from any I'd been using before, but it seemed better suited to the US qwerty layout than the Finnish one, so I've been learning both a new physical layout and a logical layout.

Also, I've been curious of using a US layout for programming for some time, and this is the perfect excuse to learn. Much fun. Luckily, it's not been actually painful, and I've not lost any blood this time.

Now that I'm getting a little closer to my previous typing speed of 60 words per minute on the new keyboard, it is time to write this review. I've never been a fast typist, but this speed seems to be fast enough that my brain doesn't get bored or frustrated waiting for my fingers to do their thing.

Good stuff:

  • It just works. Plug it in via USB, and start typing.
  • Typing feel is great. It's fairly quiet, thanks to using Matias Quiet Click key switches, instead of Cherry ones. Yet there's no doubt about having pressed a key.
  • Build quality is good. Feels solid. They call it heirloom-grade, and I can imagine this one lasting me decades.
  • The firmware is free software, hackable, and changing it does not void warranty. I've not managed to brick the device. It's basically an Arduino with a fancy peripheral.
  • Keyboard layout can be configured with the Chrysalis desktop software, without having to build and update a whole new firmware blob. I've used to convert what is normally num lock to be scroll lock, so I can use it as a compose key.

I don't really have complaints, but of course one can always whinge:

  • The Keyboardio website is a little disorganised and could be improved. There might be a need for a documentation project just for this keyboard and its firmware and associated software.
  • Oh boy does it take time and effort to learn to type all over again. Even if it's worth it, it's still frustrating to re-learn something I first learnt almost forty years ago.
  • I wasn't overly impressed with the bundled cables (USB-C and Ethernet), but they're easy enough to replace. I now have cables that are just the right length, even if it seems silly to use CAT7 to connect two halves of a keyboard.

Verdict: I like the keyboard. If I lost it, I'd want to buy a new one. If necessary, I'd write another book to get one.

Disclaimer: this review was not commissioned by Keyboardio. When they offered to gift me a keyboard, they made no condition or request or even hint that I should write a review. They only asked that if I didn't like it, I'd gift it forward to some young hacker who would put it into good use, but couldn't afford it themselves. Sorry, young hackers, I'm keeping it.

Posted Sat Oct 5 21:43:00 2019 Tags:

The reMarkable tablet is a 10" e-paper tablet on which you can read PDF and ePub files, and write on with the stylus that comes with the device. It has fundamentally changed how I read textbooks.

I used to collect books, and was proud of my library. I have a custom-made book case, with about 20 shelf meters of space. Not huge, but I curated my dead trees carefully.

I have for years not liked having paper books. They're expensive to store (need a larger home, and thus higher rent), and become quite heavy to carry (I've moved home more than twenty times in my life). For a decade now I've preferred e-books. However, Kindle devices, or their competitors, tend to be small, paperback size. That's no good for texts that have graphs, diagrams, tables. Worse, most e-book formats are reflowable, which is great for novels and straight prose, but not so good for textbooks or other works that need layout.

I have, over the years, bought a number of textbooks as PDFs. PDF is in many ways an excellent format for textbooks. However, I've lacked a convenient way to read them. Reading on a laptop screen is awkward, due to the small screen. Reading on an external monitor is uncomfortable, since it ties me to my desk. Also, it's very easy to be distracted when at my computer (IRC, the Fediverse, email, RSS, ... and if nothing else, there's a web browser and Wikipedia).

I bought the reMarkable tablet almost a year ago, after starting a new job, and getting my first couple of salaries. It's a little expensive, but I felt like splurging, and was in a privileged position to do so. I've not regretted it.

Things I especially like:

  • The screen is big enough for most books, and big enough for me to read A4 (or letter) sized documents without problems.

  • Writing is natural and smooth, almost exactly like writing on paper. The tablet seems to not have any trouble keeping up with the pen.

  • Did you know it's fun to scribble notes on books? It wasn't allowed when I was in school, since books were shared and often borrowed from the school. So much fun! Also, seems to make comprehension better for me.

  • There are no distractions on the device, except all the other books you've put there.

There are some things I don't much like, of course. They're not big enough to prevent me from using the device, and finding it a pleasure, but I feel I should mention them in case someone reading this is considering to buy one.

  • While the tablet keeps up with writing just fine, it's a little slow when jumping around a long document. It feels like it only caches a few pages in full, and thumbnails of the rest, if that, and has to re-render pages often. This makes jumping around a little tedious. I'm not sure why it doesn't cache more, since I have gigabytes of free space.

  • The software isn't free, and the APIs, file formats, and data structures are not documented. This makes it harder to, say, sync any new documents to the device automatically. I bet the company would get an enthusiastic developer community in no time, if they opened up the software. That seems like it would be a no-brainer, given they make their money from hardware sales and better software support would result in more hardware sold.

  • The way it renders PDF tables of content is ugly, hard to read, a little slow, and a little too easy to misnavigate.

  • The tablet does not follow intra-document links in PDFs. In some books this is annoying.

  • There's a bug in the firmware when exporting annotations you've made to a PDF with different sized pages. It turns out a lot of the books I've bought as PDF have a cover page that's of a different size to the interior pages, and the tablet exports annotations relative to the top left of the cover page, rather than the page where the annotations are.

Verdict: I like the tablet, and would buy a new one if I lost mine.

Posted Sun Sep 22 10:00:00 2019 Tags:

Recently I announced a tool for acceptance testing. It turned out that the name we'd chosen was already used by another testing tool, so we renamed ours. The new name is Subplot (the old name was Fable).

Work on the production implementation has started. If you are good at typography, help with automated typesetting of Subplot documents would be greatly appreciated. The goal: to use typography to make Subplot documents as easily understood and as effective at communicating acceptance criteria as possible.

Posted Tue Sep 17 09:09:00 2019 Tags:

Lars Wirzenius and Daniel Silverstone announce the Fable project.

given all stakeholders need to understand acceptance criteria
when Fable is used to document them
then all stakeholders understand them
and they can be automatically tested

Fable is a tool set for documenting acceptance criteria for a system, in a way that's understandable by all stakeholders, and for implementing automated tests to verify the criteria are being met.

See the Fable home page, including links to source code and Debian packages. There is a tutorial (PDF), examples, and documentation. Fable is free software, but doesn't constrain the license of the generated documentation or test programs.

Posted Sat Aug 24 09:44:00 2019 Tags:

Debian uses PGP keys of its uploading members to authenticate package uploads. The keys are stored in a keyring maintained by the keyring-maint team. The team also maintains a PGP keyserver, and new keys and signatures are uploaded there. The Debian keyserver gets new signatures from other keyservers, but only accepts signatures by keys already in the Debian keyring. New keys are accepted into the keyring manually, after a vetting process of the person. Updates from the Debian keyserver to the Debian keyring happen manually, roughly once a month. Only package uploads signed by keys in the Debian keyring get accepted by the Debian package archive.

The Debian package archive is signed by another key, securely maintained by the Debian FTP team. A copy of the public key is installed on every Debian machine, and updates to the key, as well as new keys, are distributed via package updates. This happens routinely in Debian.

Because of these reasons, Debian seems immune to the current attack on the SKS keyserver network, since Debian isn't getting those signatures, and the Debian package archive and updates to machines running Debian aren't getting the fraudulent signatures either.

(I've checked the above text with the keyring-maint team and they are OK with it.)

Posted Tue Jul 2 17:18:00 2019 Tags:

Edsger Dijkstra was one of the most influential computer scientists, in the early days of the field. One of the many quotes from him is about testing:

Testing shows the presence, not the absence of bugs

(See page 16 of the linked PDF. Note that the context is formal correctness in software development.)

This is used from time to time to claim testing is pointless. I object to that sentiment. Dijkstra's quip is funny, but it's only partly correct, for general software development, that testing can't show the absence of bugs. More importantly, testing is meant to show the absence of bugs.

Testing is about showing what works.

Consider the physical world, from the point of a physicist. What happens if you drop an apple? It falls down. The physicist needs to answer the question: Does all fruit always fall down?

To answer that, it's not enough to drop one apple one time. Do pears also fall down? Do all apples fall down? Every apple, every time? Does it happen on sea level? At the top of a mountain? When it rains? When there's a lot of people watching? When there's betting about what happens?

To answer the question, the physicist needs to drop a very large number of different fruit, a very large number of times, in all sorts of environment and contexts. And eventually, they form a hypothesis that yes, all fruit always falls down. After a long time, after many other physicists have tried everything they can think of to prove the hypothesis wrong, the community of physicists accepts the hypothesis as true: all fruit always falls down when dropped.

Until someone goes to outer space. And then no fruit falls. It just floats there looking smug.

The point of testing software is not to do one test, once, and assume the code always works. The point is to consider all the cases in which to code under test needs to work, and try it in all those ways, and make sure it does what is expected of it.

Tests don't tell you that code works in cases that aren't tested. Tests tell you code works in the cases that are tested. If you want it to work in some other case, you add a test, or expand an existing test to cover the case you're interested in.

If the suite of tests misses a use case, and the code happens not to work in that particular case, that does not mean testing is useless, or that there's no point in even trying. If you don't have a test for dropping an orange in outer space, you don't know if oranges fall in outer space. It doesn't mean physics is pointless. If you care about dropping fruit in outer space, you go to outer space and try it.

Posted Sat Jun 29 15:58:00 2019 Tags:

Had a discussion recently with my friend Richard Braakman about debugging. Here's a lightly edited version, in case it is of any use for others.

Richard is awesome at debugging, and I've often suggested he should employ himself as a consulting debugger, the way Sherlock Holmes was a consulting detective: to be called in when the usual experts are stymied.

The context of this discussion is that I'm working in my free time on a new system, named Ick, which will have a server component, and I want to make it easily debuggable. So of course I asked advice from the best debugger I know.

L: What would your top three hints be for someone who needs to learn to debug better?

R: Hmmm... obviously it depends on where they are now :)

L: I'm asking for myself primarily but also collection ideas in case I do a talk on this some day.

R: One. Find a way to observe the problems. By which I mean, instead of massaging the starting conditions to make hypotheses, actually follow it step by step through what goes wrong. See what it's actually doing. This might mean using a debugger, or strace, or tcpdump, or adding logs, whatever it takes. (When doing so involves extra work it's often tempting to leave it as a last resort. I've found that it pays to resort to this early.)

Two. When you conclude that the behaviour you're seeing is completely impossible, don't give up. You're actually getting close. One of your assumptions is wrong. When you find which one, you'll have the bug.

Three. Try to duplicate the buggy behaviour on another system. (This is easiest if you already have one - the "it works for me" case). Then systematically remove the differences between the working and non-working systems.

If you ask on another day you might get a different top 3. :)

Something I often say is "make sure the code you're reading is the same code you're running."

L: Interesting. Thank you. This helps me. New question: if I were building a program that you may need to debug later, what would you like me to provide to help you debug?

R: Heh. An easy way to get the debug log. I often find that logging has been turned off in multiple ways. I have to figure out how to compile it in, then how to turn it on, then how to make it go somewhere else than /dev/null.... and some programs have different debug logging frameworks in different parts that have to be turned on in different ways. It's a pain.

Sometimes there is actually a simple way but it's not documented, and I have to read the code or google for it.

Sometimes the way to get logs keeps changing between versions. (Looking at Qt.)

L: Haha. Q: would it be useful to have highly detailed debug log for recent times but the rest reduced the level of detail for older stuff? Or would that just be complicated?

R: Do you mean for recently written code?

L: Recent in terms of of execution, so much detail for the latest hour, but less for older logs.

R: Hmm. I had one program where I logged debugs logs to a memory buffer... as soon as there was an error or warning log, it dumped the whole debug log too (and wrote the debug log directly for the rest of the transaction). If the transaction was error free, the debug log buffer was discarded.

It works for server-like programs.

I think time based log purging wouldn't be good in my current type of jobs, where I often see problems only the next day etc.

L: Was that useful? Should I consider that for Ick?

R: Yeah it was useful :) It meant we got detailed logs of problem cases, without overflowing the log files. We had a high transaction rate and the logs were several GB a day.

L: I shall keep it in mind then :)

R: I guess it's less useful if you have no capacity problem :)

L: Speaking of logs, what's a good log like?

R: One thing is, it helps if the log text is unique in the code. That way I know for sure which bit of code generated the log.

Hmm, when I modify the logging, it's often to add the actual values the code is having problems with. Like instead of "too many entries", log how many there were and what the limit was.

Same with stuff like "unknown command code".

Including those values is often extra work and I don't actually know if it pays to do it in advance :) I just know it's the change I most commonly make.

L: Would you say log message should make sense without having the code in front of you?

R: I think that's a "sometimes".

Like... if the log message is like trace logging, for example if it's logging the disposition of a packet, then the trace should be understandable without looking at the code. But if it's logging something internal, like the workings of an algorithm, then I'm probably looking at that code already.

L: Nod, good point.

What's a good way to control logging? As in where it goes and how detailed it is.

R: That I don't know :) All the ways I've seen annoy me.

I think my favourite is to generate a separate debug.log file next to the normal logs.

It all depends on whether capacity is a problem.

Hmm a separate point is about consistency in logging. Like, if there are five reasons to reject an input and only four of them have logs, then I'm likely to miss that fifth one and assume "no log means input was accepted".

L: Nod.

What's your preferred format for logs?

R: I don't think I have a preference :)

L: Do you like logs that are easily processed by programs?

R: Nah, at most I use grep. But the people who make intrusion detection systems prefer that :)

Same for system monitoring I guess.

L: Check

Posted Sun Jun 23 11:14:00 2019 Tags: