Code quality and output is the most direct measure of a good programmer. How can I improve code quality and output? This starts with software refactoring and review. There are a lot of books out there on refactoring and review, but the code doesn’t improve immediately. It only helps us solve superficial bugs and specification points, but it doesn’t help us find deeper design problems.

From a design point of view, identifying bad code smells can be a great way to reduce technical debt. Technical debt is debt caused by making wrong or sub-optimal design decisions, intentionally or unintentionally. Debt accumulates until the problem can only be solved by a complete redesign of the project, also known as technical bankruptcy. How to solve the problem of technical debt, it is necessary to make clear the important cause of technical debt from the root — the bad taste of design and the lack of understanding of reconfiguration.

The first step is to define software design principles

  • Principle of abstraction: Simplify entities by streamlining and summarizing: Streamlining refers to the removal of unnecessary details, and summarizing refers to identifying and defining important general characteristics.

  • The acyclic dependency principle: relationships between packages cannot form loops.

  • Principle of Non-self-duplication: In detailed design, design entities and code and duplication may manifest as type name duplication and implementation duplication.

  • Principle of encapsulation: Separation of concerns and information hiding are achieved by hiding abstract implementation details and hiding changes.

  • The principle of information hiding: Identify difficult or potentially changing design decisions and create appropriate modules or types to hide those decisions from other modules or types.

  • Rule of Simplicity: Simplicity is an important goal in software system design and the introduction of unnecessary complexity should be avoided.

  • Richter’s substitution principle: All subtypes must provide at least the promised behavior of the supertype and references to each supertype must be replaced with instances of the subtype.

  • Hierarchical interface principle: Organize pairs of abstractions hierarchically by classifying, summarizing, replacing, sorting, and so on.

  • Principle of modularity: Create highly cohesive, low-coupling abstractions through concentration and decomposition.

  • Open closed principle: Types should be open for extension and closed for modification. Specifically, the module should be able to support new requirements without modifying the code.

  • The single responsibility principle: There should never be more than one reason a class needs to be modified. For example, changing a member might affect other unrelated responsibilities of the class, making it difficult to maintain.

  • Change encapsulation principle: An information hiding method is advocated, and it is suggested to encapsulate the concepts that may change. Many design patterns embody this design principle, such as the strategy pattern, the bridge pattern, and the observer pattern.

When we look at code from a design perspective, there are six elements to follow:



With the principles and six elements of design behind us, let’s look at design bad taste.



We will select only one example of each bad taste in this article.

Abstract bad taste

The principle of abstraction advocates simplifying entities through simplification and generalization: simplification refers to the removal of unnecessary details, while generalization refers to identifying and defining important features that pass. Traffic signs are abstract examples for communication, while numerical symbols and programming languages are abstract examples for problem solving.



Lack of abstract

This is a bad taste when you use a series of data or encoded strings instead of creating classes or interfaces

  1. concept
  • One way to apply the principle of abstraction is to create conceptually distinct entities with unique identities. Instead of creating an Abstraction to represent the entity, it used raw data such as a basic data type or encoded string to represent it, violating the principle of Abstraction, which was called the bad Abstraction Missing. Unnecessary abstraction also violates the principle of modularity.
  1. Potential causes
  • No repeated design analysis was done
  • Not refactoring
  • The wrong focus is on subtle performance improvements
  1. The sample
  • The method printStackTrace() in JDK1.0 prints the stack trace as a string to the standard error stream.
  • In clients that need to programmatically access stack trace elements, programming code must be used to retrieve data such as line numbers, and JDK designers will only be able to accommodate this format in later releases because the client is so dependent on this string format.



Refactoring advice: JAVA apis have been improved since Jdk1.4, and the StackTraceElement class is the missing object from the original design.



  1. The alias
  • Primitive type paranoia: This is a bad taste when using primitive types to encode dates and amounts instead of creating classes.
  • Data blob: This is a bad taste in many places when colleagues use a series of data items without creating classes.
  1. Reality to consider
  • Avoid over-design: Sometimes entities are just data elements without any associated behavior. Using classes or interfaces to represent them in this case can lead to over-design.

Encapsulated bad taste

The principle of encapsulation advocates the separation of concerns and information hiding by hiding abstract implementation details and changes. Do you have to know the engine to drive?



Inadequate encapsulation

This bad taste results when one or more members of an abstraction are declared with more access than is actually required. For example, classes that declare fields as public have a bad taste of “inadequate encapsulation.”

  1. concept
  • The principle of encapsulation is to separate the interface from the implementation so that it can be modified independently. This separation of concerns lets clients rely only on abstract interfaces while hiding concrete implementations from them. Modifying the implementation does not affect the client. The underlying inadequacy of the abstract is termed Deficient Encapsulation.
  1. Potential causes
  • For testing purposes
  • Adopt process thinking in object orientation
  • Fast delivery
  1. The sample
  • Java.lang.System. In, out, and err are declared final, but can be assigned to setIn, setOut, and setErr by java.lang. They can be easily used by any code, such as system.out.println ();
  • PrintStream is Java 1.0 and supports only 8-bit ASCII values. Java1.1 supports Unicode PrintWriter. However, because applications can access PrintStream methods directly, You cannot dismiss the PrintStream class at all.



  1. Refactoring advice: Java 1.6 introduced the java.io.Console class, which provides methods for accessing the character-based Console. Reader () and writer() to get the writer and reader objects associated with the Console.

  2. The alias

  • Public properties, methods that can be hidden
  • Unencapsulated classes
  • A class that contains unparameterized methods
  1. Reality to consider
  • Overly loose accessibility in nested or anonymous classes
  • Performance considerations: such as java.lang.system mentioned earlier

Modular bad taste

The principle of modularity advocates the use of concentration and decomposition techniques to create highly cohesive, low-coupling abstractions.



Modular disassembly

This bad taste results when data and methods that should be concentrated in one abstraction are scattered across multiple abstractions. The class is used as a data container without any methods, and the methods of the class are more often called by members of other classes.

  1. Concept An important approach to modularization implementation is “bringing together related data and methods.” If the abstraction contains only data members, and the methods that operate on those data members are in other abstractions, it violates this implementation and smells of “disassembled modularity.” It is called Broken Modularization.

  2. Potential causes

  • Use object-oriented languages with process thinking
  • Not familiar with existing designs
  1. Reconstruction Suggestions For the process design containing a large number of data classes, you can use the reconstruction method to “transform the process design into objects”.

  2. The alias

  • A class that passively stores data
  • Data classes
  • Data records
  • Record the class
  • Data containers
  • Misplaced operation
  • Attachment bond
  • Misplaced control
  1. Reality to consider
  • Automatically generated code
  • Data transfer object
  • Layered bad taste
  • The principle of hierarchy advocates hierarchical organization of abstractions by classifying, merging, replacing, and sorting. Like the 8.7 million living things on earth.



Missing hierarchy

Code snippets that use conditional logic to explicitly manage behavior changes have the bad taste of creating a hierarchical directory and using it to encapsulate those changes

  1. concept
  • Switch statements (or concatenated if-else statements) based on type codes are one of the most well-known design SINS.
  • The use of type codes to deal with behavioral changes indicates a lack of meaningful classification, resulting in a lack of hierarchy in the design. It’s called the Missing Hierarchy.
  1. Potential causes
  • The mistake of using too simple a design
  • Process design thinking
  • Ignoring inheritance is also a design trick
  1. The sample
  • The concatenated if else statement displays the check types AbstractButton, JToolBar, and JTextCompont and calls the method getMargin() under various conditions, creating a situation that may occur elsewhere in the code in the future.



  1. Reconstruction Suggestions
  • If multiple implementations in a condition check invoke the same method, related interfaces can be introduced to abstract the common protocol.
  • If your code contains conditional statements that can be converted to classes, you can use the refactoring technique “Extract hierarchy” to create a class hierarchy where each class represents one of the conditions in the condition check.
  1. The alias
  • Tag class
  • Absence of inheritance
  • Constricted type hierarchy
  • Built-in function
  1. Reality to consider
  • Interacting with the outside world

—————————————————— split line ——————————————————

I’m a black teenager, straight male, micro-service hardcore gamer, love to share, love to make friends, believe in the concept of “practice makes knowledge”, and enjoy tinkering with code

My wechat account: weiweiweiblack (Note: Nuggets)

Wechat official number: Black little micro services, focus on micro service technology sharing, non-technology not gossip!