<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Morris Brodersen</title>
  <description>Thoughts, observations, insights, mostly from my experience in software engineering</description>
  <link>https://morrisbrodersen.de</link>
  <atom:link href="https://morrisbrodersen.de/rss.xml" rel="self" type="application/rss+xml" />
  <lastBuildDate>Sat, 11 Apr 2026 11:11:20 GMT</lastBuildDate>
  <pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate>
  <ttl>3600</ttl>

  <item>
        <title>Outlining</title>
        <description>&lt;p&gt;I&amp;nbsp;find it difficult to &amp;ldquo;teach&amp;rdquo; staff-level software engineering
work (system design, technical planning, etc.) as there are no hard and fast
rules. On the contrary, it’s about knowing when to &lt;em&gt;break&lt;/em&gt; the rules, which
requires experience and getting comfortable with ambiguity.&lt;/p&gt;
&lt;p&gt;These &lt;a href=&quot;https://commoncog.com/tacit-knowledge-is-a-real-thing/&quot;&gt;kind of skills&lt;/a&gt;
are best acquired by working on real projects, with real constraints, and expert
guidance. However, those projects are (rightfully) limited; it’s hard to get
enough exposure for people in an organization to level up consistently.&lt;/p&gt;
&lt;p&gt;To fill this gap, I’ve recently started a workshop format for practicing system
design and technical planning called &lt;strong&gt;outlining&lt;/strong&gt;. It features a powerful
overlap of deliberate practice and real work, and goes like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pick (or invent!) a &lt;strong&gt;realistic, unplanned project&lt;/strong&gt; in our context.&lt;/li&gt;
&lt;li&gt;Find a small group of &lt;strong&gt;interested people&lt;/strong&gt; (3-10 people).&lt;/li&gt;
&lt;li&gt;Pick a time box (1-2 hours).&lt;/li&gt;
&lt;li&gt;Meet and work on a &lt;strong&gt;rough outline&lt;/strong&gt; for the given project (tasks, questions,
risks, and so on). Bullet points and diagrams only!&lt;/li&gt;
&lt;li&gt;Log the result; actual implementation or following up is not required.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It sounds simplistic, but so far these workshops have always been fun, intense,
and uniquely rewarding. We discuss project requirements, architectural
constraints, and dive into existing systems and code to understand how the given
project could fit in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What data needs to be gathered and processed?&lt;/li&gt;
&lt;li&gt;What system components need to be changed, in what order?&lt;/li&gt;
&lt;li&gt;What trade-offs do we need to make based on known constraints?&lt;/li&gt;
&lt;li&gt;What difficulties, risks, and second-order effects can we anticipate?&lt;/li&gt;
&lt;li&gt;How might we find answers to open questions?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Working these kind of questions in the context of a real system we’re familiar
with, but without the pressure to implement or report, provides a frame &lt;em&gt;just
right&lt;/em&gt; for learning and knowledge building. Groups are often a mix of experts
and active listeners of any level; that way, anyone can get exposure, but the
group can always make good progress.&lt;/p&gt;
&lt;p&gt;Besides leveling up the team, I’m seeing some additional positive effects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Increased estimation quality&lt;/li&gt;
&lt;li&gt;Increased domain knowledge&lt;/li&gt;
&lt;li&gt;Deeper understanding of our own systems&lt;/li&gt;
&lt;li&gt;Reduced barrier to tackle difficult technical migrations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Best of all, features which were considered &amp;ldquo;impossible&amp;rdquo; before
became tangible through outlining, and some have made it &lt;strong&gt;into production!&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Here are some more practical tips and tricks for outlining sessions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use the outline as a “working memory” for the group. Start with a blank page,
then write down notes, thoughts and open questions as you go, even if you
resolve them later. That way, you can park items mentally and revisit them
later.&lt;/li&gt;
&lt;li&gt;Work the subject breadth-first, i.e. start on a high level and only go deeper
as time allows.&lt;/li&gt;
&lt;li&gt;Do not remove incomplete items when closing the session, as they can provide
valuable insights.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Happy outlining! ∎&lt;/p&gt;
</description>
        <link>https://morrisbrodersen.de/outlining</link>
        <guid>https://morrisbrodersen.de/outlining</guid>
        <pubDate>Sun, 01 Feb 2026 00:00:00 GMT</pubDate>
      </item>
<item>
        <title>The Power is in the Network</title>
        <description>&lt;p&gt;... or, why LLMs have no place in internal communications of high-performing
organizations.&lt;/p&gt;
&lt;p&gt;Organizations depend on their inner relationships. The quality of these
relation&amp;shy;ships often make or break an organization’s mission: Is there
enough trust between peers to collaborate? Are leaders able to motivate and
inspire? Are we willing to make sacrifices for each other?&lt;/p&gt;
&lt;p&gt;Relationships are shaped by communication, with all its
&lt;a href=&quot;https://en.wikipedia.org/wiki/Four-sides_model&quot;&gt;facets&lt;/a&gt;. People read far
between the lines, looking for authenticity and care, not just raw information,
in every signal. Relationships suffer when we’re unable to connect to the person
behind the signal.&lt;/p&gt;
&lt;p&gt;Communicating with the intent to connect requires authenticity. Being authentic
can be difficult and uncomfortable, especially in writing&lt;sup&gt;&lt;a id=&quot;footnote-ref-1&quot; href=&quot;#footnote-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Writing well
takes time and practice, and unfortunately, there are no shortcuts. But whatever
you do, do&amp;nbsp;&lt;em&gt;not&lt;/em&gt; reach for&amp;nbsp;LLMs.&lt;/p&gt;
&lt;p&gt;LLMs are &lt;em&gt;hopeless&lt;/em&gt; at producing communication fit for building relationships.
&lt;strong&gt;There is no chance an LLM can get enough context about a specific situation
and the involved people to consistently produce authentic text.&lt;sup&gt;&lt;a id=&quot;footnote-ref-2&quot; href=&quot;#footnote-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/strong&gt; We would
have to provide &lt;em&gt;books&lt;/em&gt; worth of context, not to mention that
&lt;a href=&quot;https://commoncog.com/tacit-knowledge-is-a-real-thing/&quot;&gt;not everything can be described with words&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;LLMs don’t know about shared history or values, prior conversations, the
individual needs of involved people, the little social cues of the day. When we
speak to someone, we tap into those things intuitively. When using LLMs, it’s
unreasonable to provide so much context upfront, and it’s not enough to add a
personal touch onto an LLM-generated draft&lt;sup&gt;&lt;a id=&quot;footnote-ref-3&quot; href=&quot;#footnote-3&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;LLM-generated text erodes relationships. Weaker relationships lead to weaker
organizations. It’s really that simple.&lt;/p&gt;
&lt;p&gt;Don’t send LLM-generated walls of text to your colleagues. They don’t care that
much about grammar. They don’t care about &lt;em&gt;crucial&lt;/em&gt;. They care that you care,
and they are trying to see &lt;em&gt;you&lt;/em&gt; behind the message.&lt;/p&gt;
&lt;p&gt;Don’t summarize texts your colleagues have put time and energy into. You’re
missing out on a chance to connect to them, if only by understanding them
better. If a text is too long, let the author know why you think that. Show them
that you care about what they wrote.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LLMs will always, by design, be perfect strangers&lt;/strong&gt;, through which we cannot
hope to communicate with honesty and care. LLMs may or may not be fit for other
things, but using them to communicate within organizations is indefensible.&lt;/p&gt;
&lt;p&gt;The power of a high-performing organization is in its network of relationships.
People that feel connected and cared about will care about the organization in
return. Taking the time to &lt;em&gt;really&lt;/em&gt; communicate with your colleagues is the most
important sign of care, and must not be replaced.&amp;nbsp;∎&lt;/p&gt;
&lt;hr data-footnotes&gt;
&lt;section class=&quot;footnotes&quot; data-footnotes&gt;

&lt;ol&gt;
&lt;li id=&quot;footnote-1&quot;&gt;
&lt;p&gt;When in doubt, write how you would speak. &lt;a href=&quot;#footnote-ref-1&quot; data-footnote-backref aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;footnote-2&quot;&gt;
&lt;p&gt;Technically, it could be possible: We just need to introduce &lt;em&gt;total&lt;/em&gt;
surveillance, and grant LLMs full access to the tapes. Let’s &lt;em&gt;not&lt;/em&gt;. &lt;a href=&quot;#footnote-ref-2&quot; data-footnote-backref aria-label=&quot;Back to reference 2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;footnote-3&quot;&gt;
&lt;p&gt;That’s the modern &amp;ldquo;shit sandwich&amp;rdquo;: Beginning and ending have a
personal touch, but the middle is generic LLM slop. &lt;a href=&quot;#footnote-ref-3&quot; data-footnote-backref aria-label=&quot;Back to reference 3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
        <link>https://morrisbrodersen.de/the-power-is-in-the-network</link>
        <guid>https://morrisbrodersen.de/the-power-is-in-the-network</guid>
        <pubDate>Thu, 28 Aug 2025 00:00:00 GMT</pubDate>
      </item>
<item>
        <title>Designing Together</title>
        <description>&lt;p&gt;Some time ago, I&amp;nbsp;helped build a small translation feature. Our users
regularly needed to translate some of their assets, and we figured it would be
straight&amp;shy;forward to integrate translation right into our platform. In the
morning, I&amp;nbsp;received a UI&amp;nbsp;design file and got to work.&lt;/p&gt;
&lt;p&gt;In our backend, translation was already available as a reusable primitive. Based
on that, implementing a user-facing endpoint for translating this specific kind
of asset took less than an hour.&lt;/p&gt;
&lt;p&gt;As for the frontend, there already was a context menu for each asset. The UI
design featured a new &amp;ldquo;Translate to...&amp;rdquo; menu item, which was
supposed to bring up a submenu of available languages.&lt;/p&gt;
&lt;p&gt;Unfortunately, our component library didn’t support submenus yet. For a moment,
I&amp;nbsp;was stuck; in my experience, getting submenus working &lt;em&gt;just right&lt;/em&gt; is
non-trivial, and I&amp;nbsp;felt chasing robust submenus right now would only yield
marginal value (if any).&lt;/p&gt;
&lt;p&gt;However, our component library &lt;em&gt;did&lt;/em&gt; have dialogs, so I&amp;nbsp;went and made the
new menu item open a separate dialog for language selection instead, which
worked well. I shared a screenshot, explained how submenus are probably not
worth it, everyone agreed, happy merging.&lt;/p&gt;
&lt;p&gt;The feature landed in our staging environment in about &lt;strong&gt;two hours&lt;/strong&gt;, which was
a nice turnaround due to
&lt;a href=&quot;/agility-and-friction&quot;&gt;fast pipelines and robust tooling&lt;/a&gt;. We were able to play
with it, adjusted some details, and were ready for production before lunch.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This small anecdote may sound like &amp;ldquo;just another day at the office&amp;rdquo;,
but in my experience, there are plenty of potential failure modes here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not even looking for more economical alternatives, missing an opportunity&lt;/li&gt;
&lt;li&gt;Taking on the submenus without informing anyone, risking a delay&lt;/li&gt;
&lt;li&gt;Rushing the submenus, risking bugs&lt;/li&gt;
&lt;li&gt;Handing the issue back to the UI&amp;nbsp;designer to come up with alternatives&lt;/li&gt;
&lt;li&gt;Insisting on the marginally better design, even if high effort&lt;/li&gt;
&lt;li&gt;Not seeing that submenus can follow in a later iteration&lt;/li&gt;
&lt;li&gt;Delegating the UI&amp;nbsp;work to the maintainers of the component library&lt;/li&gt;
&lt;li&gt;Complaining about it as a planning mistake&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve been guilty of all of these in similar situations. I&amp;nbsp;know any of those
decisions could have meant &lt;em&gt;days&lt;/em&gt; of additional lead time for this one simple
task, without adding significant value. If you do dozens of such tasks, costs
compound quickly.&lt;/p&gt;
&lt;p&gt;While there is no silver bullet for avoiding such inefficiencies altogether,
I&amp;nbsp;believe the one thing we got right this time was &lt;strong&gt;sharing the design
process&lt;/strong&gt;, beyond the handover of the UI&amp;nbsp;design file, and beyond our
individual roles. In the words of one of the most important American designers
of the 20th century:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here is one of the few effective keys to the design problem: the ability of
the designer to recognize as many of the constraints as possible, [their]
willingness and enthusiasm for working within these constraints. The
constraints of price, size, strength, balance, time and so forth. Each problem
has its own peculiar list. &amp;mdash;&amp;nbsp;&lt;em&gt;Charles Eames&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Rather than thinking in terms of planning and resources &lt;em&gt;after&lt;/em&gt; the design
phase, we saw timing and effort as &lt;em&gt;design constraints&lt;/em&gt; to work with, and made
significant adjustments to our initial design based on these, even late in the
process.&lt;/p&gt;
&lt;p&gt;In software development, you want this to happen, and often. This is how you win
back efficiency lost to unknown unknowns, and save opportunity costs better
spent on chasing the next big thing.&lt;/p&gt;
&lt;p&gt;To me, this is the ideal of cross-functional work: Embracing constraints from
outside our bubble, taking an economic perspective, and designing
together.&amp;nbsp;∎&lt;/p&gt;
</description>
        <link>https://morrisbrodersen.de/designing-together</link>
        <guid>https://morrisbrodersen.de/designing-together</guid>
        <pubDate>Thu, 24 Jul 2025 00:00:00 GMT</pubDate>
      </item>
<item>
        <title>Functional Core Diagrams</title>
        <description>&lt;p&gt;I often follow the
&lt;a href=&quot;https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell&quot;&gt;functional core, imperative shell&lt;/a&gt;
way of constructing software:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Isolate business logic into a set of pure functions (the functional core).&lt;/li&gt;
&lt;li&gt;Implement side-effects and mutable state in a thin layer around the core (the
imperative shell).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This not only shapes how I write code, but also how I think. When designing a
software system, I’ll assume the functional core and the imperative shell are
independent. This allows me to ignore servers, storage, networks, and other
technical constraints when starting out.&lt;/p&gt;
&lt;p&gt;Instead, I can focus on data and functions in the abstract, which are (by
definition) enough to describe the functional core of the system: What needs to
be computed, and from what? What intermediary data and functions can I
anticipate?&lt;/p&gt;
&lt;p&gt;I’ve found drawing the flow of data types through the functional core to yield
useful system diagrams. For example:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/functional-core-diagrams/example.png&quot; alt=&quot;Example FCD&quot;&gt;&lt;/p&gt;
&lt;p&gt;This article illustrates the properties and use of these &lt;strong&gt;functional core
diagrams&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;(I’m probably reinventing some wheel here. So far, I haven’t found a diagram
type with the nuance I’m looking for. A
&lt;a href=&quot;https://en.wikipedia.org/wiki/Data-flow_diagram&quot;&gt;data-flow diagram&lt;/a&gt; comes
close, but it’s a bit too rigid. If you can think of something,
&lt;a href=&quot;mailto:mb@morrisbrodersen.de&quot;&gt;let me know!&lt;/a&gt;)&lt;/p&gt;
&lt;h2&gt;Definition&lt;/h2&gt;
&lt;p&gt;A functional core diagram (FCD) is a directed graph with two kinds of nodes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Types&lt;/li&gt;
&lt;li&gt;Functions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An FCD allows the following edges:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Arguments: Types point to functions accepting them.&lt;/li&gt;
&lt;li&gt;Results: Functions point to their return types.&lt;/li&gt;
&lt;li&gt;Subtypes: Types point to their subtypes (if any).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Types and functions are &lt;em&gt;abstract&lt;/em&gt;. They need not reflect a concrete
implementation, but should have clear semantics.&lt;/p&gt;
&lt;p&gt;I use rectangles for types, and hexagons for functions, but any distinct shapes
work. Types are in noun-form, functions are in verb-form. Colorings may group
types and/or functions.&lt;/p&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;p&gt;I use FCDs to explore potential layouts for a software system. I start with
known inputs and outputs and connect the gaps with (abstract) functions and
intermediary types, until I’m confident the design is sound.&lt;/p&gt;
&lt;p&gt;While drawing candidate diagrams, I’ll look out for various system properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dependencies&lt;/li&gt;
&lt;li&gt;Coupling&lt;/li&gt;
&lt;li&gt;Module boundaries&lt;/li&gt;
&lt;li&gt;Transaction boundaries&lt;/li&gt;
&lt;li&gt;Standard data types&lt;/li&gt;
&lt;li&gt;Opportunities for caching&lt;/li&gt;
&lt;li&gt;Opportunities for concurrency&lt;/li&gt;
&lt;li&gt;Hot paths&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When I identify a problem (e.g. unnecessary coupling) I’ll try to &lt;em&gt;refactor&lt;/em&gt; the
FCD, almost like code. In that sense, FCDs are like &lt;em&gt;graphical pseudo-code&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For example, the introductory diagram can be refactored to be less coupled to
the CSV format, and support additional output formats:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/functional-core-diagrams/refactoring.png&quot; alt=&quot;Refactoring an FCD&quot;&gt;&lt;/p&gt;
&lt;p&gt;Notice how the new type for chart series emerges as a natural boundary,
something immediately visible in the FCD. (Adding support for more input types
is left as an exercise for the reader.)&lt;/p&gt;
&lt;p&gt;It’s hard to pin down the list of things to look out for, or when and why to
refactor. Like with many skills, it takes a bit of practice to build an
intuition and get good results.&lt;/p&gt;
&lt;h2&gt;Colorings&lt;/h2&gt;
&lt;p&gt;I use colorings to group types and functions by various properties. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Which module is responsible for which function?&lt;/li&gt;
&lt;li&gt;Which data needs to be persistent?&lt;/li&gt;
&lt;li&gt;Which workloads belong on the server-side, which can be run client-side?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following is a real-world FCD with a coloring specifying where to implement
functions in a service-oriented architecture (labels removed):&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/functional-core-diagrams/colorings.png&quot; alt=&quot;FCD with colorings&quot;&gt;&lt;/p&gt;
&lt;p&gt;Discovering the dependency on the yellow function in the upper right early saved
us from a difficult refactoring later on.&lt;/p&gt;
&lt;h2&gt;Abstraction&lt;/h2&gt;
&lt;p&gt;FCDs allow abstraction and imprecision by design. For example, listing all
inputs and outputs of a system and connecting them by one big function is a
valid FCD, however useful. On the other hand, an FCD laying out &lt;em&gt;every&lt;/em&gt; type and
&lt;em&gt;every&lt;/em&gt; function of a concrete implementation is probably too granular.&lt;/p&gt;
&lt;p&gt;Being able to explore this “search space” graphically feels both natural and
powerful. Finding the right level of abstraction is key—just enough depth that I
can confidently explain the system to myself and others, but not more.&lt;/p&gt;
&lt;h2&gt;Limitations&lt;/h2&gt;
&lt;p&gt;Not all system designs benefit from an FCD. For example, systems where efficient
I/O is an inherent goal (e.g. databases, video streaming, etc.) often have a
shallow functional core, and the design problems are found in concrete
technology or infrastructure.&lt;/p&gt;
&lt;p&gt;FCDs don’t capture choice, temporal order, or relations between types. For these
purposes, consider activity diagrams, sequence diagrams or entity relationship
diagrams.&lt;/p&gt;
&lt;p&gt;Finally, functional cores are generally &lt;em&gt;not&lt;/em&gt; independent from imperative
shells. At some point, we have to invite the real world in (computers, memory
limits, networks, etc.) and may have to adjust our functional core to fit these
constraints.&lt;/p&gt;
&lt;p&gt;(Incidentally, the moment when I have to adapt an otherwise ideal functional
core to fit the real world has become my definition of
&lt;a href=&quot;https://en.wikipedia.org/wiki/No_Silver_Bullet&quot;&gt;accidental complexity&lt;/a&gt;.)&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;FCDs are no silver bullet, but I often find drawing the functional core of a
system a worthwhile exercise. Most of all, I enjoy the organic construction of
FCDs: I can start with a diagram as simple as one big function, and refactor it
until I’m satisfied with the level of detail.&lt;/p&gt;
&lt;p&gt;I suspect there are some fundamental properties making FCDs effective
(&lt;a href=&quot;https://en.wikipedia.org/wiki/Category_theory&quot;&gt;category theory&lt;/a&gt; comes to
mind). In any case, I hope I was able to present FCDs as a practical, useful
tool for system design. ∎&lt;/p&gt;
</description>
        <link>https://morrisbrodersen.de/functional-core-diagrams</link>
        <guid>https://morrisbrodersen.de/functional-core-diagrams</guid>
        <pubDate>Mon, 10 Feb 2025 00:00:00 GMT</pubDate>
      </item>
<item>
        <title>How Do You Like What You’ve Built?</title>
        <description>&lt;p&gt;Recently, a colleague asked me for a code review on some complex UI changes. The
idea was to make an error-prone form easier to use by displaying warnings in the
right moment, and automating various state changes in the background (think
“smart configurator”). The requirements were given upfront, so my colleague was
in execution mode, turning these requirements into code.&lt;/p&gt;
&lt;p&gt;Glancing over the pull request, nothing stood out as problematic, but I didn’t
feel ready to approve the changes before playing with the new UI.&lt;/p&gt;
&lt;p&gt;However, before testing it myself, I asked (via chat message):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How do you like the new behavior?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I went to grab a coffee; when I came back, they had answered with roughly the
following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not sure, to be honest.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A couple minutes pass...&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It feels a bit off, like sometimes I can’t really make the changes I want as a
user.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Another pause...&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Actually there’s still another bug I need to fix, let me get back to you. This
needs to be rock-solid for our users!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I can only assume what happened in the meantime, but it seems asking them for
their opinion (and &lt;em&gt;not&lt;/em&gt; responding for a while) was a cue for
&lt;a href=&quot;https://blog.jim-nielsen.com/2024/sanding-ui/&quot;&gt;sanding the UI&lt;/a&gt;, with great
results: In the end, a problematic requirement was dropped and multiple commits
were added before the actual review.&lt;/p&gt;
&lt;p&gt;Later, knowing how the author had engaged with their solution, reviewing and
approving the changes felt very comfortable.&lt;/p&gt;
&lt;p&gt;I find it remarkable how a simple question can have such an outsized impact. Of
course, my colleague’s particular reaction to it was fantastic, and not to be
taken for granted. They took ownership and got to work, and were able to
critically look at the requirements and their solution. Thank you!&lt;/p&gt;
&lt;p&gt;In any case, I believe asking engineers how &lt;em&gt;they&lt;/em&gt; like what they’ve built to be
a useful trick to try from time to time. I&amp;nbsp;suspect only upside. ∎&lt;/p&gt;
</description>
        <link>https://morrisbrodersen.de/how-do-you-like-what-you-built</link>
        <guid>https://morrisbrodersen.de/how-do-you-like-what-you-built</guid>
        <pubDate>Fri, 03 Jan 2025 00:00:00 GMT</pubDate>
      </item>
<item>
        <title>On Agility and Friction</title>
        <description>&lt;p&gt;I find it useful to treat agile software development as an &lt;em&gt;outcome&lt;/em&gt;, rather
than something we can &lt;em&gt;adopt&lt;/em&gt;. Taking that perspective, we can
&lt;a href=&quot;https://fs.blog/inversion/&quot;&gt;invert the problem&lt;/a&gt; and ask:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What is making us less agile, right now?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The answer is often surprisingly tangible, and rarely about missing agile
methods. It is about the concrete &lt;em&gt;friction&lt;/em&gt; we encounter when trying to get
work done. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Slow builds&lt;/li&gt;
&lt;li&gt;Deployment dependencies&lt;/li&gt;
&lt;li&gt;Cumbersome software architecture&lt;/li&gt;
&lt;li&gt;Recurring manual verification of changes&lt;/li&gt;
&lt;li&gt;Hand-overs&lt;/li&gt;
&lt;li&gt;Silos&lt;/li&gt;
&lt;li&gt;Gatekeeping&lt;/li&gt;
&lt;li&gt;Firefighting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In high friction environments, making decisions is risky. Change is slow,
therefore making bad decisions is expensive, and therefore more time is invested
in planning in order to avoid bad decisions. In the worst case, new controls are
introduced, resulting in more friction. These environments become less agile
over time, regardless of any agile method.&lt;/p&gt;
&lt;p&gt;To break this cycle, fixing obvious sources of friction is often easier than
reaching for new process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reduce pipeline times&lt;/li&gt;
&lt;li&gt;Enable continuous integration&lt;/li&gt;
&lt;li&gt;Enable ad-hoc production deployments&lt;/li&gt;
&lt;li&gt;Enable self-service infrastructure&lt;/li&gt;
&lt;li&gt;Simplify development environments&lt;/li&gt;
&lt;li&gt;Fix regular sources of bugs&lt;/li&gt;
&lt;li&gt;Add automated checks&lt;/li&gt;
&lt;li&gt;Increase observability&lt;/li&gt;
&lt;li&gt;Disband committees&lt;/li&gt;
&lt;li&gt;Training&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This list is widely applicable; none of these actions require organizational
change, but will make most organizations more agile (as in, able to react and
adapt to new information more effectively).&lt;/p&gt;
&lt;p&gt;Interestingly, most agile methods are all about avoiding friction, if you read
them carefully. One could even argue that friction is &lt;em&gt;just&lt;/em&gt; the other side of
the same coin.&lt;/p&gt;
&lt;p&gt;However, reducing friction, as an explicit approach or as a goal, is inherently
&lt;em&gt;simplifying&lt;/em&gt; and &lt;em&gt;empowering&lt;/em&gt;. It is a natural driver towards less overhead. It
is descriptive and actionable, not prescriptive. It is easier to rally behind
removing friction than to convince an organization to adopt new process, roles,
or ceremony, which is almost always disruptive.&lt;/p&gt;
&lt;p&gt;Note that friction is not a set of things to optimize individually. Some
friction can be good in the long term, and there may be complex interactions
between different kinds of friction. Mandatory code reviews, for example, can be
considered an expensive slowdown, but can act as training.&lt;/p&gt;
&lt;p&gt;Managing friction is a design problem, and should be a first-class citizen of
any software development strategy. True agility emerges when friction is low,
while process, roles, and ceremony should be of secondary concern. ∎&lt;/p&gt;
</description>
        <link>https://morrisbrodersen.de/agility-and-friction</link>
        <guid>https://morrisbrodersen.de/agility-and-friction</guid>
        <pubDate>Fri, 27 Dec 2024 00:00:00 GMT</pubDate>
      </item>

</channel>
</rss>
