Fundamentals 20 min read

Why Software Complexity Grows: From Tactical Tornadoes to Strategic Design

This article explores the nature of software complexity, contrasting tactical programming shortcuts with strategic architectural design, explains McCabe cyclomatic complexity and Ousterhout's perception, and offers practical insights and code examples to help engineers manage and reduce complexity in their systems.

Alibaba Terminal Technology
Alibaba Terminal Technology
Alibaba Terminal Technology
Why Software Complexity Grows: From Tactical Tornadoes to Strategic Design

Preface

A doctor and a civil engineer argue about the oldest profession, and a software engineer humorously asks who created the chaos they work in.

What Is Complexity

Complexity is defined both rationally (McCabe’s cyclomatic complexity) and intuitively (John Ousterhout’s perception). McCabe introduced cyclomatic complexity in 1976 to measure software’s structural complexity and maintenance cost.

Complexity is anything that makes software hard to understand or modify.

Forms of Complexity

Change Amplification

Change amplification: a seemingly simple change requires code modifications in many different places.

Typical example: copy‑paste code that forces changes across multiple modules.

/**
 * 销售捡入客户
 */
public void pick(String salesId, String customerId) {
  long customerCnt = customerDao.findCustomerCount(salesId);
  long capacity = capacityDao.findSalesCapacity(salesId);
  if(customerCnt >= capacity) {
    throw new BizException("capacity over limit");
  }
  // ...
}

Cognitive Load

Cognitive load: how much a developer needs to know in order to complete a task.

Complex systems increase the knowledge required, making short‑term gains costly in the long run.

Unknown Unknowns

Unknown unknowns: it is not obvious which pieces of code must be modified to complete a task.

When maintaining legacy code, developers often cannot predict the impact of a change.

Why Complexity Arises

Short‑term shortcuts without proper refactoring.

Lack of craftsmanship, ignoring dirty code.

Insufficient technical ability to handle complex systems.

Missing handover, making maintenance impossible.

Tactical Programming

John Ousterhout calls fast, short‑term solutions “tactical programming”. Its traits are:

It is the fastest solution at the moment.

It avoids spending time on optimal design.

Each task introduces additional complexity.

Refactoring slows down current work, so speed is prioritized.

Tactical Tornado

An extreme form of tactical programming that sacrifices long‑term health for immediate delivery. Characteristics:

Produces code at a frantic pace.

Leaves destructive traces for others to clean up.

Highly “competitive” and unsustainable.

Strategic Programming

In contrast, strategic programming focuses on long‑term value, aiming for clean design that supports future extensions. Its traits are:

Work code alone is insufficient.

Introducing unnecessary complexity is unacceptable.

Continuously make small improvements to system design.

Invest 10‑20% of effort in good design.

System Dilemmas and Evolution

Software maintenance, evolution, and preservation are distinct: fixing bugs, adapting to new requirements, and keeping decaying systems alive respectively. Most effort is spent on preservation, which is costly and unsustainable.

Architectural Myths

Good Code Is Self‑Explanatory

Comments do not make up for bad code.

Martin Fowler’s claim that good code needs no comments is a myth. Proper naming, design documentation, and comments are essential, especially in complex domains.

/**
 * 批量查询客户信息
 */
public List<CustomerVO> queryCustomerList(){
  UserInfo userInfo = context.getLoginContext().getUserInfo();
  if(userInfo == null || StringUtils.isBlank(userInfo.getUserId())){
    return Collections.emptyList();
  }
  // ... business logic ...
  return customerSearchVOList;
}

Pursuing Elegance

While elegant code is a noble goal, over‑optimizing for elegance can lead to unnecessary refactoring. Architecture’s ultimate aim, per Robert C. Martin, is to minimize human effort required to build and maintain the system.

Conclusion

Software engineering’s toughest challenge is managing inherent complexity without over‑engineering or under‑engineering. Balancing short‑term speed with long‑term maintainability remains a lifelong lesson for developers.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

architecturesoftware designcomplexitystrategic programmingtactical programming
Alibaba Terminal Technology
Written by

Alibaba Terminal Technology

Official public account of Alibaba Terminal

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.