What is Complexity?
Recently, I finished reading "A Philosophy of Software Design" and in the second chapter, it explores the topic of Software Complexity.
The book "A Philosophy of Software Design" defines complexity practically:
"Complexity is anything related to the structure of a software system that makes it hard to understand and modify."
In other words, complexity can take many forms, and doesn't necessary has anything to do with performance, your code can be performant and still be complex
I'd like to share some key definitions and insights from the book in this article. But first, let's imagine a common situation that probably you’ve already been to…
A Short Horror Story
Let's dive into a horror story many of you have probably experienced or will experience.
It started with a simple CRUD task management app. The code was clean, modular, and easy to maintain. The development team was happy, and the system worked perfectly for initial clients.
Problems began when the sales team sold the system to a large company, claiming it had calendar integration, email notifications, and an amazing report generator. With the sale finalized, these features had to be implemented quickly.
Calendar Integration: The team had to integrate with Google Calendar and Outlook. Different developers implemented the solutions, resulting in inconsistent approaches.
Email Notifications: Email notifications were added next. One developer used a specific library, while another created a custom solution. The mixed approaches made the code confusing.
Report Generator: For the report generator, developers used various technologies: PDFs, Excel exports, and interactive dashboards. The lack of a unified approach made maintenance a nightmare.
Growing Complexity: Each feature was developed in isolation and quickly, leading to dependencies between features. Developers started creating "quick fixes" to make everything work, increasing the system's complexity and coupling.
Software development doesn't happen in a vacuum; various internal and external factors influence it. We've all been, or will be, in a situation like this.
The Beginning of the End
Then the problems began:
- Changes in one part of the system affected other parts unexpectedly.
- Small changes required modifications in many other files, making estimations difficult.
- Month after month, the code became harder to understand, often fixed through trial and error.
- Productivity declined, and everyone dreaded maintenance tasks.
- The inevitable call for "We need to refactor."
- Certain tasks could only be handled by specific developers (classic)
- Over time, the once beautifully written and well-documented software became a train wreck.
Naming the Symptoms
It's clear we now have a complex system.
Now let's "dissect" this complexity to make it easier to identify and mitigate it.
Well, "mitigate" means:
"To make less severe, serious, or painful; to alleviate."
I believe complexity is often inherent in code. Some things are complex by nature. Your role as a developer isn't just to create code that the computer can execute efficiently but also to create code that future developers (including your future self) can work with.
“Controlling complexity is the essence of computer programming.”
— Brian Kernighan
The author of the mentioned book states that complexity typically manifests in three ways, which we will explore here.
Change Amplification
Change amplification occurs when a seemingly simple change requires modifications in many different places.
For example, if the Product Owner requests a "priority" or "completion date" field and your entities are tightly coupled, how many changes would you need to make?
Cognitive Load
Cognitive load refers to the amount of knowledge and time a developer needs to complete a task.
So imagine this scenario: A new developer joined the team, he was assigned to fix a bug in the report generator. To complete this task, the dev needed to:
- Understand the different calendar integrations (Google and Outlook).
- Grasp the distinct approaches to email notifications.
- Navigate through the fragmented code of the report generator, dealing with PDFs, Excel, and dashboards.
- Integrate these diverse technologies and styles to find and fix the bug.
It's the classic "impossible to estimate" scenario, where the task could take one point or eight—better roll a D20 and respond accordingly.
Unknown Unknowns
Unknown unknowns are when you don't know what you don't know.
This is the worst manifestation of complexity because you might alter things you shouldn't, causing everything to break.
Example: A developer modified the email-sending code to add a new notification, unaware that it would affect the report generator, which depended on that function. This caused significant issues for clients, exemplifying the worst form of emergent complexity.
Causes of Complexity
Having seen the horror story and the three main symptoms, let's look at what causes complexity.
1. Dependencies
Dependencies are essential in software and cannot be completely eliminated. They allow different parts of the system to interact and function together. However, dependencies, when not managed properly, can significantly increase complexity.
Definition:
A dependency exists when code cannot be understood or modified in isolation, requiring consideration or modification of related code.
Types of Dependencies:
- Direct: Module A directly relies on Module B.
- Transitive: Module A relies on Module B, which relies on Module C.
- Cyclic: Modules A, B, and C are interdependent in a circular manner.
2. Obscurity
Obscurity occurs when important information is not obvious. This can make the codebase hard to understand, leading to increased cognitive load and the risk of unknown unknowns.
Definition:
Obscurity occurs when important information is not obvious.
Examples of Obscurity:
- Poor Naming: Variables and functions with unclear names.
- Hidden Side Effects: Methods that perform unexpected actions.
- Global State: Overuse of global variables.
- Deep Inheritance: Behavior spread across many levels in class hierarchies.
Remember: Complexity is Incremental
- Complexity is rarely caused by a single "error" or bad decision.
- Complexity builds up "slowly" through bad decisions and dependencies over time.
Because it is incremental, it's easy to think, "just this once, it won't matter." But when accumulated, fixing one or two dependencies alone won't make much difference.
“Everything is a tradeoff in software engineering.”
— I don't remember the author
Conclusion
I could write a lot of rules, strategies, and frameworks that you probably already saw on the internet on how to avoid complexity: SOLID, Design Patterns, YAGNI, KISS, etc.
However, you can unify them all into one guiding principle (as mentioned in "The Pragmatic Programmer."): "Is what I am implementing easy to change?" If the answer is no, then you are probably increasing complexity.
Ensuring your code is easy to change simplifies maintenance, reduces cognitive load on developers, and makes the system more adaptable and less error-prone.
Thank You!
The above is the detailed content of The Never Ending Battle Against Software Complexity. For more information, please follow other related articles on the PHP Chinese website!

JavaScript's applications in the real world include server-side programming, mobile application development and Internet of Things control: 1. Server-side programming is realized through Node.js, suitable for high concurrent request processing. 2. Mobile application development is carried out through ReactNative and supports cross-platform deployment. 3. Used for IoT device control through Johnny-Five library, suitable for hardware interaction.

I built a functional multi-tenant SaaS application (an EdTech app) with your everyday tech tool and you can do the same. First, what’s a multi-tenant SaaS application? Multi-tenant SaaS applications let you serve multiple customers from a sing

This article demonstrates frontend integration with a backend secured by Permit, building a functional EdTech SaaS application using Next.js. The frontend fetches user permissions to control UI visibility and ensures API requests adhere to role-base

JavaScript is the core language of modern web development and is widely used for its diversity and flexibility. 1) Front-end development: build dynamic web pages and single-page applications through DOM operations and modern frameworks (such as React, Vue.js, Angular). 2) Server-side development: Node.js uses a non-blocking I/O model to handle high concurrency and real-time applications. 3) Mobile and desktop application development: cross-platform development is realized through ReactNative and Electron to improve development efficiency.

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

Python is more suitable for data science and machine learning, while JavaScript is more suitable for front-end and full-stack development. 1. Python is known for its concise syntax and rich library ecosystem, and is suitable for data analysis and web development. 2. JavaScript is the core of front-end development. Node.js supports server-side programming and is suitable for full-stack development.

JavaScript does not require installation because it is already built into modern browsers. You just need a text editor and a browser to get started. 1) In the browser environment, run it by embedding the HTML file through tags. 2) In the Node.js environment, after downloading and installing Node.js, run the JavaScript file through the command line.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

Notepad++7.3.1
Easy-to-use and free code editor

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.