Backend Development 8 min read

Why Over‑Engineering and Bad Code Kill Your Project—and How to Fix It

This article reveals how common bad coding practices such as over‑engineering, hidden business logic in utility classes, deep inheritance trees, excessive DTO layers, unnecessary interfaces, and contract‑less microservices degrade team efficiency and project quality, and offers concrete, principle‑driven remedies.

Continuous Delivery 2.0
Continuous Delivery 2.0
Continuous Delivery 2.0
Why Over‑Engineering and Bad Code Kill Your Project—and How to Fix It

Introduction

Having previously written code‑quality evaluation criteria, this piece explains how "bad code" can actually protect your job by highlighting practices that cripple team efficiency and project quality.

Over‑Engineering

Symptoms

Stacking countless abstractions, interfaces, and design patterns for potential future requirements.

Code becomes so complex that even the author can’t understand it, yet proudly claims the architecture is elegant.

Java Example (Bad)

<code>public interface UserPersistenceStrategy {
    void saveUser(User user);
}
public class DefaultUserPersistenceStrategy implements UserPersistenceStrategy {
    public void saveUser(User user) {
        // 保存逻辑
    }
}
public class UserManager {
    private UserPersistenceStrategy strategy;
    public UserManager(UserPersistenceStrategy strategy) {
        this.strategy = strategy;
    }
    public void save(User user) {
        strategy.saveUser(user);
    }
}
</code>

Problem

The complexity is unnecessary for simply persisting a user; the requirements are not volatile, and the code wastes maintenance effort.

Correct Practice

Apply the

YAGNI

(You Aren’t Gonna Need It) principle: design only for the current real needs and avoid premature complexity.

Core Logic Hidden in Utility Classes

Symptoms

Proliferation of

Utils

and

Helper

classes that hide essential business logic behind static methods.

The project becomes a tangled soup where no one knows what each part does.

Java Example (Bad)

<code>public class UserUtils {
    public static boolean isVip(User user) {
        return user.getPoints() > 1000;
    }
}
public class OrderService {
    public void createOrder(User user) {
        if (UserUtils.isVip(user)) {
            // 走VIP流程
        }
    }
}
</code>

Problem

Business logic such as VIP determination is buried in utility classes, making it hard to read and maintain.

Correct Practice

Place business logic in the domain model or the service layer , not in generic utility classes.

Abusing Inheritance and Deep Inheritance Trees

Symptoms

A chain of

Manager

classes inheriting from

BaseManager

, which in turn inherits from

AbstractBaseManager

, etc.

Changing a parent class breaks all subclasses.

Java Example (Bad)

<code>public class AbstractUserManager {
    protected void connect() { /* 连接DB */ }
}
public class BaseUserManager extends AbstractUserManager {
    protected void authenticate() { /* 鉴权 */ }
}
public class PremiumUserManager extends BaseUserManager {
    public void premiumFeatures() {
        connect();
        authenticate();
        // 高级功能
    }
}
</code>

Problem

Deep inheritance makes understanding the code extremely difficult.

Reuse is misaligned:

PremiumUserManager

is forced to inherit low‑level details just to extend functionality.

Correct Practice

Prefer

Composition

over

Inheritance

; "has‑a" relationships are usually more flexible than "is‑a".

DTO/Entity/VO/Form Layering Overkill

Symptoms

A single user object is converted back and forth among DTO, Entity, Form, VO, BO multiple times.

Each class contains 99% identical fields, differing only in name.

Java Example (Bad)

<code>public class UserDTO {
    private String name;
    private int age;
}
public class UserEntity {
    private String name;
    private int age;
}
// 然后各种Mapper工具来回copy...
</code>

Problem

Excessive layering harms performance and development efficiency.

When there is no clear business boundary, hard layering becomes a burden.

Correct Practice

Design objects according to upstream/downstream system boundaries ; introduce

DTO

or

VO

only when genuine cross‑layer or cross‑system isolation is required.

Fake Interface Programming

Symptoms

Every class forcibly implements an interface that has only one implementation.

"Interface for the sake of an interface" adds unnecessary duplicate code.

Java Example (Bad)

<code>public interface UserService {
    void createUser();
}
public class UserServiceImpl implements UserService {
    public void createUser() {
        // 逻辑
    }
}
</code>

Problem

Unnecessary abstraction inflates code volume and raises comprehension cost.

Correct Practice

Interfaces exist for change. If there is no need for multiple implementations, use a concrete class directly and extract an interface only when future variation is anticipated.

Contract‑less Microservices

Symptoms

Microservice API design is chaotic, lacking a proper

API

specification and versioning.

Parameters change arbitrarily, and return values gain fields without notice.

Java Example (Bad)

<code>@PostMapping("/user")
public Map<String, Object> createUser(@RequestBody Map<String, Object> body) {
    // 用 `Map` 接参数,返回也是 `Map`
}
</code>

Problem

No type constraints; callers have no guidance.

API documentation becomes meaningless.

Correct Practice

Use strictly defined Request/Response objects together with

Swagger

/

OpenAPI

; every endpoint must have a clear contract.

One‑Sentence Summary

In large projects, the challenge isn’t whether you can write code, but whether others can quickly understand it, maintain it easily, and keep the system extensible.

Bad code ≠ only harms yourself. Bad code is a toxin that drags down the entire project and team.
javaBackend Developmentcode qualitySoftware Designanti-patterns
Continuous Delivery 2.0
Written by

Continuous Delivery 2.0

Tech and case studies on organizational management, team management, and engineering efficiency

0 followers
Reader feedback

How this landed with the community

login 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.