<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://thinkingsideways.net/feed.xml" rel="self" type="application/atom+xml" /><link href="https://thinkingsideways.net/" rel="alternate" type="text/html" /><updated>2026-02-24T19:58:34+00:00</updated><id>https://thinkingsideways.net/feed.xml</id><title type="html">Thinking Sideways</title><subtitle>A software development blog for my thoughts on various topics in professional software development.  Focus topics are clean code, automated tests, kanban, scrum, anti-patterns, object orientation and scalable team organization.</subtitle><entry><title type="html">Organizational Scalability</title><link href="https://thinkingsideways.net/people/organizational-scalability.html" rel="alternate" type="text/html" title="Organizational Scalability" /><published>2026-02-24T08:26:01+00:00</published><updated>2026-02-24T08:26:01+00:00</updated><id>https://thinkingsideways.net/people/organizational-scalability</id><content type="html" xml:base="https://thinkingsideways.net/people/organizational-scalability.html"><![CDATA[<p>When developers talk about scalability, we’re chiefly referring to technical scalability. In other words, we want to enable our systems to gracefully handle growing loads. This is a technical problem, and as with most technical problems, it’s well understood and manageable. However, there’s a related problem that is primarily a people problem: organizational scalability. This topic is rarely explored, which makes it worthy of its own blog post.</p>

<p>In the context of this blog post, organizational scalability is defined as the ability of our organization to gracefully handle growing success. This includes having more customers, a higher market share, more employees, and everything else that comes with it. Technical scalability is a subset of organizational scalability, as it’s also only relevant when we’re successful. After all, if nobody uses our software, we don’t need to worry about our servers getting overloaded.</p>

<p>Even though organizational scalability is only relevant when we’re successful, that doesn’t mean that it’s a luxury problem. Insufficient organizational scalability can significantly slow down our growth. As growth is king in the software industry, any loss of momentum can be a serious threat to our business. So, how can we prepare for success on an organizational level in the context of software development? I was fortunate enough to experience sustained success and growth during my time with SuccessFactors and hence have a few recommendations.</p>

<p>It’s important to stress that these recommendations are only for established companies! If we’re still unsure whether the company will survive at all, then we need to focus on the basics: find our market and get enough cash flow. Only once we’ve established ourselves and started to see some early signs of success should we think about our organizational scalability.</p>

<p>Furthermore, I only recommend practices that are also beneficial to small development teams. It would be ridiculous to implement something like <a href="https://framework.scaledagile.com/#big-picture">SAFe</a> in a small team just because we might need it ten years down the road. With that out of the way, let’s dive into the recommendations in detail.</p>

<h4 id="prepare-for-new-hires">Prepare For New Hires</h4>
<p>Success increases demand for software developers, as more customers mean more feature requests and support tickets. The natural fix for this is to hire more people. It’s expected that growing the team will decrease <a href="https://en.wikipedia.org/wiki/Brooks%27s_law">productivity at first</a>. However, we expect this to turn around after a couple of months.</p>

<p>Sadly, this turnaround isn’t guaranteed, so we need to hire good people and help them get up to speed quickly. First, we need to come up with a way to screen applicants to ensure that we find good candidates. While the team manager will do most of the work in that area, at least some developers should be involved in the hiring process to ensure cultural fit and to help filter out any weak candidates.</p>

<p>After we have hired someone, we need to be prepared for him to show up. That means having the necessary hardware at hand, knowing what access rights he will need and how to get them, and, most important of all, a plan on how to get him up to speed. This plan also includes picking out some introductory work items for him. In my experience, small, low-priority bugs are perfect for this.</p>

<p>I highly recommend appointing a dedicated mentor for every new colleague. The mentor serves as the primary point of contact to answer any questions that the new hire might have. Good documentation is also very helpful for new hires, which leads me to my next point.</p>

<h4 id="have-good-documentation">Have Good Documentation</h4>
<p>As growth means both bigger teams and more capable software, it becomes increasingly difficult to manage information. It gets harder to keep everyone up to date and to keep everything important in mind. As a result, <a href="https://thinkingsideways.net/processes/documentation.html">good documentation</a> becomes essential. It pays off to invest time into documentation early on and to keep the documentation up to date, as it allows everyone on the team to independently hunt down needed information. This is not only very efficient but also removes a lot of friction in distributed teams where asking a colleague might not always be an option. Documentation also helps to retain knowledge. Some employee churn is expected over time, and with comprehensive documentation, we can at least mitigate the brain drain that comes with people leaving.</p>

<p>In addition to writing good documentation, we should properly describe any bugs or features in our issue tracker to make it easy to understand the requirements and the context. I’ve written about this best practice already in more detail <a href="https://thinkingsideways.net/processes/issue-tracker.html">here</a>.</p>

<h4 id="have-some-processes">Have Some Processes</h4>
<p>Even when we’re very small, I highly recommend having some lightweight processes in place. My recommendation would be <a href="https://thinkingsideways.net/processes/kanban.html">Kanban</a>, but anything can work. I think it’s important to have some kind of weekly planning meeting to make sure that we’re aligned on what to do next. We also need an issue tracker where everything we’re currently working on is visible. This way, we can keep track of who’s doing what and easily check on the progress.</p>

<p>We should have a couple of meetings each week to discuss the current state. In these meetings we talk about the current state using the issue tracker as guidance. The general idea is to quickly resolve any blockers and to share knowledge about what the rest of the team is working on. Note that the idea is to focus on the tracker and not on the person! If I haven’t done any work that’s in the tracker, then I just keep quiet. That’s a notable difference compared to a standard Daily Scrum meeting and the key factor why these meetings deliver value in contrast to most Daily Scrums.</p>

<p>It can be tempting to just go without any explicit processes when we’re a very small team. This can also work, especially if the team members have already worked together in the past and know each other’s quirks. However, this way of working doesn’t scale as the information flow is too limited. It also struggles to quickly onboard new colleagues for the same reason. Hence, my advice is to have some processes from the start. Even very lightweight ones can carry us for a long time.</p>

<h4 id="keep-regressions-low">Keep Regressions Low</h4>
<p>Customers expect our software to work. Hence, we need to be very careful not to introduce regressions. This is especially problematic when we’re delivering our software as a service because this usually means that all (or at least most) of our customers get upgraded to a new version at the same time. If we ship a version with a couple of regressions in it, we will receive feedback very quickly and spend the next couple of days shuffling customer tickets and hammering out a fix. Needless to say, this is a poor use of our time and a loss for everyone involved.</p>

<p>If we keep pushing out buggy versions, then the customers we fought so hard to acquire might very well leave and move to a competitor who respects their time. Few companies are able to lock in their customers so tightly that leaving is close to impossible, and even for those companies, low software quality is not a good look. Customer churn is very damaging to a company as it disrupts expected revenue streams and because the cost of acquiring new customers is often very high.</p>

<p>For all these reasons, we should see every regression as a personal failure that should never happen again. We need to understand why it happened and what we can do to prevent it from happening again. I also highly recommend making new features or changes to old ones opt-in. That way, the customer has to actively turn them on instead of receiving a potentially unwelcome surprise from us. Keeping regressions in check requires discipline, but I’m convinced that it pays off in the long term.</p>

<h4 id="learn-from-customer-tickets">Learn From Customer Tickets</h4>
<p>Customer tickets can tell us a lot about what’s wrong with our product. We should use them to figure out which areas of the product aren’t working well and what exactly causes frequent customer problems. For example, if we often see issues that are caused by a misconfiguration of the software on the client’s side, it’s an excellent idea to add further validations and to give better user guidance in the configuration. This helps us to keep our maintenance load under control.</p>

<p>Also, if we frequently encounter data corruption issues, it’s not enough to just fix the corruption and move on. Instead, we need to figure out where exactly these corruptions are coming from and address the root causes. Over time, it should become harder and harder to cause any kind of data corruption in our software.</p>

<h4 id="automated-tests">Automated Tests</h4>
<p>Automated tests are a great way to keep our productivity up, as they prevent fixed bugs from creeping back into the product. As successful products often live for a long time and continuously get more complex, they benefit massively from a comprehensive automated test suite.</p>

<p>Hence, we should get started with automated testing early and keep investing in it over time. <a href="https://thinkingsideways.net/testing/integration-tests.html">I usually recommend sticking to unit tests</a>, but integration tests can be very useful in the early stage of a product when the internal structure isn’t sufficiently clear yet. We need to find the right mixture for our product and situation. An unbalanced test suite can actually reduce productivity, so it’s important to get it right and to keep an eye on it. Unstable and very slow tests can massively reduce productivity and need to be tackled quickly.</p>

<p>Having no automated tests at all is certainly a bad idea, as manual tests have no return on investment. It is fine to only test manually when we’re just getting started, but as soon as we start earning money with our software and plan to expand, we need to start writing automated tests.</p>

<h4 id="embrace-subsidiarity">Embrace Subsidiarity</h4>
<p>In a very small team it’s possible for one leader to make all decisions. However, as we grow, this is no longer an option, as simply too many decisions need to be made. Instead we need to rely on the <a href="https://thinkingsideways.net/processes/subsidiarity.html">subsidiarity principle</a> and delegate the decisions to the people best equipped to make them. Research has shown that this delegation leads to better results. It’s essential for big software development organizations, as coordinating many different teams from top down doesn’t work.</p>

<p>We should strive to build a bottom-up culture from the very start. Otherwise, we might teach our colleagues not to think for themselves and not to share their perspective. Obviously, this is the exact opposite of what we want. For bottom-up to work, people also need the courage to decide things on their own. With the wrong company culture this will never work.</p>

<h3 id="conclusion">Conclusion</h3>
<p>We can improve organizational scalability by preparing for new hires, having good documentation, having some lightweight processes, keeping regressions low, learning from customer tickets, writing automated tests, and embracing subsidiarity.</p>

<p>If you liked this blog post, please share it with somebody. You can also follow me on <a href="https://twitter.com/fxr256">Twitter/X</a>.</p>]]></content><author><name></name></author><category term="people" /><summary type="html"><![CDATA[Software companies should prepare for success by adopting good organization scalability. This blog post gives some recommendations on how to do it.]]></summary></entry><entry><title type="html">Guest Post: Killed by Apathy</title><link href="https://thinkingsideways.net/people/apathy.html" rel="alternate" type="text/html" title="Guest Post: Killed by Apathy" /><published>2025-08-27T08:26:01+00:00</published><updated>2025-08-27T08:26:01+00:00</updated><id>https://thinkingsideways.net/people/apathy</id><content type="html" xml:base="https://thinkingsideways.net/people/apathy.html"><![CDATA[<h3 id="the-dangers-of-apathy">The Dangers of Apathy</h3>
<p>There is a silent killer stalking the software industry: apathy. Apathy can severely impair both individual
employees and whole teams. It is infectious and can turn once great companies into mediocre shells or
even paralyze them completely. And the worst part is that it is often seen as normal and inevitable.</p>

<h3 id="what-is-apathy">What is Apathy?</h3>
<p>The <a href="https://dictionary.cambridge.org/dictionary/english/apathy">Cambridge Dictionary</a> defines apathy
as “behaviour that shows no interest or energy and shows that someone is unwilling to take action,
especially over something important” which is too broad of a definition for this discussion. Instead,
this blog post will use the following definition: Employees are suffering from apathy if they don’t
care about the results of their work unless their performance is directly being measured based on them.</p>

<p>Excellent employees are almost always intrinsically motivated. They will try to find the best solution
for a coding problem, customer ticket, UI design, or whatever else they are currently working on,
even if nobody but them cares. This drive is missing in apathetic employees. They can still produce
acceptable results, but somebody would need to give them very specific acceptance criteria that cover
everything their non-apathetic peers keep in mind when doing their work to get the same level of quality.
Since this is not realistic, apathetic employees will usually produce worse results compared to their
unafflicted co-workers.</p>

<p>Since they are not intrinsically motivated, apathetic employees typically don’t think about their work
process and what they would need to do to improve it (unless someone would tell them to do it, but
this is very rare). As a result, apathetic employees typically <a href="https://thinkingsideways.net/people/developer-growth.html">don’t show improvements over time</a>,
which leads to them falling behind the non-apathetic employees. Eventually, this can create vast
gulfs of productivity inside a team.</p>

<p>At first, apathy is a problem of the individual employee, but once other members of a team become
affected, the entire team is in danger. Apathetic teams will see their productivity stagnate or even
decline over time since they cannot compensate for losses of productivity caused by external factors.
This is a massive problem since lower productivity makes it much more difficult to reduce technical
debt and to achieve the working conditions needed for not having to choose between software quality
and fast feature delivery. This situation can be very difficult to break out of once apathy has spread
far enough in a team.</p>

<p>How common is apathy? Since we cannot peer into the hearts and minds of employees, hard data is difficult
to find. However, there are indicators, and they are not looking good. For example, Tom DeMarco and
Timothy R. Lister mention in their excellent book <a href="https://www.goodreads.com/book/show/67825.Peopleware">Peopleware</a>
that employees in software development projects typically only spend 5% of their time attending trainings,
investigating new methods, or doing other things that can improve long-term productivity. DeMarco
and Lister also report that the average developer does not own a single book on software engineering
and has also never read one. This data indicates a large portion of apathetic employees in the
workforce, since intrinsically motivated employees spend considerable amounts of time with the
activities DeMarco and Lister were hard-pressed to find and most certainly read books – or blogs –
about software engineering.</p>

<p>Before we go any further, I want to stress that raising awareness on apathy is not a call for perfectionism.
Employees should not start feeling responsible for things outside of their control or obsess about
individual factors of their work at the cost of the whole. Caring about results implies making judgment
calls when something is “good enough” and compromises are not a sign of apathy (in fact, apathetic
employees wouldn’t even think about what is good enough but just blindly do what they are told).</p>

<p>I also want to point out that employees do not owe intrinsic motivation to their employer. If anything,
they owe it to themselves, since they not only will become better at their job but also will have a
much better time doing it. Over time, it might even get them that promotion they have always eyed.</p>

<h3 id="causes-of-apathy">Causes of Apathy</h3>
<p>There can be many causes of apathy. A common source can be personal problems like health issues,
relationship troubles, or personal tragedies. We will call this type of apathy personal apathy.
Personal apathy is serious but also individual and should hopefully not affect many employees at the
same time, which reduces the risk for infection.</p>

<p>Apathy can also be caused by the work itself. Let’s call this cultural apathy. Cultural apathy means
that motivated employees slowly get the enthusiasm sucked out of them by the work environment. This is
the worst kind of apathy since it is highly infectious. Unchecked cultural apathy is a surefire way to
hamstring an entire organization.</p>

<p>Cultural apathy is usually caused accidentally. Apathy grows when people feel that their work does not
matter. Whether this impression is correct or not is irrelevant; if employees feel that the higher-ups
do not care about the quality of the product or some other thing that is dear to their hearts, apathy
will soon set in.</p>

<p>The quickest way to cause cultural apathy is by rejecting or suppressing ideas raised by employees. If the
team comes up with some idea on how to improve the product or their way of working, only to get
stonewalled by their boss, motivation will invariably suffer. Once this has happened a couple of times,
weary acceptance will set in and apathy will reign. Sometimes organizations even react hostile to the
suggestion of changing something. If this happens, apathy becomes a defense mechanism to avoid punishment
by the higher-ups, and only the bravest employees will resist it.</p>

<p>Finally, there is wrong job apathy. Some employees have a job that isn’t right for them anymore and
are just keeping it out of convenience or because they are scared to try something new. Naturally, they
are only doing the bare minimum and aren’t interested in long-term success.</p>

<h3 id="leaders--apathy">Leaders &amp; Apathy</h3>
<p>Leaders can also be afflicted by apathy, which is especially dangerous since all eyes are on them. If
they appear disinterested, their subordinates will notice and feel disheartened if they still care about
their work. This makes leader apathy highly infectious.</p>

<p>Development managers are particularly at risk since they are expected to manage their teams, to help
their boss, and to keep up with their management peers. This can easily become overwhelming, and once
they start cutting corners, they can quickly appear apathetic to others.</p>

<h3 id="apathy--the-developer-skill-matrix">Apathy &amp; the Developer Skill Matrix</h3>
<p>Long-term readers of this blog might be wondering how apathy affects the different types of developers
outlined in the <a href="https://thinkingsideways.net/people/developer-skill-matrix.html">developer skill matrix</a>.
Unsurprisingly, stars are almost never apathetic; their high-quality output simply would not be
possible if they were not intrinsically motivated. Apathy might have started to creep in, and they might
be coasting on their previous results, but this is very rare. By contrast, plants are almost certainly
apathetic, especially if they have been in this quadrant for a year or longer without signs of improvement.</p>

<p>Glaciers usually care too much about quality to be apathetic but might have the wrong definition of
success. They obviously do not care about fast results or efficient ways of working, which is a problem
in most software engineering jobs.</p>

<p>Like the stars, volcanoes are almost never apathetic. They are driven to code, even if no one appreciates
their breakneck speed. Indeed, their high drive is what makes volcanoes so dangerous. They want to be
fast but don’t care about quality or maintainability, which prevents long-term success and shows intrinsic
motivation on its own is not enough to achieve excellence.</p>

<h3 id="overcoming-apathy">Overcoming Apathy</h3>
<p>Apathy can only be cured by removing its cause. If you suffer from personal apathy, focus on your
personal life first. Motivation at work will come back once your private affairs have settled down.</p>

<p>For cultural apathy, try fixing small things at work that bother you. It is common that employees try
to solve the big problems – maybe some other team is slowing you down or the Scrum process has some
glaring faults everyone else ignores – which almost always need buy-in from others. These changes
usually take a long time and fail more often than not.</p>

<p>This can be very frustrating; however, it is rare that developers are so disempowered that they cannot
change anything. Focus on what you can improve and do this first; over time you can gain a lot of
ground this way. If you need buy-in from other people, try making it easy for them by only mentioning
the problem when you already have a solution in mind. Avoid complaining about things that you cannot
change or where you don’t have an actionable solution yet. While it can be cathartic to vent, doing
this too often will make people label you as a complainer and ignore what you say.</p>

<p>If the culture of your company is so apathetic and top-down that you cannot change anything, do yourself
a favor and leave. The same is true if you secretly want a different kind of career and suffer from wrong
job apathy; you are doing nobody a favor if you stick to a job you don’t really want.</p>

<p>Finally, refrain from trying to fix the apathy of others. It is unlikely to work and could get you into
serious trouble. You can only cure yourself and try to improve the culture around you. Similarly,
leaders cannot micromanage apathy out of employees since intrinsic motivation by definition cannot
be created by outside factors. They should instead focus on breaking cultural apathy, which is
easier for them than for their subordinates.</p>

<h3 id="conclusion">Conclusion</h3>
<p>Apathy might seem like a natural response to the difficulties of the corporate world, but this is an
illusion. It does not offer a solution to a problem but rather numbness to it, the acceptance of it
as normal, and the removal of any expectation otherwise. This may help in the moment but is devastating
for the long-term success of an individual employee and of the company as a whole.</p>

<p>We all need to take steps to prevent and overcome apathy so we can continue to improve our way of
working and get better results in the future. Leaders have to be especially mindful of it and make
sure they do not accidentally create or perpetuate cultural apathy.</p>

<p>If you liked this blog post, please share it with somebody. You should also have a look at the many
blog posts from the main author. As for me, you can find me on <a href="https://twitter.com/Geisterschleier">Twitter/X</a>.</p>]]></content><author><name></name></author><category term="people" /><summary type="html"><![CDATA[Apathy is a silent killer stalking the software industry. It has tremendous negative effects but is rarely acknowledged as a problem.]]></summary></entry><entry><title type="html">Bring Back Specialization</title><link href="https://thinkingsideways.net/people/specialization.html" rel="alternate" type="text/html" title="Bring Back Specialization" /><published>2025-08-19T08:26:01+00:00</published><updated>2025-08-19T08:26:01+00:00</updated><id>https://thinkingsideways.net/people/specialization</id><content type="html" xml:base="https://thinkingsideways.net/people/specialization.html"><![CDATA[<p>I’ve looked at a lot of software developer job postings recently, and one thing has become very clear to me: modern developers are supposed to be jacks-of-all-trades. For example, it has become quite common to abolish the separation between frontend and backend developers, so instead of just needing to know one of these things, it’s now often expected that we know both. To make things worse, both frontend and backend development have been getting increasingly complicated over the last fifteen years. In the frontend, we’ve seen the emergence of more and more complicated frameworks  and metaframeworks combined with elaborate build processes and involved deployment techniques. In the backend, things are more grounded but also far from ideal. In addition to some backend programming language, backend developers are also expected to work with all kinds of databases, message queues, caching services, API protocols, and authentication methods. This is such an issue that I’ve already seen <a href="https://x.com/SumitM_X/status/1955206298343235723">satirical tweets on the subject</a>.</p>

<p>To make things worse, thanks to the <a href="https://en.wikipedia.org/wiki/DevOps">DevOps</a> movement, operation work was partially offloaded to software engineers. While the idea of a closer cooperation between developers and operators sounds good on paper, in practice it has many problems, as Cory O’Daniel has outlined in his famous <a href="https://www.massdriver.cloud/blogs/devops-is-bullshit">“DevOps is Bullshit” article</a>. For the context of this post, the important thing about DevOps is that it increases the amount of things developers need to know even further. They need to figure out how to deploy to production and how to monitor the current state. This doesn’t sound terribly difficult at first, until we remember that the days of deploying with a simple bash script are long gone. Software systems are much more distributed today, so there is often an elaborated order in which different parts of the system need to be deployed after a change. But wait, isn’t that what tools like <a href="https://en.wikipedia.org/wiki/Kubernetes">Kubernetes</a> are supposed to help us with? Yes, but that also means that we now need to understand Kubernetes and its implications on our application design. That’s no easy task, as even <a href="https://www.theregister.com/2021/02/25/google_kubernetes_autopilot/">Google has admitted</a>.</p>

<p>Things get even more challenging when we consider the cloud. Cloud providers like <a href="https://en.wikipedia.org/wiki/Amazon_Web_Services">AWS</a> offer a dazzling amount of different services. As of 2020, AWS offers more than <a href="https://alleo.tech/2020/01/14/how-many-services-does-aws-actually-have/">200 products and services</a>, and I’m sure the number is even higher by now. We usually need to combine several of these services to get the desired outcome. Understanding what services are best for our use case, how we should combine them, how any future changes might affect us, and, most important of all, how much money this is going to cost us is quite a challenge. And while we figure that out, we also need to design our deployment pipelines to automate everything and describe the infrastructure in code.</p>

<p>And there is one more thing: testing. Manual testing was largely replaced with automated testing. While this is a good thing for routine tests, it’s not great for specialized testing. Being good at testing software and being good at developing it are two very different skill sets. A great software tester might find exotic bugs that we’d never catch with automated tests. Sadly, these roles have largely disappeared. Granted, highly directed testing via test cases was always a waste of time, money, and energy, but just getting rid of testers entirely is a step too far.</p>

<p>All in all, a developer’s job has become a lot broader over the last fifteen years, and I think this is a problem. There is a limit to the amount of knowledge we can realistically acquire. By increasing the number of things we need to know something about, we limit our capacity for deep and specialized knowledge. This problem is made worse by the incredible capabilities of modern software. A tool like Kubernetes or a message broker like <a href="https://kafka.apache.org/">Kafka</a> are very powerful tools that require a lot of time to understand in their entirety. As time is limited, most developers just learn the parts that they need in their daily work. Rather than actually specializing in something, we acquire tiny, specialized pieces of a dozen different things. We end up as jacks-of-all-trades, but also as masters of none.</p>

<p>While this generalist approach can take us very far, it clearly has limits. In some situations, we will require deeper knowledge, knowledge that we most likely won’t have at hand, as we never bothered to learn it. Specialization has value, which is clearly visible in other jobs. For example, when we need heart surgery, we want to go to a specialist instead of just any surgeon. So, why don’t we apply the same logic to software development and let a backend engineer get really good at building backends? The only explanation I have for this trend is that generalist software developers are very convenient for management. With lots of generalists, managers can just exchange developers at will without having to worry about whether they have the right skill set. While I can see the appeal, I highly doubt that this strategy produces great results in the long run.</p>

<p>The bottom line is, if we want excellence, we need specialization. I think we should bring it back into software development. Let people play to their strengths rather than burdening them with a lot of other additional tasks where they will be mediocre at best.</p>

<h3 id="conclusion">Conclusion</h3>
<p>Software developers need to be generalists today, as this is what the market demands. However, this produces subpar results, as specialization is needed for excellence. We should revisit the way we distribute tasks in software development and let people play to their strengths.</p>

<p>If you liked this blog post, please share it with somebody. You can also follow me on <a href="https://twitter.com/fxr256">Twitter/X</a>.</p>]]></content><author><name></name></author><category term="people" /><summary type="html"><![CDATA[Modern developers have to be jacks-of-all-trades. This enforced generalization leads to broad but superficial knowledge. We need to bring back specialization.]]></summary></entry><entry><title type="html">The Three Facets of Software Quality</title><link href="https://thinkingsideways.net/testing/software-quality.html" rel="alternate" type="text/html" title="The Three Facets of Software Quality" /><published>2025-07-23T06:26:01+00:00</published><updated>2025-07-23T06:26:01+00:00</updated><id>https://thinkingsideways.net/testing/software-quality</id><content type="html" xml:base="https://thinkingsideways.net/testing/software-quality.html"><![CDATA[<p>What is software quality? The term is frequently used, but a concrete and helpful definition is not easy to come by. While there is an <a href="https://www.iso.org/standard/78175.html">ISO standard for software quality</a>, it’s very abstract and doesn’t contain any actionable insights. <a href="https://en.wikipedia.org/wiki/Software_quality">Wikipedia</a> has a more interesting definition, as it splits up the term into two distinct parts:</p>
<blockquote>
  <ul>
    <li>Software’s functional quality reflects how well it complies with or conforms to a given design, based on functional requirements or specifications.</li>
    <li>Software structural quality refers to how it meets non-functional requirements that support the delivery of the functional requirements, such as robustness or maintainability.</li>
  </ul>
</blockquote>

<p>This definition is somewhat helpful as it illustrates an important point: software quality is multifaceted. Hence, further details are needed when talking about it. It makes no sense to just state that a piece of software is high or low quality without qualifying what facet we’re talking about. Building on the Wikipedia definition, I think it makes sense to split software quality even further into these three facets:</p>
<ol>
  <li>Functional quality</li>
  <li>Nonfunctional quality</li>
  <li>Structural quality</li>
</ol>

<p>Functional quality measures how well a piece of software fulfills its primary purpose. This includes features as well as <a href="https://thinkingsideways.net/product/design/easy-implementations.html">how easy the software is to implement</a>. Nonfunctional quality includes performance, reliability, and security. Last, structural quality encompasses maintainability as well as extensibility. Out of these three, structural quality is the odd man out, as it’s primarily relevant to the software maker. The end user usually doesn’t care how easily the software maker can change the code. However, the ability to painlessly modify existing software is crucial for keeping up with market demands. Hence, it’s a bad idea to underinvest in structural quality. Failing to keep the structural quality up can result in serious problems. To make things worse, these problems can occur without any warning. For example, the widely used cryptographic library <a href="https://en.wikipedia.org/wiki/OpenSSL">OpenSSL</a> suffered from a <a href="https://en.wikipedia.org/wiki/Heartbleed">very serious security flaw</a> back in 2012. This vulnerability was caused by poor code quality, and OpenSSL’s reputation has been permanently tarnished by it. That means that poor structural quality can also harm the end users even though they don’t care about it under normal circumstances.</p>

<p>Clearly, it’s important to keep quality up. But how exactly do we do that? Again, it depends on what facet of quality we’re talking about. Functional quality is easy to improve, as we just need to add more features and fix any existing bugs. As a result, most software has at least decent functional quality despite the fact that there is a lot of confusion regarding the <a href="https://thinkingsideways.net/testing/testing-vs-quality.html">impact of testing</a>. Nonfunctional quality has many subfacets. Hence, there are many ways to improve it. For example, we might improve it by making our UIs accessible for users with disabilities, by improving the performance in high-load scenarios, or by adding two-factor authentication. The investment volume into certain aspects of nonfunctional quality usually ebbs and flows. For example, investments into accessibility might pick up when we’re attempting to sell our software to the public sector, as it is a required feature in some parts of the world. Last, improving the structural quality of the software can be done, for example, by refactoring the code to make it easier to understand, by improving modularization, and by adding more automated tests.</p>

<p>It’s important to keep in mind that there can be tradeoffs between different quality facets. For example, adding a new feature will improve the software’s functional quality. However, if said feature is sloppily implemented, it will reduce the software’s structural quality, as the software is now harder to maintain. In the end, we may even end up with less quality than before if a code change was very poorly implemented. It’s difficult to keep an eye on this, as all facets of software quality cannot be measured in any reliable way. Hence, we need to rely on our own judgment.</p>

<h3 id="conclusion">Conclusion</h3>
<p>Software quality is multifaceted. It can be split into functional, nonfunctional, and structural quality. Due to its multifaceted nature, we need to be precise when talking about software quality. We should invest in all facets of software quality, and we need to keep in mind that there can be tradeoffs between the different facets.</p>

<p>If you liked this blog post, please share it with somebody. You can also follow me on <a href="https://twitter.com/fxr256">Twitter/X</a>.</p>]]></content><author><name></name></author><category term="testing" /><summary type="html"><![CDATA[Software quality is multifaceted. It can be split into functional, nonfunctional and structural quality. We should invest in all facets.]]></summary></entry><entry><title type="html">The Software Documentation Trifecta</title><link href="https://thinkingsideways.net/processes/documentation.html" rel="alternate" type="text/html" title="The Software Documentation Trifecta" /><published>2025-03-09T06:26:01+00:00</published><updated>2025-03-09T06:26:01+00:00</updated><id>https://thinkingsideways.net/processes/documentation</id><content type="html" xml:base="https://thinkingsideways.net/processes/documentation.html"><![CDATA[<p>Even though most people will probably agree that software documentation is important, the topic of how to do it best is quite underdiscussed. I want to rectify this by offering some suggestions on how to do it.</p>

<p>First, I think it’s helpful to split the topic of software documentation. From my understanding, there are at least three different kinds of software documentation:</p>
<ol>
  <li>Documentation primarily targeting <strong>developers</strong> (e.g., code comments, internal wikis, style guides)</li>
  <li>Documentation primarily targeting <strong>management</strong> (e.g., issue tracker entries, project plans, release schedules)</li>
  <li>Documentation primarily targeting <strong>customers</strong> (e.g., setup guides, detailed feature documentation, best practices)</li>
</ol>

<p>There’s some overlap between these different kinds of documentation. For example, a developer might take a look at the customer documentation to understand how to configure a certain feature. That said, it’s important to keep the primary target group in mind. The documentation needs to match their needs first, and any additional concerns are less important. Let’s discuss the three different kinds in more detail.</p>

<h4 id="developer-documentation">Developer Documentation</h4>
<p>Developer documentation is the most discussed kind of documentation. Usually, these discussions center around whether or not to add code comments. While this topic is out of scope for this blog post, I have addressed it in passing <a href="https://thinkingsideways.net/code/clean-code.html">here</a>. Instead of rehashing the topic, I want to stress that code comments are not enough. Not only does the code itself have to be readable, we also need a place for all the additional information a developer needs. This includes information like how to use the development toolchain, how to get code into production, what style guides to follow, where to find what in the codebase, etc. Basically, everything a new developer needs to know to be productive should be documented somewhere. Preferably, all this information should be in one place. My recommendation is to use some sort of wiki for this and include a link to this wiki in the “readme” files of each GitHub project. This way, every developer should at least know that the central wiki exists and hopefully should then be able to find whatever he needs in it.</p>

<h4 id="management-documentation">Management Documentation</h4>
<p>It’s clear that management also needs certain pieces of information to do their job. For example, it needs answers to questions like:</p>
<ol>
  <li>When will which feature be shipped?</li>
  <li>Which features currently in production absolutely have to be delivered?</li>
  <li>Is anything at risk?</li>
  <li>What is the bottleneck (a.k.a. critical path) for a certain feature?</li>
  <li>Are we on track?</li>
  <li>What kind of changes have we made to certain features over the years?</li>
  <li>Why did we build that feature in the first place? Which customer is relying on it, and for what?</li>
  <li>Are any teams overloaded or underloaded?</li>
</ol>

<p>These needs cover project management concerns, people management concerns, and feature concerns. These differing needs make management documentation very challenging to do right. The hardest part is keeping track of feature changes. For example, imagine we’re building a time management application, and we want to figure out why we added support for multiple overlapping time accounts. We might still remember that this was done a couple of years back but not why. We can probably find the relevant issue tracker entry by looking through the commit history of the changed code. However, it’s far from guaranteed that this will include any information about the motivation. If we’re lucky, we might learn that the feature was introduced to fulfill the special needs of a key customer. That’s helpful but still doesn’t tell us whether the customer is actually using the feature and what problem it’s solving exactly. That kind of information is probably buried in some email account if it exists at all.</p>

<p>The key challenge here is to bind the different information threads together. In other words, we need to decide on a leading knowledge platform where all the information is stored and find a way to bind them to code changes. From my point of view, the only suitable choice for this is our issue tracker, as it maps directly to code changes. In general, I think that issue trackers are great communication tools. I’ve explained this <a href="https://thinkingsideways.net/processes/issue-tracker.html">here</a> in more detail. That means that we need to spend more effort on our issues. More precisely, we need to include at least this information:</p>
<ol>
  <li>What is the motivation for this issue? Who needs it, and for what?</li>
  <li>Is this a change to an existing feature? If yes, then we need to include a link to the last related issue so we can build a chain of changes.</li>
  <li>When was this issue shipped / when do we plan to ship it?</li>
  <li>What’s the priority of this change?</li>
  <li>What team is this assigned to?</li>
  <li>Does it belong to any long-running project? If yes, we need to link to the project itself so we can get the full picture.</li>
</ol>

<p>As we can see, this strategy only works if we get as much information into the issue tracker as possible. We can also link to other places, but the issue tracker has to be the central point that ties everything together. Only then can we link a code change to the bigger picture and get all the information we might need. However, this also means that there will be a lot of information to process. While digging through different lengthy issues is time-consuming, I still think that it’s worthwhile as we can retain a lot of institutional knowledge this way, which otherwise might get lost. In addition to the issues themselves, we also have to construct suitable dashboards to cover the project management and people management concerns. When using this strategy, everybody is using the issue tracker, so the differing needs of engineers, product owners, and managers need to be met.</p>

<p>Whether or not a feature is actually used in production is something we cannot tell from the issue tracker. While getting this information is very difficult in traditional on-premise software, it’s quite possible to figure it out in cloud software. Ideally, we should be able to check this with minimal effort in some kind of monitoring tool.</p>

<h4 id="customer-documentation">Customer Documentation</h4>
<p>Great customer documentation is highly beneficial as it helps to prevent customer issues and makes the software easier to implement, which in turn <a href="https://thinkingsideways.net/product/design/easy-implementations.html">makes it more valuable</a>. Hence, we need to take great care when writing it. The most important thing to keep in mind is to always offer context. It’s not enough to just describe how to configure a feature; we also need to give some explanation on what a feature actually does and why we might want to turn it on. Enterprise software often has very niche features that target certain highly specific scenarios. The customer has to be able to tell from the documentation whether or not he needs a certain feature. It’s also helpful to use cross-references between different topics. For example, when describing how to enable overlapping time accounts in a time management system, it’s a good idea to add a link to the time account section. Without context, the documentation will feel disjointed.</p>

<p>Similar to the other documentation types, we also need a single place to tie all of our customer documentation together. In addition to the general documentation, we might have more specialized ones like descriptions of best practices, lists of important new features, or guides on how to solve common issues. All of this information needs to be gathered in one place so that the customer can actually find it. After all, even the best documentation is useless if it remains unread.</p>

<h3 id="conclusion">Conclusion</h3>
<p>Software documentation targets developers, managers, and customers. These three groups have different needs that need to be considered. However, they have the common need of a central point where they can find all documentation relevant to them.</p>

<p>If you liked this blog post, please share it with somebody. You can also follow me on <a href="https://twitter.com/fxr256">Twitter/X</a>.</p>]]></content><author><name></name></author><category term="processes" /><summary type="html"><![CDATA[Software documentation targets developers, managers and customers. This blog post explains how to craft helpful software documentation for all three groups.]]></summary></entry><entry><title type="html">Software Performance Rarely Matters</title><link href="https://thinkingsideways.net/software/design/performance.html" rel="alternate" type="text/html" title="Software Performance Rarely Matters" /><published>2024-12-23T16:26:01+00:00</published><updated>2024-12-23T16:26:01+00:00</updated><id>https://thinkingsideways.net/software/design/performance</id><content type="html" xml:base="https://thinkingsideways.net/software/design/performance.html"><![CDATA[<p>Arguing about software performance is a highly traditional software developer pastime. On the internet, we can find developers criticizing certain programming languages, frameworks, design paradigms, libraries, etc., for their poor performance. Complaints about the poor performance of current software (e.g., Microsoft Teams, Slack, Jira, ServiceNow, Microsoft Visual Studio, and many others) have also become quite common over the past years. While I understand the frustration and I’m not fond of many current software products as well, I think that this whole debate is fruitless because it misses the point.</p>

<p>First of all, we need to keep in mind that it’s impossible to predict software performance in a vacuum. There are so many moving parts in any current software stack that we have to actually measure the performance to find out which approach is faster. Intuitively guessing about performance is not reliable and can lead us in the wrong direction. This is described in detail in <a href="https://www.goodreads.com/book/show/59095357-the-art-of-writing-efficient-programs">“The Art of Writing Efficient Programs” by Fedor Pikus</a>. Hence, all these performance discussions are pointless. It’s just not possible to state with certainty, for example, that framework X will always be faster than framework Y or that garbage collection is always slow. People who make these kinds of statements are misguided.</p>

<p>More importantly, there is no evidence that high-performance software is desired by end users. Of course, people will claim to prefer fast software similar to how they will claim to prefer secure software. However, this stated preference <a href="https://en.wikipedia.org/wiki/Revealed_preference">isn’t visible in their purchase decisions</a>. There are a lot of very successful slow software products on the market today, and there is very little customer pushback to their poor performance. Microsoft Teams is a great example of a slow (and in my opinion quite terrible) software product that is immensely successful. Granted, a big part of this success is Microsoft’s ability to just bundle it with other products to get it into the market, but it’s still a great success nevertheless. Jira is another great example. It’s the de facto standard for bug tracking with an <a href="https://6sense.com/tech/bug-and-issue-tracking/jira-software-market-share">estimated market share of 86%</a>, even though it’s quite notorious for being slow. If customers actually valued performance highly, there would be a competitor with a “turbo Jira” product taking the market by storm.</p>

<p>This phenomenon is not limited to enterprise software. Even in video games where high-performance programming has a long history and where high frame rates are considered highly important, we don’t see significant customer pushback to poor performance. It’s well known that games are <a href="https://www.pcworld.com/article/2455340/are-modern-pc-games-badly-optimized-or-is-it-just-time-to-upgrade.html">less optimized for best performance</a> today than they were in the past. However, this doesn’t mean that poorly optimized games also sell poorly. For example, “Cyberpunk 2077”, which was so poorly optimized on launch that <a href="https://www.cnbc.com/2020/12/18/sony-pulls-cyberpunk-2077-from-playstation-store-after-backlash.html">it was removed from Sony’s PlayStation store</a>, still sold more than 30 million copies. People might complain about poor performance, but they will still buy the product.</p>

<p>So, what does this all mean? Sadly, it means that spending a lot of effort to create high-performance software doesn’t pay off. While there are some cases where high performance is a hard requirement, for example, in a high-frequency trading software, in general we don’t see a big demand for fast software. People just value different qualities more. As we only have a limited amount of time and money to invest into a piece of software, we probably should focus on different aspects rather than on performance. My recommendation is to build the software in the simplest way possible and then to check whether we have any performance issues. This minimizes complexity and allows us to get things done quickly. It’s an optimistic approach that assumes that we’re unlikely to encounter any serious performance issue and that we will be able to solve them if we do. Nevertheless, it pays to keep performance in mind when designing the application. For example, we should design our UIs in a way that limits the amount of read data. Let’s assume that we’re building a stock broker application. It makes a lot of sense to only display any trades done in the last month by default, as displaying all trades at once could lead to poor performance. If we keep this in mind, we should at least achieve acceptable performance. We’re lucky that today’s technology allows us to get away with an optimistic approach.</p>

<h3 id="conclusion">Conclusion</h3>
<p>If we look at the software market today, we can clearly see that customers don’t buy a product just because it offers better performance than other comparable software. Hence, it’s rational to prioritize software performance less during the development process.</p>

<p>If you liked this blog post, please share it with somebody. You can also follow me on <a href="https://twitter.com/fxr256">Twitter/X</a>.</p>]]></content><author><name></name></author><category term="software" /><category term="design" /><summary type="html"><![CDATA[I think that software performance rarely matters. In this blog post, I'll explain why I think so and what this implies for software design.]]></summary></entry><entry><title type="html">Modularization Can Mitigate People Problems</title><link href="https://thinkingsideways.net/people/people-problems-modularization.html" rel="alternate" type="text/html" title="Modularization Can Mitigate People Problems" /><published>2024-12-11T09:26:01+00:00</published><updated>2024-12-11T09:26:01+00:00</updated><id>https://thinkingsideways.net/people/people-problems-modularization</id><content type="html" xml:base="https://thinkingsideways.net/people/people-problems-modularization.html"><![CDATA[<p><a href="https://thinkingsideways.net/people/people-problems.html">A while ago</a>, I wrote about people problems and explained why process changes cannot fix them. This is still true, and it’s very important to address people problems directly. However, there is one more thing I’d like to add: it’s possible to somewhat mitigate certain people problems by increasing modularization. Note that this <strong>doesn’t</strong> mean that the problems are solved. They are just made less painful. If it’s not possible to actually fix the people problem, it can be a good idea to explore such mitigation options.</p>

<p>Using modularization as a mitigation technique is only an option when the people problem lies within a development team or between development teams. Basically, the idea is to further modularize the code, thereby isolating the disagreeing people from each other. In the context of this post, modularization means adding any kind of additional substructure to the code with the goal of decoupling teams from each other. This can be a traditional method like adding a dedicated package or a software module as well as moving the code into a standalone service. As a sidenote, I think that the popularity of <a href="https://en.wikipedia.org/wiki/Microservices">microservices</a> is at least in part motivated by the desire to isolate oneself from other development teams. This is why some teams desire to move their code into a microservice even though they have no scalability issues.</p>

<p>But how exactly does modularization mitigate a people problem? It mitigates the issue by increasing empowerment. As soon as we have our own module to do as we please, we need to coordinate less. That means that certain conflicts can be avoided completely because a consensus is no longer needed. For example, let’s imagine that we have a long-running conflict between two development teams because the two teams cannot agree on what static code checks should run in the development pipeline. As soon as we give each of the teams its own module, the conflict just vanishes as each team is empowered to do as it pleases. Another example that I have encountered during my work is that two teams share a module, and one team likes to add <a href="https://thinkingsideways.net/testing/integration-tests.html">a lot of brittle integration tests</a>, which makes it more time-consuming and difficult to merge code changes. As the module is shared by both teams, everyone is affected by this even though only one team likes to invest in these integration tests. Naturally, this causes friction. Splitting up the module into two mitigates the issue, as now only the team that actually owns the tests is affected by them.</p>

<p>The examples given above might seem a bit silly to some readers. In the grand scheme of things, these seem like tiny problems that are hardly worth debating. However, these small things are often <a href="https://en.wikipedia.org/wiki/Law_of_triviality">debated with great intensity</a>. Hence, it can cause great resentment if no suitable solution is found. Fortunately, these issues can usually be solved by empowering the teams further, which <a href="https://thinkingsideways.net/processes/subsidiarity.html">leads to better results in general</a>. That said, it’s possible to split up the code too finely. A good indicator for a too fine-grained split is that we make changes in multiple modules for a single feature. Also, modularizing the code based on conflict avoidance can lead to quite awkward splits, especially when the team setup changes. In general, we should only modularize the code if the resulting split makes sense independent of any personal conflicts. This is especially important if we’re using a very distributed architecture like microservices, as adding an additional service has a much higher cost than just adding an additional module.</p>

<p>Last, I want to stress that these kinds of mitigations are only a second-best solution. We should always prefer solving the people problem instead. It can be tempting to just do the modularization instead because it can be less painful, but this is unlikely to produce good results in the long run.</p>

<h3 id="conclusion">Conclusion</h3>
<p>Most hard problems in software development are people problems. In certain cases, we can try to mitigate a people problem by increasing modularization. While this can be helpful, it’s only a second-best solution.</p>

<p>If you liked this blog post, please share it with somebody. You can also follow me on <a href="https://twitter.com/fxr256">Twitter/X</a>.</p>]]></content><author><name></name></author><category term="people" /><summary type="html"><![CDATA[This blog post explains why people problems can be mitigated by modularization. This is important as most difficult problems are people problems.]]></summary></entry><entry><title type="html">In Defense of Object-Oriented Programming</title><link href="https://thinkingsideways.net/software/design/defense-of-oop.html" rel="alternate" type="text/html" title="In Defense of Object-Oriented Programming" /><published>2024-08-28T16:26:01+00:00</published><updated>2024-08-28T16:26:01+00:00</updated><id>https://thinkingsideways.net/software/design/defense-of-oop</id><content type="html" xml:base="https://thinkingsideways.net/software/design/defense-of-oop.html"><![CDATA[<p>It has been fashionable to condemn <a href="https://en.wikipedia.org/wiki/Object-oriented_programming">object-oriented programming (OOP)</a> for a long time. The practice was already <a href="https://kawagner.blogspot.com/2006/08/oop-is-dead.html">proclaimed dead in 2006</a>, and the stream of <a href="https://betterprogramming.pub/object-oriented-programming-the-trillion-dollar-disaster-92a4b666c7c7">long critical articles</a> and <a href="https://x.com/Hasen_Judi/status/1815939219698974951">silly tweets</a> on the subject continues to this day.</p>

<p>I understand that many developers are frustrated with OOP. I’ve criticized <a href="https://thinkingsideways.net/software/design/futile-quest-for-true-oo.html">the practice myself</a>, and I agree that OOP has failed to achieve its goals. However, it’s a mistake to just discard OOP alltogether. When <a href="https://thinkingsideways.net/code/sane-programming.html">done correctly and with a lot of restraint</a>, it still offers some benefits. In this blog post, I want to point out the good things that OOP offers.</p>

<h4 id="defining-oop">Defining OOP</h4>
<p>But what exactly is OOP? This is a surprisingly difficult question to answer. Clearly, it’s about objects, but what is an object exactly? <a href="https://en.wikipedia.org/wiki/Alan_Kay">Alan Kay</a> is considered the inventor of the term, and <a href="http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en">his definition</a> is as follows:</p>
<blockquote>
  <p>I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages (so messaging came at the very beginning – it took a while to see how to do messaging in a programming language efficiently enough to be useful).</p>
</blockquote>

<p>Sadly, this definition isn’t very helpful and also not in line with how OOP is actually done in reality. <a href="https://en.wikipedia.org/wiki/Robert_C._Martin">Robert C. Martin</a> defines OOP like <a href="https://x.com/unclebobmartin/status/1813946286808137787">this</a>:</p>
<blockquote>
  <p>OOP is the partitioning of systems into cohesive units composed of hidden data structures and exposed functions called through a separately defined dispatch table.</p>
</blockquote>

<p>Martin mentions three important points here:</p>
<ol>
  <li>Data and functions (=behavior) are combined in the same units.</li>
  <li>The data is hidden while the functions are exposed.</li>
  <li>The runtime behavior might change depending on the type of parameters passed to a function. The “dispatch table” he mentions is a mechanism for implementing <a href="https://en.wikipedia.org/wiki/Subtyping">polymorphism</a>.</li>
</ol>

<p>This is a lot clearer than Alan Kay’s vision. It’s also important to note that while polymorphism is usually implemented via <a href="https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)">inheritance</a>, this is not the only way to achieve this. For example, <a href="https://en.wikipedia.org/wiki/Bjarne_Stroustrup">Bjarne Stroustrup</a> thinks that it’s possible to <a href="https://www.youtube.com/watch?v=xcpSLRpOMJM">do OOP without inheritance</a>, as you can achieve polymorphism with <a href="https://en.wikipedia.org/wiki/Generic_programming">generic programming</a> instead. Now, we’re still not entirely sure what OOP means, as Martin, Stroustrup, and Kay define the term differently. Hence, I’ll define the term myself. That way, we at least gain clarity in the context of this blog post.</p>

<p>My personal definition of OOP is that OOP is the combination of (mostly hidden) data and behavior in the same unit. That means a unit containing only behavior isn’t object-oriented, and a unit with only data in it isn’t object-oriented either. However, this is fine, as there is no rule that every piece of code in a codebase needs to be object-oriented. Instead, we can mix and match different paradigms as we see fit to achieve the best outcome. I included neither polymorphism nor inheritance in this definition, as I think that these techniques aren’t that important. They can be useful in certain situations, but you can still do OOP without them. I also think that data hiding isn’t essential. While the majority of data will be hidden, some might be exposed. I don’t see why a unit should suddenly lose its “object-oriented” status just because we’ve made one piece of data public instead of private.</p>

<h4 id="reasons-to-use-oop">Reasons to use OOP</h4>
<p>But why should we use OOP in the first place? I think that there are three advantages to using OOP:</p>
<ol>
  <li>It <strong>can</strong> be easier to understand than procedural programming.</li>
  <li>It facilitates the creation of powerful data structures.</li>
  <li>It facilitates writing automated tests.</li>
</ol>

<p>Let’s go through these points one by one. Object-oriented code can be easier to understand as it allows the hiding of unnecessary details. For example, a complex data structure like a thread-safe hash map is easier to use when all its implementation details are hidden. This is easy to achieve with OOP but much harder to do in procedural programming. For example, let’s take a look at <a href="https://web.archive.org/web/20160329102146/http://elliottback.com/wp/hashmap-implementation-in-c/">this hash map implementation</a>, which is done in C. Notice how we have to pass a pointer to the map itself into functions like “hashmap_put”. This is not needed when using OOP. In general, object-oriented data structures are very powerful and offer significant productivity gains. Also, through the use of generics, these complex data structures can also be used in a type-safe manner. This is very hard to achieve in a purely procedural language like C, as we need <a href="https://sglib.sourceforge.net/">to rely on macro commands</a>. Last, using OOP makes it easier to write automated tests as it is easier to replace unwanted parts with mocks. Passing a mock into a constructor is easy; manipulating the linker to achieve the same in a procedural language is much harder. Having a good suite of automated tests is a great way to <a href="https://thinkingsideways.net/testing/reasons-for-no-tests.html">keep productivity up</a> during the development process. Hence, this is a big advantage.</p>

<p>These three advantages are the reason why I consider OOP valuable and usually pick it over procedural programming, with the exception of very small projects. There are other points that sometimes get listed as advantages of OOP, which I don’t agree with. These are:</p>
<ol>
  <li>Increased reuse.</li>
  <li>Greater flexibility to change your architecture.</li>
  <li>The ability to model your code after the real world.</li>
</ol>

<p>OOP has been around for decades, but reuse hasn’t improved. The greater flexibility is mostly an illusion. Sure, we can switch our database implementation if we only interact with a wrapper, but how often do we actually do that? Also, there are a lot of hidden properties in our current architecture that we implicitly rely on. For example, we might discover that our new database is much slower in certain situations than our old one. The database wrapper, therefore, only offers the illusion of flexibility. Last, I don’t believe that modeling your code after the real world is helpful. I’ve written more about this <a href="https://thinkingsideways.net/reviews/ddd-book-review.html">here</a>. Sadly, the three non-advantages were widely hyped during the rise and peak of OOP. This has tarnished the reputation of the practice.</p>

<p>The good news is that it’s easy to reap the benefits of the actual advantages of OOP by <a href="https://thinkingsideways.net/code/sane-programming.html">showing restraint</a>. By avoiding inheritance, polymorphism, and design patterns, we avoid the complexity for which OOP is criticized. We end up with code that is object-oriented where it makes sense and procedural (or functional) where it offers no benefits. In a sense, we end up with the best of all worlds, and this can be very helpful in the <a href="https://www.quora.com/When-is-OOP-better-than-FP-and-vice-versa/answer/Aaron-Christianson-2">battle against complexity</a>.</p>

<h4 id="why-are-so-many-people-mad-about-oop">Why are so many people mad about OOP?</h4>
<p>I think part of the reason why some people are very vocal about hating OOP is that the technique was overhyped for a long time. This led to overblown expectations as well as a dogmatic usage of the paradigm. I’ve written about the <a href="https://thinkingsideways.net/software/design/futile-quest-for-true-oo.html">futile search for true OOP</a> before, and I think that a lot of time was wasted on that endeavor. Sadly, it’s impossible to give a full overview of all the reasons against using OOP here, both because it would take too much space and because I don’t have full knowledge of all the things anybody has ever said against OOP. However, I found some recurring patterns during my research. OOP is ofter critized for:</p>
<ol>
  <li>failing to reduce complexity.</li>
  <li>adding a lot of boilerplate because it adds a lot of indirection.</li>
  <li>encouraging modeling after the real world even though this doesn’t add any benefits.</li>
  <li>scattering logic throughout the codebase.</li>
  <li>encouraging the sharing of mutable state.</li>
</ol>

<p>All of these points are valid. We will encounter these problems if we use OOP dogmatically and without restraint. This is the main problem of OOP: it makes it very easy to create a big mess. It’s easy to get wrong and hard to get right. However, I still believe that it’s beneficial <a href="https://thinkingsideways.net/code/sane-programming.html">when done right</a> and in the right circumstances. We’re doing ourselves a disservice when we condemn OOP entirely.</p>

<h3 id="conclusion">Conclusion</h3>
<p>OOP can be easier to understand, allows the construction of powerful data structures, and facilitates the writing of automated tests. We can avoid its downsides by avoiding inheritance, polymorphism, and design patterns. It is a mistake to condemn OOP in total just because of its past excesses.</p>

<p>If you liked this blog post, please share it with somebody. You can also follow me on <a href="https://twitter.com/fxr256">Twitter/X</a>.</p>]]></content><author><name></name></author><category term="software" /><category term="design" /><summary type="html"><![CDATA[It has become popular to condemn object-Oriented programming. In this blog post, I'll attempt to defend the practice.]]></summary></entry><entry><title type="html">Guest Post: In Defense of Clean Code</title><link href="https://thinkingsideways.net/software/design/defense-of-clean-code.html" rel="alternate" type="text/html" title="Guest Post: In Defense of Clean Code" /><published>2024-08-10T10:26:01+00:00</published><updated>2024-08-10T10:26:01+00:00</updated><id>https://thinkingsideways.net/software/design/defense-of-clean-code</id><content type="html" xml:base="https://thinkingsideways.net/software/design/defense-of-clean-code.html"><![CDATA[<p>It seems to have become very fashionable to attack <a href="https://www.goodreads.com/book/show/3735293-clean-code">Robert C. Martin’s classic book “Clean Code”</a>. Lots of developers
voice their displeasure at the book and the bad practices it supposedly encourages on social media (as an example of
countless others, please see <a href="https://x.com/ryanrwinchester/status/1762180771018686569">this</a> post on Twitter/X) and
very harsh criticism of it can also be found in blog posts and at conferences. One example would be the otherwise very
<a href="https://www.youtube.com/watch?v=CDcP5e7-NOU">thoughtful talk</a> of David Whitney at Copenhagen DevFest, in which
Whitney even encourages listeners to burn their copies of “Clean Code”.</p>

<p>I am by no means a blind follower of Robert C. Martin, or the ideas expressed in “Clean Code”. Indeed, if a new
developer were to ask me today which book he should read, I would probably recommend <a href="https://www.goodreads.com/book/show/39996759-a-philosophy-of-software-design">John Ousterhout’s excellent “A
Philosophy of Software Design”</a> rather than “Clean Code”.</p>

<p>Still, the criticism of “Clean Code” seems overly harsh and strangely focused on one supposed piece of advice in it:
writing lots of small classes. The internet is ripe with developers venting their frustration about the atomized
codebases they are forced to work with, and David Whitney also criticizes “Clean Code” for encouraging needless
abstraction and dogmatism (ironically, one of the book recommendations in his talk is <a href="https://www.goodreads.com/book/show/57345272-code-that-fits-in-your-head">Mark Seemann’s “Code That Fits in Your Head”</a> which I consider not only a massive waste of time but a much better example of dogmatic coding rules).</p>

<p>The thing is, I completely agree with the arguments against tiny classes. It can be incredibly frustrating to start
searching for a certain functionality in a promising-looking class and only finding it after checking six other classes
that don’t even seem related. Indeed, after working with a codebase where no class was bigger than maybe twenty lines –
this limit was rigorously enforced by one developer – I have gained a new understanding of the antipathy some developers
feel for object-oriented programming.</p>

<p>Today, if a malicious genie gave me the choice between working with a 3000-line class or with the same functionality
split into 100 classes with 30 lines of code each, I would probably pick the former. Huge classes are bad for a lot of
reasons, but at the very least it is easy to find the right file, and the search function of your editor will often
quickly locate the relevant section within it. The same cannot be said for a completely atomized codebase where the
pieces are simple, but you can never see the whole picture.</p>

<p>So, how does “Clean Code” fit into this? Did it cause this wave of tiny classes that seems to have swept over the
industry (or at least over social media)? The best way to answer this question is to look at the text itself. This part
is often missing from the discussions both online and offline, and this oversight is one reason why these debates are
frequently unproductive.</p>

<p>We will start with functions. While they are not brought up as often, tiny functions have similar downsides as
tiny classes, and the chapter about functions is written by Robert C. Martin (unlike the one dealing with classes), so
we can hear it from the man himself. All quotes are from my 2012 edition of “Clean Code”. On page 34, Martin writes:</p>

<blockquote>
  <p>The first rule of functions is that they should be small. The second is that they should be smaller than
that. (…)
Every function in this program was just two, or three, or four lines long. Each was transparently obvious.
Each told a
story. And each led you to the next in a compelling order. That’s how short your functions should
be!</p>
</blockquote>

<p>It seems obvious that this advice could motivate programmers to write very short functions (even to a fault), but we
should not forget the qualifications Martin adds to his statement. Having a clear and compelling order with such tiny
functions is not easy, and most codebases consisting of tiny functions probably ignore this point. Still, this section
could reasonably be used to blame “Clean Code” for a developer’s arsenal of miniscule functions. So, what does the book
say about classes? The relevant chapter is written by Jeff Langr and has this to say about the size of classes on page
136:</p>

<blockquote>
  <p>The first rule of classes is that they should be small. The second rule of classes is that they should be smaller than
that. No, we’re not going to repeat the exact same text from the Functions chapter. But as with functions,
our immediate
question is always “How small?”</p>
</blockquote>

<p>Langr then goes on to talk about the <a href="https://en.wikipedia.org/wiki/Single-responsibility_principle">single-responsibility principle (SRP)</a>, cohesion, and other classic object-oriented
programming rules that help limit class size and often result in many small classes. So, at this point, it looks like
the criticism is correct after all, and “Clean Code” can be blamed for at least some of the atomized codebases out
there.</p>

<p>However, this is not the end of the book. When we go to the “Emergence” chapter (also written by Langr), we can find
this section on page 176:</p>

<blockquote>
  <p>Minimal Classes and Methods</p>

  <p>Even concepts as fundamental as elimination of duplication, code expressiveness, and the SRP can be taken too far. In
an
effort to make our classes and methods small, we might create too many tiny classes and methods. So this rule suggest
that we also keep our function and class counts low.</p>

  <p>High class and method counts are sometimes the result of pointless dogmatism. Consider, for example, a coding standard
that insists on creating an interface for each and every class. Or consider developers who insist that fields and
behavior must always be separated into data classes and behavior classes. Such dogma should be resisted and a more
pragmatic approach adopted.</p>
</blockquote>

<p>This perfectly captures the problems created by blind adherence to the earlier rules, and I could not agree more with
Langr’s statement. So, whoever is using “Clean Code” to justify a codebase of five-line classes has either not read the
book at all or skipped the “Emergence” chapter. Indeed, I consider it likely that developers coding this way are
influenced by much older ideas like the SRP and are on a <a href="https://thinkingsideways.net/software/design/futile-quest-for-true-oo.html">quest for true object-oriented
programming</a>. They use “Clean Code” as a fig
leaf for their already existing taste and to deflect criticism of their coding style. After all, it is much harder to
object to the notion of “clean” code than to the object-oriented programming paradigm, which had its detractors ever since its birth.</p>

<p>On the flip side, developers who do not like tiny classes or unnecessary abstractions now think “Clean Code” caused this
coding style. As a result, they often attack the book and are wary of anyone who claims to follow its advice. This is
understandable, however, it is both misinformed and harmful to their cause, as it focuses the discussion on the book
rather than the coding style. So, one might say that this is a big misunderstanding and a symptom of a larger conflict
inside software development.</p>

<p>Still, it does not mean Robert C. Martin, Jeff Langr, and the other authors of “Clean Code” did everything right. They
should have known better than to include the far too broad statements regarding class and function size. While the arguments
against very long classes and functions are valid, going this far in the opposite direction is harmful as well, and
although they added the necessary caveat to balance out their advice, this section is in a different chapter and can be
missed unless the book is read cover to cover. I am convinced Martin et al. never intended to encourage atomized
codebases, but their book made it easy to be misunderstood. This is one reason why I consider “Clean Code” to be largely
superseded by the mentioned “A Philosophy of Software Design”, which takes great care to avoid such mistakes.</p>

<p>Still, “Clean Code” is a classic and raised a lot of important points back in its day. I am glad to have read it in 2012
and think people can still learn from it today, especially when it comes to proper naming of variables and functions. It
certainly does not deserve the vitriol spewed online, especially since it does not even say what its critics claim it
does.</p>

<h2 id="conclusion">Conclusion:</h2>

<p>“Clean Code” is not advocating mindless abstraction, even if some sections of the book can be read this way when taken
out of context. While there are better books for beginners today, the hate against it is largely a sign of a bigger and
more important conflict inside software development: the <a href="https://thinkingsideways.net/software/design/cost-of-abstraction.html">proper use of abstraction</a>. We should talk about this issue
directly instead of debating a book most people taking part in the debate haven’t even read.</p>

<p>If you liked this blog post, please share it with somebody. You should also have a look at the many blog posts from the
main author. As for me, you can find me on <a href="https://twitter.com/Geisterschleier">Twitter/X</a>.</p>]]></content><author><name></name></author><category term="software" /><category term="design" /><summary type="html"><![CDATA[The book classic Clean Code has been viciously attacked recently. While it is not perfect, the main criticism is unfounded]]></summary></entry><entry><title type="html">Are Developers Feature Machines?</title><link href="https://thinkingsideways.net/people/feature-machines.html" rel="alternate" type="text/html" title="Are Developers Feature Machines?" /><published>2024-06-12T07:50:34+00:00</published><updated>2024-06-12T07:50:34+00:00</updated><id>https://thinkingsideways.net/people/feature-machines</id><content type="html" xml:base="https://thinkingsideways.net/people/feature-machines.html"><![CDATA[<p>Recently, I stumbled over a post in X (formerly Twitter) in which <a href="https://en.wikipedia.org/wiki/Erik_Meijer_(computer_scientist)">Erik Meijer</a> claimed that <a href="https://x.com/headinthebox/status/1793357828507513324">the introduction of Agile reduced the developers to user story implementation machines</a>. Here’s the full quote:</p>
<blockquote>
  <p>When I warned developers nearly a decade ago that Agile is a cancer that needs to be eliminated from our industry, many thought I was crazy. But Agile has completely marginalized the role of developers to just mechanically implementing user stories handed to them by the product owner. Now, AI is the savior who will free them from this misery by killing the developer role.</p>
</blockquote>

<p>This got me thinking. I agree with Meijer that quite frequently, developers are just executing the product owner’s wishes. As product owners are primarily interested in features (a.k.a. “user stories”), developers will mostly work on these rather than on more technical improvements like code refactorings. Many developers work for <a href="https://thinkingsideways.net/processes/fake-agile-companies.html">fake agile companies</a> where they are <a href="https://dominikberner.ch/what-are-agile-empowered-teams/">disempowered</a>. That means that they can’t decide which features will be developed in which order. In other words, they don’t control the “what”. In such a setup, the developer’s purpose is just to execute the product owner’s orders and to turn his feature requests into reality.</p>

<p>However, in addition to the “what”, there is a second dimension: the “how”. Many product owners have little technical knowledge, so they might be able to tell the developers what new thingy to build, but they cannot tell them how to build it. Enter the architects. Usually only found in bigger software companies, they understand how the code works (or at least they used to back when they were still doing actual development work). The architects <strong>can</strong> tell the developers how to build a feature, and sometimes they have a very strong preference for how it should be done and will accept no deviation from the master plan.</p>

<p>So, in an extreme case, the product owner and the architects together control both the “what” and the “how”. I have seen this in practice myself. The product owner writes a long document describing a feature and then passes it over to the architects. These then create a new document that describes the planned implementation, including what new classes to add and which fields to add to an existing class. After this is done, the architecture document is passed over to a developer, who will implement the changes. During the implementation, the developer might find edge cases that were missed by the architects. In this case, he has to discuss the issue with them so that a compliant solution can be found and the architecture document can be updated. Sadly, this is not a spook story or some tale out of the eighties. It happened to me back in 2015 at a company that still claims to be agile today and still uses Scrum as its main development model.</p>

<p>In this situation, developers are really just machines, executing the decisions made by other people further up the chain of command. In that sense, I agree with Meijer. However, I don’t think that Agile can be blamed for this (rather dysfunctional) working model. I’d argue that the idea that developers should just execute the given plan is way older. The distinction between “architects” and “implementers” is already mentioned in Fred Brooks’ <a href="https://en.wikipedia.org/wiki/The_Mythical_Man-Month">“The Mythical Man Month”</a> which was published in 1975, where he writes</p>

<blockquote>
  <p>Are not the architects a new aristocracy, an intellectual elite, set up to tell the poor dumb implementers what to do? Has not all the creative work been sequestered for this elite, leaving the implementers as cogs in the machine? (…) As to the aristocracy charge, the answer must be yes and no. 
Yes, in the sense that there must be few architects (…) and the architect sits at the focus of forces which he must ultimately resolve in the user’s interest. If a system is to have conceptual integrity, someone must control the concepts. That is an aristocracy that needs no apology. No, because the setting of external specifications is not more creative work than the designing of implementations. It is just different creative work.</p>
</blockquote>

<p>As we can see, Brooks clearly rejects the idea of an egalitarian development model. So, even more than fifty years ago, way before Agile existed, the “how” was, at least in some companies, not under the developer’s control. OK, so how about the “what”? Before Agile took over, <a href="https://en.wikipedia.org/wiki/Waterfall_model">waterfall planning</a> was the standard development model for software. Here, the “what” was determined by a small group of expert planners at the very beginning of the project. At that point, only a small handful of programmers (if any) were even part of the project staff. Both the scope and the time line were determined in advance. It was a purely top-down approach. In many companies, the only difference Agile has made is that it has reduced the level of upfront planning and replaced the project manager with the product owner. In that sense, developers have always been feature machines. There are (and have always been) exceptions to this, of course. For example, the 1994 video game “Warcraft: Orcs &amp; Humans” <a href="https://warcraft.wiki.gg/wiki/Warcraft:_Orcs_%26_Humans_credits">credits the whole company for the game design</a>, as everyone had a say.</p>

<p>So, where does this leave us? I think Meijer is wrong to blame Agile: as I’ve demonstrated in the above paragraph, developers have just been machines to execute a plan way before Agile existed. However, I think he touched upon another important question: what level of empowerment should we strive for as developers? In a top-down company, we can expect very little say regarding the “what”. The company might use Agile on paper, but that is irrelevant if it doesn’t match the company culture. However, even in such rather grim circumstances, we must at least take control of the “how”. Relying on the architects to define the “how” is not a good idea, as they are way too detached from the actual situation in the metaphorical trenches to come up with great solutions. Instead, we should rely on the <a href="https://thinkingsideways.net/processes/subsidiarity.html">subsidiarity principle</a> to find the best possible solution. Of course, this also means that we will take responsibility for the quality of our work and have to accept the consequences. However, I think that’s something every developer worth his salt will do without hesitating. The downside of this approach is that different developers in different teams will come up with different coding styles and concepts. This might undermine the conceptual integrity of the full product, as Fred Brooks has warned. Nevertheless, I think we should still push for control over the “how” as I think the idea of conceptual integrity by a central committee doesn’t work in practice.</p>

<p>Taking control of the “what” is only possible in an actually empowered “bottom-up” company. These companies do exist, but they are a minority. I think that “bottom-up” companies have a fundamental advantage as they make better use of the subsidiarity principle. It’s important to keep in mind that feature requests are primarily requests to find the solution to a problem. When thinking about it in more detail, you might come up with something completely different from what was originally requested. For example, imagine you’re in charge of a time off application that is used by companies to keep track of the time off taken by their employees. You might get a feature request to allow an export of all vacations of an employee in a certain format. Rather than just building this, it’s a good idea to understand the reason behind the requirement. It might just turn out that the customer actually wants an automatic integration in Outlook and just requested the data export as a work-around. Questioning requirements can expose better solutions. Such a reflection on requirements happens more frequently in “bottom-up” companies where the teams actually own their products. I think it’s a superior way to run a business, but it’s outside our control. We either work for such a company or we don’t.</p>

<p>Last, let me briefly talk about AI and development. I think that <a href="https://en.wikipedia.org/wiki/Large_language_model">large language models</a> are conceptually unsuitable for development work and, hence, am not worried about them. I don’t think that people who want to replace developers with AI actually understand what developers do.</p>

<h3 id="conclusion">Conclusion</h3>
<p>Agile isn’t to blame for reducing developers to feature machines. Developers should always strive to control the “how” and take control of the “what” only if the company culture allows it.</p>

<p>If you liked this blog, please share it with somebody. You can also follow me on <a href="https://twitter.com/fxr256">Twitter/X</a>. And if you want to acquire even more knowledge, then please check out my other posts on this blog.</p>]]></content><author><name></name></author><category term="people" /><summary type="html"><![CDATA[This blog post discusses whether developers are just feature machines and whether the rise of Agile is to blame.]]></summary></entry></feed>