Weeknotes 2024


Is Weeknotes (see https://doingweeknotes.com/) is something I want to do? Let’s find out.

March 11th—March 16th

After yet another batch of structured thinking I fail to follow up, I decide to try again with a different format, a different trigger and a different scope.

I found the concept through Patrick Dubroy’s weeknotes: https://github.com/pdubroy/weeknotes/blob/main/notes/2024-11.md

Why weeknotes

Weeknotes seem to hit a sweet spot. Once a week, I can do that. I can even schedule time in my calendar!

On the importance of learning from excellent people

The only reason whatsoever I’m doing this is because I’ve rigged my Twitter account to follow a few highly competent people in detail. One of those people I (subjectively) consider to be highly competent (without ever having met the person) is Patrick Dubroy. I caught a tweet in which Patrick announced that he’d be writing weeknotes, and asked his Twitter audience whether they would find it useful. I found it very interesting. Utility will have to wait.

The best way to find excellent people is through trust networks.

Step 1: pick someone who you respect and believe you have something to learn from.

Step 2: observe what they do, read what they write, answer when they ask questions. Try to help them do things they care about.

Step 3 (the recursive step): explore who they trust. But do this slowly. The recursive step will open you to get more content, which is a double edged blade. If they are great and you’ve read all they have written, great! This is exactly what you need. If they are actually mediocre, stop. Full stop!

I started thinking about the importance of exploring networks of trust about a year ago, when I made the frist version of this site (play.teod.eu). That lead me to make first class support for remote references. Patricks’s page here on my site is a remote reference. Technically, there’s a metadata file with

:form :remote-reference

in it, found here: https://github.com/teodorlu/play.teod.eu/blob/afc06c6954ee2782057b3bf6b2676a766aeb7d8a/patrick-dubroy/play.edn#L3

but that’s not too important.

One of my main lessons from speaking at babashka-conf (my talk was Build Your Own Little Memex with Babashka) was the importance of referring to sources. And not in a literal “how to write papers” sense, in the hypertext sense. With hypertext, we can refer effortlessly to sources at any point in time. And that is absolutely amazing.

By the way, I found Patrick by reading Jack Rusher’s tweets. I interacted with Jack first on Clojureverse. I engaged with the Clojure community on Clojureverse after realizing that the team I currently worked on didn’t care too much about programming, and wanted to learn more. I found Clojure kind of randomly by watching a Youtube video about some guy doing REPL-connected Clojure programming with Emacs. And I found Clojure sort of by accident after finding Haskell in 2014 (I did a 148 slide presentation about Haskell in Norwegian in 2014, Haskell: hardt og godt, in English something like “Learn Haskell the good, hard way”). And I don’t remember how I stumbled upon Haskell, other than that I thought it was absolutely amazing, and embarassing that we had spent so much time at NTNU learning Java.

I digress.

I encourage you to look around for the people around you that you’d like to learn something from, engage with them (take what they say seriously, ask questions if you don’t think it makes sense, perhaps they will respond), then dig deeper into the rabbit hole when you’ve got energy.

On the importance of slowing down and sharing knowledge in software teams

On my current team, we have lots of code, and limited shared understanding of that code.

I’m convinced that the right thing to do is to slow down and build shared understanding.

Since joining the team, I’ve spent less than 5 % of my own time writing code. I do like writing code, so I’d like to increase that fraction over time. But I hate writing code that isn’t needed, or code that solves the wrong problem.

So, let’s slow down! First, we build a solid shared understanding. Then, later on, we’ll use that shared understanding as a foundation to create & capture value.

Kent Beck knows his shit, but cares about everything

I had the fortune to chat briefly with Kent Beck when he visited Oslo in 2023. He gave a talk about the importance of feeling safe to people working in Iterate AS. I felt like that was a bad topic / audience match. Iterate is so awesome at creating a safe environment for people that I feel like we struggle with actually expecting people to do things. Anyway.

Kent Beck ran amazing software teams in the 90s, and wrote Extreme Programming (book) about the principles. The most important principle from that book that I had not taken with sufficient seriousness before 2023 was pair programming, and its generalization ensemble programming. Pairing is a ridiculously effective tool to build shared intent. (which is one of the pillars in my “product howto philosopy”, Tillit, kvalitet og intensjon i praksis: en håndbok for produkt- og programvareutvikling (Norwegian)).

Kent Beck knew this 30 years ago, I learned it just yet. And it’s … really really weird to fully lean into the importance of shared intent. It’s Rich Hickey’s ideas from Design in Practice taken to to level 9000. To make some ultra-clear directives:

  1. NEVER start writing code unless you know what problem you want to solve.
  2. NEVER start solving you problem unless you have at least two different approaches.
  3. ALWAYS share the problem and share your options before moving on.

These directives are divisive, and almost every team I’ve ever worked on break them at every option.

Some people that I don’t think are breaking those rules:

  1. Rich Hickey (kinda obvious? Hammock Driven Development and Design in Practice talk about this directly)
  2. Stuart Halloway, see Debugging with the Scientific Method.
  3. Martin Kavalar and Jack Rusher: making Clerk so that we can explore options better
  4. Christian Johansen and Magnar Sveen: They’ve been pairing effectively for years.
  5. Evan Czaplicki. Deep theoretical understanding of programming and type systems, AND one of the best teachers of his generation. What a guy.
  6. Sam Ritchie
  7. Gerald Jay Sussman

But does Kent Beck himself break those rules? I’m guessing perhaps. Because he seems to be a person who on principle breaks rules to learn from breaking the rules.

“but cares about everything”? Yeah.

  1. My impression is that Kent Beck has very wide interests.
  2. That may lead to him giving off more chaotic vibes than a certain situation can handle.
  3. I observe myself doing the same thing. In dialogue and work, I sometimes jump to conclusions. In those situations, I rely on others asking me to slow down.

No value judgements here, just observing. Sometimes, chaotic is good. Sometimes, systematic is good. I believe in people judging how they should act for themselves!

Also, I have to remember that I cause this exact same confusion (because I’ve seen it happen, and have had people comment to me that it has happened!) I also tend to be a bit … rigid in my views on epistemology. When people mistake something subjective for something objective, I can respond a bit harshly. That can cuase problems.

Paths not taken (yet)

My ultra-old (so far) failed attempt at adding SI units to Emmy: https://github.com/mentat-collective/emmy/issues/46. I’ve been assigned to the issue for four years. I’ve recently made (subjectively) serious progress, but I’m hitting problems:


Clerk has been an essential tool to make progress. Perhaps the only thing I need to do is not load the system from within Clerk, and instead keep the SI system and the documentation of the system separate. Dunno. Still working on this, though. I feel like Sam is giving us so much, and I want to give something back. I’m still grateful for the hour of pairing we did back in 2020, which made me realize just how much I still had to learn. And how interacting with generics in Emmy has opened my eyes to why Clojure has built-in polymorphic dispatch (protocols/multimethods), and why Software Design for Flexibility is an awesome book.

Helping the Clerk team debug problems. I reported some problems last Sunday. Andrea Amantini took the trouble of digging into those problems. And he probably discovered that I had hit not one, but two different problems, and reported both at once. He asked for some follow-up (while I was in some meeting), and I haven’t been able to answer yet.

Still curious about running Clojure directly in Emacs. Jack Rusher started out: https://github.com/jackrusher/scimacs. I presume he wanted to encourage someone to try explore this further, because I presume that he has many options on his hands. I tried doing some work there, but quickly got stuck:

  1. I don’t know C (well enough).
  2. Embedding one language into another through FFI bindings is something I find hard (subjectively).

Selected gratitude

I’ve had the pleasure to get to work more with Olav Moseng. Olav and Ruben Sevaldson gratiously helped making last week’s Clojure workshops happen. (The material for those workshops are not yet public, but I’ve gotten all OKs I need, and will publish, I promise!)

Michiel Borkent helps everyone from scratch as always, continuing to be a one man bulldozer army lifting us all up.

Nikita Prokopov continutes to be a one man (slightly smaller) bulldozer army — but one that cares deeply about design.

Jørgen, Ann and Viktor continue to see problems clearly, and similarly care deeply about the people they empower to solve those problems.

Thusan Arul and Magnus Reier Rushfeldt for picking up my slack on the Tidy First book club.

Finn Holme and Adrian Tofting for honestly, shamelessly being themselves.

Richard Tingstad for some really enjoyable interactions & par programming sessionds last week.

Short retrospective, should I do more weeknotes?

  1. I really liked the process
  2. Finding the right target audience was a bit hard. I landed on writing two docs: one for my team, and one for me. You’re reading the one that’s for me.
  3. I spent about two hours on the one for me, and about two hours for the one for my team. I probably want to aim to use less time. Four hours per week is 10 % of total spent time. Probably not a sustainable amount.
  4. I’ve got no idea whatsoever what others are going to think about me writing this, really curious. I’d appreciate it if you’d send me reactions you have.
  5. I wonder if I want to publish a link to my weeknotes on Twitter? Perhaps yes?
  6. I have too many spelling errors in this text. I need to get spell checking in Emacs working again. 😔

OK, done. Time to get some air. Untill next time!

March 17th—March 22nd

On the importance of having great people to learn from

Every day that passes, I cherish my chances to learn from great people. They are out there! They might just be … hard to find. And who you should be learning from is intimately related to what your goals are. Those I enjoy learning from may not be the right people for you to learn from.

On the balance between design and implementation when we build software

X: “design”? You mean the work designers do?

T: No. I mean software design. I have a beef with the current usage of the word “design”. We’re using it vaguely! I used to do design of steel structures and design of concrete structures. These days I often engage in software design.

I feel like the agile movement inadvertently dragged in an assumtion that design is bad, and writing code is better. I think “don’t do design, write code instead” is a really bad idea.

X: So … Why now?

T: I’m working with two great people. Having a lot of fun. But I feel like we struggle a lot finding a balance between design and implementation. Right now, we talk a lot about implementation details, but not about system design.

X: Ah, I get it! You’re talking about architecture! Software architecture!

T: 😅 I … have a bit of a beef with that word too.

X: why?

T: We software developers took the word “architecture” from civil engineering projects, and I fear that we took the wrong word. In software, we want to talk about the core of our system. Architects can do the start of the work, if what you care about is floor plan utilization, and the civil engineering is trivial. Architects do not build bridges. Architects do not build dams. Architects do not build industrial plants. In those cases, the civil engineers (or construction engineers) hold the “core”.

X: so … which word, then, if architecture is bad?

T: I think the word is “design”. And for systems, “system design”!

X: okay. Man, when you insist on redefining words before you even start speaking, it sometimes rubs be the wrong way. It’s like everything I say is wrong, right?

T: Yeah, I know. Sorry about that. I don’t know of a better way — other than leaning completely into the arts, presenting ideas as theater, dialogue or as novels. Steal from Eliyahu Goldratt’s way of presenting things, perhaps.

X: yeah, yeah. I don’t always have time for that, you know?

T: Yeah, there’s so much f-in stuff. I feel like we could make due with less stuff. But that requires some thinking.

X: So … What was that balance you mentioned? A balance between design and implementation?

T: Right. Thanks. That was where we started.

We spend so much time on implementation and so little time on design. And we’re calling it “agile”. “agile” as an excuse for coding up things when we don’t have any idea why we have to do the things we do. If we slow down, we might get pressure to speed up. It’s lean to do less stuff. But rather than cut the problems we don’t care about, we solve the problems we care about badly!

This is where design comes in. We should know what our goal is. I’m … I’m at a point where I have no interest in writing code unless the goal is clear.

X: what about teamwork? Everyone needs to know what do do, right?

T: Yeah, that’s the hard part. It’s harder to solve real problems than write code. And it’s even harder when you’re a team. So much shared context is needed.

X: So, what do we do?

T: I’m discovering this myself as I go along. I’ve had success with two activities.

One activity is pair programming. This one is hard. Knowing when to focus on design and when to focus on implementation is hard. I think great pairing is something you have to re-learn every time you pair with someone new. Without trust, this will simply fail. And that trust needs to go both ways. I need to trust you, and you need to trust me.

Another activity is to use a decision matrix to compare approaches to solve a problem. A decision matrix lets you do clean software design work without getting stuck in all the details.

X: How should I learn pair programming?

T: Ideally, you get to pair with someone who is good at pair programming. I had the chance to pair with Lars Barlindhaug in 2019 and Oddmund Strømme in 2020. From Lars, I learned that it’s better to organize your code into modules where each module solves a problem you care about. From Oddmund, I learned that I could work in smaller increments.

If you do not have someone you can learn pairing from on your team, watch Magnar Sveen and Christian Johansen pair from their youtube screencasts: https://www.parens-of-the-dead.com/

X: And … those decision matrices?

T: Watch Rich Hickey explain decision matrices in Design in Practice. Then try it out with your team!

Selected gratitude

To Lars Barlindhaug, Oddmund Strømme, Kent Beck, Christian Johansen and Magnar Sveen for helping me understand pairing.

To Christian Johansen and Peter Strömberg for their willingness to engage personally with people in their software community.

To Simon Wardley and Eliyahu Goldratt for ideas I’ve stolen.

To Rich Hickey, Jack Rusher and Alan Kay for caring deeply about the important problems in computing. And not just “fake caring”, they put their skin in the game. Rich Hickey paid for Clojure with two years of his life.

Selected comments

Patrick Dubroy suggests that I might want to read Designerly ways of knowing (via twitter).

March 23rd—March 31st

My head is too full of thoughts, I struggle to narrow into weeknotes.

Yup. I just had spent some time off. That was absolutely amazing.

Our family has a cabin 921 meters above the ocean. My (now deceased) grandfather used to talk about how they used the cabin during the German occupation of Norway in World War 2. German soldiers had “requisitioned” clothing to stay warm. My grandfather never saw any of that clothing again. But the Germans did leave some impressively detailed maps of the area. I guess I should have taken a picture of that map, now? Too late.

I love working with plaintext on my site. I don’t love how much harder it is to include a simple image!

So, all those ideas. A person on the internet has been taking notes in order to write their weeknotes. I figured I’d try. I’m including my weeknotes-notes, in all their messy. Feel free to skip that list!


When I write, I very often get myself into scope creep. I want to write about all the things! So far, timeboxing has saved my weeknotes. And I’m 23 minutes into my timebox. I wanted to stick to 30 minutes. Let’s see how that goes.

Are we walking too quickly when we create software?

According to a youtube recording of a Thoughtworks guy, people walk faster in bigger cities (until some limit). While that might be interesting to know, is it good to walk fast? Should you get done as soon as you can, or should you not?

I suspect that we should walk slower.

Do fewer things, so that we can do the things we do with pride.

I used to work in civil engineering. In that work, we had a set amount of time to finish some piece of work. Looking back at that experience, it was freeing. Yup, not stressful, freeing. Here is the budget we have for this task. Try to hit it. If you’re way off, you may have to simplify.

I do software, not civil these days. And I’ve said that estimates are bad myself. But I feel like we’re maybe missing the point.

Estimating something if you don’t know what it is is silly. But being explicit about how much effort we want to put into something makes sense to me.

Trurl and Klapaucius: two makers, their egos, and their tiny scene

Trurl makes something, and is immediately caught in a dilemma. If he does share it with Klapaucius, Klapaucius might embarrass Trurl for its flaws, and open Trurl’s imperfection to the world. But if he does not share it, nobody will know. Which is worse?

In The Cyberiad, Trurl never ceases to share with Klapaucius.

The book was published in 1965, which makes me wonder how it can resemble two grumpy old developers.

Joy in cutting scope?

My timebox is out! That’s actually kind of nice. I can finish. I don’t have to write about everything. This is not a report. I can actually decide that this is not a report, this is some stuff I write for myself. And that’s something I like!

April 1st—April 5th

My experience of a team-building/planning workshop we did

I’m working with two great colleagues. One of my colleagues pointed out that I might have some implicit expectations about how we should work together, and he’d like to know what they were.

To address that, we spent two half-days together on Tuesday and Wednesday.

I thought the workshop was for my co-workers, but in the end it was tremendously useful for me. Which was weird!

I narrowed my expectations into:

  1. I expect us to make an effort to build trust in our team
  2. I expect us to make an effort to build shared intent in our team
  3. I expect us to make an effort to build shared sense of quality in our team
  4. I expect us to know which organizational goals we are currently working towards
  5. I expect us to know how what we are doing today is influencing our organizational goals

But that’s kind of abstract. So we did something less abstract too. We made a 2D map of skills and evaluated ourselves on each skill.

Things I learned during the workshop:

  1. I had assumed that everyone were interested in product management (if you are interested in product management, consider reading Empowered by Marty Cagan)
    1. That was wrong
    2. I’m interested in product management, my co-workers want to focus on code, and perhaps explore product later
    3. Decision: I take responsibility for us doing reasonable things product-wise.
  2. I had assumed that I should be the one doing system design
    1. That was wrong
    2. Everyone were really interested in getting good at system design
    3. Decision: I make sure we can be proud of our large-scale system design—other than that, we try do system design work together.

So, this was super useful.

We wrote the list of skills by spending 5 minutes by ourselves thinking about skills that had been relevant in previous software / product work.

But why was it useful? What was the goal of that activity?

I think the goal was to build shared sense of quality. And I think it’s easier to build shared sense of quality that just to build quality.

I think it’s easier to build shared sense of quality than just to build quality

X: What does that even mean?

T: Let me give some context and explain why that statement has been useful for me.

When we want to create something good, we need to engage in creativity. In Creative Computation, Jack Rusher describes creativity as a dual process between a generator and a filter. If you do not have the time to watch his presentation, here is a simplified ascii-representation of his figure:


  |                  |
  v                  |

Generator         Filter
 Writer            Edtior
 Maker             Critic
 Creative          Discromitive

  |                  ^
  |                  |

(please excuse my silly arrows.)

My summary of his model:

  1. Creativity is a dual process
  2. We make things
  3. Then we judge whether they are any good.

Jack also cites Friedrich Nietzsche, Ernest Hemingway and William James:

[Creativity is born] of a rare cooperation between the “Dionysian” spirit of ecstatic intoxication, which imbues the work with vitality and passion, and the “Appolonian” spirit of sober restraint, which tempers chaos with order and form.


Write drunk, edit sober.


[Creativity] involves the process of blind-variation and selective-retention.

—William James

X: OK, OK, that’s creativity. But where’s the shared sense of quality?

T: If have created something in a Dionysian (drunk) manner, building shared sense of quality with the people around you will likely force you into taking the Appolonian (sober) perspective into account. I wrote some code. I think it’s amazing. But I’m drunk, I don’t know whether it’s any good yet. I’ll quckly realize that I’m actually drunk when I’m completely unable to tell you why the code is any good.

X: So, we should talk about our taste, and about whether it’s any good?

T: Absolutely! I find that rewarding, useful and fun. Visakan Veerasamy encourages people to cultivate their taste in friendly ambitious nerd. I think that’s a good idea.

X: Ok, ok. But what’s that “shared sense of quality”, then? How is that different from pure quality?

T: Shared sense of quality is the understanding you and I build when we discuss why the code is any good! And we don’t even have to agree that it’s any good. Just need to build some shared understanding, shared sense. I gain something by knowing whether you think it’s any good, you gain something by knowing whether I think it’s any good. Win-win!

X: 🤔 Need to think on that I think. Perhaps try for myself to see if I agree.

Selected gratitude

To my co-workers O and BO for

April 7th—April 12th

Some self-imposed limitations for weeknotes

two weeks ago, I had a hard time writing weeknotes. There was too much I wanted to say, and I wasn’t happy with the resulting text. To simplify writing weeknotes for myself, I’m imposing some limitations:

I’ve been sick! 🤒

It started last weekend. I stayed in bed Monday to Wednesday, then worked from home Thursday and Friday.

The most interesting part of that experience was re-watching Marvel’s Iron Man film from 2008. Sure, it’s action. Man gets kidnapped, put in a cave, builds himself a power source, uses that power source to power an an exoskeleton, and mounts a rocket launcher and a flamethrower. What’s not to like?

This time around, I found that I enjoyed the clips of Stark working in his basement as much or more than the clips of him shooting people or escaping fighter jets.

What does it take to get that basement in practice?

I realize that it’s unlikely that I’ll invent a new power source that’s better than fusion, and that most likely outcome of a jet pack in use is a dead pilot. But the suit is not the point, it’s the garage! And I guess we all have to start somewhere.

Pandoc is a great intermediate representation for documents

John MacFarlane wrote Pandoc, and has been maintaining it for years.

The document you’re reading right now is written in Org-mode, and converted to HTML with Pandoc. I reported a table of contents generation issue, MacFarlane fixed the problem, and rolled out a new release. The table of contents now works! 😸

Daniel and Kira keep on working tirelessly to make Clojure better suited for data science.

I’m grataful for Daniel Slutsky and Kira McLean’s tireless work on Clojure data science. Kira is writing the Clojure Data Cookbook. The cookbook is meant to teach how to do common data workflows in Clojure. Daniel has written about his recent work in Scicloj February 2024 update and Scicloj March 2024 update. For example, you can read a quite interesting analysis of how bikes are used in Chicago, based on a data set from a bike sharing company in Chicago.

April 15th—April 19th

Problem ownership reduces the difference between junior and senior software developers

If we focus only on the speed someone can write code, the difference between an inexperienced programmer and an experienced programmer is large. If we derive our value as team members from the speed in which we write code, that can suck! I’m saying this because I’ve been on a team where I felt that my contributions were slow, and it sucked.

A few years later, I feel that my mindset has shifted to a healthier mindset. Code does not equate to value, and software development is more than programming.

I believe problem ownership is important. Lack of problem ownership is to write code, then wait for someone to assign more work. Problem ownership is to make an effort to learn the context, commit to work on some well-defined problem, then push for progress solving that problem.

When we emphasize problem ownership over writing code, I claim that the difference between the value produced by an experienced programmer and the value produced by an inexperienced programmer reduces.

So if you’re an inexperienced programmer and observe some of your co-workers solving problems super-fast, know code-writing-speed does not equate to value. And you can probably make a good positive impact as long as you take some problem you’re working on seriously, and try to solve that problem.

(based on a Norwegian lightning talk I gave on Wednesday: 10x-utviklere og problemeierskap)

I introduced weeknotes in my organization

I’m doing programming work on a team of 7 people. That team of 7 people is one of about 10 product teams in the organization I work. Yesterday, I asked my team for thooughts about what was important during that week, and published weeknotes. I followed the advice on https://doingweeknotes.com/ quite exactly, I created one channel #myteam-weeknotes-notes for collecting thoughts about what was important this week, and #weeknotes for publishing weeknotes. I didn’t ask for permission, but I asked whether anyone wanted me to not publish weeknotes.

I was absolutely floored by the contributions I got from my team. Each contribution crisply explained a few things we had been working on that week. I though I knew what people had been working on, but those few sentences from a few team members were super-helpful for me.

Sharing the weeknotes with the rest of the organization got a few thumbs-ups— but I’ll refrain from claiming success when I’ve seen actual positive effects “reflect back”. Examples of that could be some person in the organization getting in touch with us based on something we’we written, either to ask us for help on something, or provide something helpful for us.

April 22nd—April 26th

Yet Another Take At Memexes

In 1945, Vannevar Bush wrote As We May Think about a device that aids human thought. Over the years, this idea has infected many minds—mine included.

It started for real when I made the first version of play.teod.eu, the site you’re reading now. My site works great for me. But:

  1. It can’t be used without reading an intricate manual, and that manual does not yet exist.
  2. It can’t be used without a Unix machine with an Emacs installation. (As you may imagine, there’s no mobile support)
  3. It supports files in Git as it’s only source for information.

These limitations prohibit certain forms of communication.

I want a system that can supplant my website, Twitter, Wikipedia, Roam Research and Basecamp. I want great hypertext support. I want user-extensible text formats. I want user-extensible text editors. And I want to support editing files as text files.

I think I’ve got a design in mind that makes this possible.

But what’s step 1?

I’ve asked some colleagues if they’re interested. We’ll see how it goes. A nearby goal is to use this Memex to share our experience eating at local food places. That information is currently scattered around other places. Perhaps it’ll work, perhaps not.

Very nicely timed, Jack Rusher shared a video from Bret Victor: Bootstrapping Research & Dynamicland, Dec 2019. Bret Victor suggests that instead of having research goals, one might want to build a little world in which one lives to do the work. The world is the work.

If we manage to live inside the Memex, we might be encouraged to keep up work on the Memex.

A stab at Test && Commit || Revert for Clojure

A cool colleague of mine invited to do mob programming last week. I had a great time. But I fear that we didn’t get anything done during the coding. We wrote a lot of code, and didn’t run any of it.

It got me thinking about how I’d like to do mob programming.

I’d like to use Clojure, because I like programming in Clojure. But I’d also like the state to be visible. Interactive programming with Clojure can get invisible if the state of the REPL drifts from the state of the files on disk. I think the combination of two technologies can alleviate that mental overhead: test && commit || revert (TCR) and clj-reload.

  1. TCR will keep people’s mental models in sync.
  2. clj-reload will keep files in sync with the REPL

A way to do TCR is to keep a file watcher running that on every save,

  1. Runs the tests
  2. Commits the tests if the tests are passing
  3. Otherwise reverts the code.

I’ve used TCR with Elm (programming language). It helped me think in smaller steps, and get progress faster. With Elm, I used the compiler (type checker) as the test step of TCR. A cold-start compile took less than 100 ms.

In Clojure, I don’t want to cold-start the JVM in order to run the tests.

My hypothesis is that we can still use TCR by embedding the TCR loop into the running program. Rather than

$ ./tcr.sh

in a terminal, we run

user> (tcr)

in a REPL.

We’ll see if this works out.

How far can you go?

TCR pushes batch size down. I’d like to push impact up. Let’s not stop at a commit on a branch. Let’s deploy the live application with live data.

I think this could work with mob-programming and TCR; then automatically deploy to production.

(note: this is a less ambitious version of what Bret Victor already is doing with Dynamicland)

April 29th—May 5th

Distraction, over-engineering or curiosity, can one tell the difference?

This is going to be yet another “writing about the practice of writing” pieces. I’m having a bit of a hard time getting into the habit of writing weeknotes. But I’ve decided to be consistent over great, so I’m putting aside half an hour for writing weeknotes, starting at 2024-05-05 11:18.

I quickly realized that in order to write weeknotes I can be proud of, I need to get better at taking notes during the week. Otherwise, I’ve forgotten all the things I wanted to bring up in weeknotes.

So, I should use samsung notes, right? Something simple? Or perhaps something more advanced, like Roam Research, since that’s a note taking app I enjoy using?

Nope. I have to make something from scratch. I enjoy having agency over the tools I use. That lets me optimize for my global workflow. Also, I just really enjoy being able to design systems, not just use systems others have made.

So I made an app. You can try it at https://weeknotes-notes.apps.garden/. Just beware everything is public, the page lists all weeknotes ever written (from you, me, and anyone else). The source is public too, https://github.com/teodorlu/weeknotes-notes.

Privacy is required for safe exploration

So I wrote my own weeknotes app, assuming privacy is irrelevant. I quickly realized that this assumption was wrong. Privacy is relevant! I want to keep my own stuff private. Or share the thing with just a few trusted friends.

Then, we can create a small world where we interact with rules different from the rest of the Internet. (Bret Victor gives an interesting perspective on “research as the creation of microworlds” in Bootstrapping Research & Dynamicland, Dec 2019).

So, I think a next step I want is something I can use with a few trusted friends.

Make things from scratch or use tools others have made?

Let’s say you want to make your own little microworld. Should you start from zero? Or should you make your thing based on things other people have made?

Here’s my take:

In other words, I think you should do both. Try making it from scratch. And try using tools others have made.

When creativity dwindles, duty and discipline can pick up the slack

This week I also (almost) didn’t write weeknotes because I didn’t know what to say. Which means I shouldn’t write weeknotes, right? The muse has left me, and the though of writing does not fill me with joy?


That is not what I promised myself when I started to write weeknotes. From my first weeknote:

Weeknotes seem to hit a sweet spot. Once a week, I can do that. I can even schedule time in my calendar!

My duty is not to write great weeknotes. My duty is to sit down and do the work so that at one point, the weeknotes might be better than when I first started out.

Weeknotes retrospective

So, bad stuff? Problems?

May 6th—May 26th

Pain on Steel


Pain washes over steel. The surface is sleek, hard. It holds.
Dawn comes. Light supplants darkness.
I can see. I see the pain, the steel, the story. It will be okay.

—Teodor, 2024-05

Canonical page: Pain on Steel.

Your Ethics


You tried following their ethics. It worked, until it did not.
Where did their ethics come from? There was no single source.
What is right? You have started finding your answers.

—Teodor, 2024-05

Canonical page: Your Ethics.

Meetups, tribes and growing together

I had a terrific experience organizing a Clojure Norway meetup for learning Babashka. The meetup was in-person and there is no recording. But I about things I learned in Norwegian on Mikrobloggeriet: OLORM-56: Dit og tilbake igjen—TDD, TCR fra en REPL og tilbake til TDD. I might write an English version, but that is not for now.

We did the following:

  1. I explained what Babashka is.
  2. I provided some examples for using babasha/fs, babashka/process and babashka/cli, three libraries that make shell scripting with Clojure a joyful experience.
  3. Emil Bengtsson showed a babashka-powered tool for working remotely with Docker containers, which used lispyclouds/bblgum for the UI
  4. We mob-programmed a Babashka script for converting Pandoc JSON to Hiccup.

I had a great time. We learned something together, and we got to know each other.

My jaw dropped when Peter Strömberg decided to travel from Stockholm to Oslo to attend the meetup, and we got to chat. I feel like Peter has internalized something important about how people can work together in great teams, but I’m unable to articulate what it is.

Mob-programming a Babashka script with the Norwegian Clojure community, Christian Johansen and Peter Strömberg

I recently mob-programmed a Babashka script with Norwegian Clojure programmers. In advance, I had asked Christian Johansen and Peter Strömberg for help. I’m so happy I asked for their help, and I’m super happy with the result.

Here are some observations:

  1. Christian took lead on design & instruction. He led us into a shallow implementation driven by unit tests.

  2. Peter took more of a back-seat role.

  3. We digressed into a discussion of dispatch and polymorphism in Clojure. Our implementation was one big case statement. Multimethods were proposed as an alternative. We continued with a single case, under the argument that it was easy to work with. The whole implementation is contained in one place (cohesion), and redefinition from a REPL is easy. No dangling defmethods in other places. We were able to do this because we were not writing a library, and did not require library consumers to extend our functionality.

    The result of the whole mob programming session can be read in one commit: https://github.com/teodorlu/pandocir/commit/13475492accd6de0b682ed677bbf9969e04d47ec

    I’ll embed the gist here. First, the tests. We wrote the tests first.

    (deftest space-test
      (is (= " " (pandoc2hiccup/pandoc-block->hiccup {:t "Space"}))))
    (deftest string-test
      (is (= "there"
             (pandoc2hiccup/pandoc-block->hiccup {:t "Str", :c "there"}))))
    (deftest emph-test
      (is (= [:em "there"]
              {:t "Emph", :c [{:t "Str", :c "there"}]}))))
    (deftest para-test
      (is (= [:p "hi," " " [:em "there"] "!"]
              {:t "Para",
               [{:t "Str", :c "hi,"}
                {:t "Space"}
                {:t "Emph", :c [{:t "Str", :c "there"}]}
                {:t "Str", :c "!"}]}))))
    (deftest hiccup-test
      (is (= '([:p "hei"] [:p "oslo" " " "clojure"])
              {:pandoc-api-version [1 23 1],
               :meta {},
               [{:t "Para", :c [{:t "Str", :c "hei"}]}
                {:t "Para",
                 :c [{:t "Str", :c "oslo"} {:t "Space"} {:t "Str", :c "clojure"}]}]}))))

    Then, the implementation. After writing space-test, we extended pandoc-block->hiccup to work for that test.

    (defn pandoc-block->hiccup [{:keys [t c]}]
      (case t
        "Space" " "
        "Str" c
        "Emph" (into [:em] (map pandoc-block->hiccup c))
        "Para" (into [:p] (map pandoc-block->hiccup c))))
    (defn pandoc->hiccup [{:keys [blocks]}]
      (map pandoc-block->hiccup blocks))

    I was baffled by how short & clear the implementation and tests were.

  4. I’ve been thinking too much top down. Peter reflected that he often thinks “middle-down”. But let’s keep advanced moode for later.

  5. do: represent your core as data, work in the REPL. What is your core? You want to make that easy to work on. Don’t sit looking at a web browser. That gives you only a very narrow view into what the code does, and you can’t use the REPL properly.

  6. don’t: write long functions that do too much. Those functions can’t be tested. Split up your code, and it will help you.

  7. don’t: arbitrarily split your implementation into multiple pieces. We could have made separate functions for converting space, trings, emphasis and paragraphs into hiccup. But that’s not really units of code we want to test. Our unit is a pandoc data block, and a hiccup data block.

  8. do: get to the point. I spent more time introducing everything than I could have. It was my job to have a plan. I could have shown the plan, then followed the plan. No need to repeatedly shove the plan down everyone’s throats. Instead, show the plan, then follow the plan. I probably wouldn’t have seen this without discussions with Peter Strömberg after the meetup.

Llewellyn Falco-inspired retrospective questions

I’ve become a fan of protospectives and retrospective. In a protospetive, I ask people what they want to achieve during the next hour or two of collaboration. In a retrospective, I’ve asked people for good and bad things the last hour or two.

Falco does retrospectives differently. He asks for topic-oriented observations, not value judgements.

I think topic-oriented observations is better than value judgements. I think they are easier to provide, and more relevant to share. Judgment is hard. Observation is easier, and often truer.

This is his full quote:

I usually start with the 1st layer: PETTDLES

Then ask for observations. I do the grouping based on what is said

I’d like to try this in my next retrospective.