Why High-Quality Code Matters: Principles, Bad Smells, and Refactoring Techniques

This article explains why maintainable, robust, and testable code is essential for front‑end development, shares insights from renowned programmers, defines key quality metrics, outlines SOLID and KISS design principles, identifies common code smells, and demonstrates practical refactoring patterns with real JavaScript examples.

Alipay Experience Technology
Alipay Experience Technology
Alipay Experience Technology
Why High-Quality Code Matters: Principles, Bad Smells, and Refactoring Techniques

Why Do We Need High-Quality Code?

Have you ever spent a long time reading source code just to fix a simple feature?

Have you seen a front‑end page go white because an exception wasn’t handled?

Have you needed to refactor a large codebase without any test cases?

These scenarios correspond to the code‑quality indicators of maintainability , robustness and testability . Code quality therefore directly affects software delivery quality.

How Renowned Programmers View High‑Quality Code

Bjarne Stroustrup

I like elegant and efficient code; the logic should be straightforward so defects are hard to hide, dependencies should be minimal, error handling should follow a layered strategy, and performance should be optimal to avoid reckless optimisations.

Grady Booch

Clean code is simple and direct, like beautiful prose. It never hides the designer’s intent and is filled with clear abstractions and straightforward control statements.

Ward Cunningham

If every routine feels intuitive, the code is clean. When the language seems crafted for the problem, the code is beautiful.

Code‑Quality Metrics

Maintainability

Maintainability measures how easy it is to repair and improve a system. Repairability is the ability to recover from failures, while improveability is the ability to add new features.

Readability – Robert Gunning’s Formula

Sentence Structure

Shorter sentences increase readability.

Fog index: the more abstract and difficult the words, the lower the readability.

Human‑interest content improves readability.

These principles, originally for news, also apply to code readability.

Self‑Descriptive Naming

Bad example: let d; // time elapsed in days Improved example:

let elapsedTimeInDays;
let daysSinceCreation;

Avoid Misleading Names

Ensure type accuracy (e.g., a hash table should not be named with a List suffix).

Avoid overly similar names such as ControllerForEfficientHandlingOfStrings vs ControllerForEfficientStorageOfStrings.

Do not differentiate meaninglessly (e.g., getActiveAccount() vs getActiveAccountInfo()).

Maintain semantic consistency across classes.

// Do not use wrong type naming
const accountList = {};
// Do not use singular form for arrays
const account = [];

Extensibility & Reusability

Good design allows new functionality to be inserted without over‑engineering the code.

Fine‑grained encapsulation and the Single‑Responsibility and Open‑Closed principles are essential.

Robustness (Resilience)

Robustness is the ability of software to survive erroneous input, disk failures, network overloads, or attacks without crashing.

Stability

Stability is closely tied to boundary handling and exception handling.

Defensive Programming

Defensive programming ensures that unexpected usage does not damage functionality.

Use good coding style and reasonable design.

Think carefully before writing each line; anticipate possible errors.

Never trust anyone , including user input and backend responses.

Clarity is more important than clever brevity.

Example of unsafe optional chaining:

// {} is non‑null but lacks sort method
(result?.response?.data || []).sort

Safer conversion using lodash:

toArray(result?.response?.data).sort

Exception Handling

Front‑end exception handling should keep the page functional and limit the impact scope.

Wrap potentially failing code in try‑catch.

Use ErrorBoundary to show a fallback UI instead of a white screen.

Guard variable access, e.g., s?.length instead of s.length.

Performance

General Optimisation

Common techniques: space‑for‑time trade‑off, parallelism, reducing computation.

// Reduce double loop to O(1) lookup
newFields.forEach((field, index) => {
  const matchCol = newCols.find(col => col.search !== false && col.dataIndex === field.dataIndex);
});

// Optimised version
const colMap = newCols.reduce((a, c) => {
  if (c.search !== false) a[c.dataIndex] = c;
  return a;
}, {});
newFields.forEach((field, index) => {
  const matchCol = colMap[field.dataIndex];
});

JavaScript‑Specific Optimisation

Benchmarking Date.now() vs +new Date() shows a ~56% speed difference on Chrome 101.

Front‑End Optimisation

Minimise component re‑renders, especially for expensive components.

import { useState } from "react";

export default function App() {
  let [color, setColor] = useState("red");
  return (
    <div>
      <input value={color} onChange={e => setColor(e.target.value)} />
      <p style={{ color }}>{"Hello, world!"}</p>
      <ExpensiveTree />
    </div>
  );
}

function ExpensiveTree() {
  let now = performance.now();
  while (performance.now() - now < 100) {}
  return <p>I am a very slow component tree.</p>;
}

By extracting the expensive component into a separate Form component, colour changes no longer trigger its re‑render.

export default function App() {
  return (
    <>
      <Form />
      <ExpensiveTree />
    </>
  );
}

function Form() {
  let [color, setColor] = useState("red");
  return (
    <>
      <input value={color} onChange={e => setColor(e.target.value)} />
      <p style={{ color }}>{"Hello, world!"}</p>
    </>
  );
}

Testability & Completeness

Testing Pyramid & Unit Tests

The pyramid (unit, integration, component, E2E, exploratory) shows that most effort should be spent on unit tests.

The internal "AIR" principle defines a good unit test:

A : Automatic – fully automated and non‑interactive.

I : Independent – tests must not depend on each other.

R : Repeatable – can run on every CI build.

describe('province', function() {
  let asia;
  beforeEach(function() {
    asia = new Province(sampleProvinceData());
  });
  it('shortfall', function() { expect(asia.shortfall).equal(5); });
  it('profit', function() { expect(asia.profit).equal(230); });
});

Completeness

Tests should cover functional, boundary, and negative cases.

Design Principles

SOLID

Single‑Responsibility Principle (SRP)

Each module should have only one responsibility.

class Modem {
  dial(pno) {}
  hangup() {}
  send(s) {}
  recv() {}
}

Refactored into two classes:

class Connection {
  dial(pno) {}
  hangup() {}
}

class DataChannel {
  send(s) {}
  recv() {}
}

class Modem extends Connection, DataChannel {}

Open‑Closed Principle (OCP)

Modules should be open for extension but closed for modification.

function drawAllShapes(list) {
  for (const item of list) {
    switch (item.type) {
      case ShapeType.circle: return drawCircle(item);
      case ShapeType.square: drawSquare(item);
    }
  }
}

Refactored using polymorphism and hooks:

class Circle { draw() {} }
class Square { draw() {} }
function drawAllShapes(list, hook) {
  list = hook?.beforeDraw?.(list);
  for (const item of list) item.draw();
  list = hook?.afterDraw?.(list);
}

Liskov Substitution Principle (LSP)

Subclasses must be replaceable for their base class.

class Rectangle {
  setWidth(w) { this._w = w; }
  setHeight(h) { this._h = h; }
  getWidth() { return this._w; }
  getHeight() { return this._h; }
}

class Square extends Rectangle {
  setWidth(w) { super.setWidth(w); super.setHeight(w); }
  setHeight(h) { super.setWidth(h); super.setHeight(h); }
}

Dependency Inversion Principle (DIP)

High‑level modules should not depend on low‑level modules; both should depend on abstractions.

class Button {
  private device: SwitchableDevice;
  private status = false;
  constructor(device: SwitchableDevice) { this.device = device; }
  poll() {
    this.status = !this.status;
    const method = this.status ? 'turnOn' : 'turnOff';
    this.device[method]();
  }
}

Interface Segregation Principle (ISP)

Split non‑cohesive interfaces into multiple focused ones.

interface IOrder { apply(); approve(); end(); }
interface IProductOrder extends IOrder { changeSupplier(); }
interface ISaleOrder extends IOrder { changeShop(); }
interface IProductSaleOrder extends IProductOrder, ISaleOrder { bindSupplierWithShop(); }

KISS

Keep it Simple and Stupid – simple, clear designs improve maintainability and testability.

Common Code Smells

Coding Smells

Mysterious Naming

Good names convey meaning without comments.

Duplicate Code & Data Clumps

Repeated code and grouped data make maintenance painful.

Long Functions / Parameter Lists / Classes

Long code is hard to understand and test.

Dead Code

Commented‑out or unused code should be removed.

Design Smells

Scatter‑shot Changes & Shotgun Modifications

Adding a feature requires touching many unrelated files, violating OCP.

Over‑Generalisation

Prematurely adding hooks for imagined future needs creates complexity.

Insider Trading

Data exchange logic scattered across modules should be centralised.

Attachment Complex

Functions that heavily interact with another module belong there.

Excessive Delegation

When half the methods simply forward to another class, remove the middleman.

Refactoring Bad‑Smell Code

Extract Function

function printOwing(invoice) {
  let outstanding = 0;
  console.log("***********************");
  console.log("**** Customer Owes ****");
  console.log("***********************");
  for (const o of invoice.orders) { outstanding += o.amount; }
  const today = Clock.today;
  invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);
  console.log(`name: ${invoice.customer}`);
  console.log(`amount: ${outstanding}`);
  console.log(`due: ${invoice.dueDate.toLocaleDateString()}`);
}

After refactoring:

function printBanner() {
  console.log("***********************");
  console.log("**** Customer Owes ****");
  console.log("***********************");
}
function printDetails(invoice, outstanding) {
  console.log(`name: ${invoice.customer}`);
  console.log(`amount: ${outstanding}`);
  console.log(`due: ${invoice.dueDate.toLocaleDateString()}`);
}
function printOwing(invoice) {
  let outstanding = 0;
  printBanner();
  for (const o of invoice.orders) outstanding += o.amount;
  const today = Clock.today;
  invoice.dueDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);
  printDetails(invoice, outstanding);
}

Extract Variable

function calc(order) {
  return order.quantity * order.itemPrice -
    Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +
    Math.min(order.quantity * order.itemPrice * 0.1, 100);
}

Refactored:

function getQuantityDiscount(order) {
  return Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;
}
function calc(order) {
  const basePrice = order.quantity * order.itemPrice;
  const quantityDiscount = getQuantityDiscount(order);
  const shipping = Math.min(basePrice * 0.1, 100);
  return basePrice - quantityDiscount + shipping;
}

Extract Class

class Person {
  get officeAreaCode() { return this._officeAreaCode; }
  get officeNumber() { return this._officeNumber; }
}

After extracting TelephoneNumber:

class TelephoneNumber {
  get areaCode() { return this._areaCode; }
  get number() { return this._number; }
}
class Person {
  get officeAreaCode() { return this._telephoneNumber.areaCode; }
  get officeNumber() { return this._telephoneNumber.number; }
}

Split Loop

let averageAge = 0;
let totalSalary = 0;
for (const p of people) {
  averageAge += p.age;
  totalSalary += p.salary;
}
averageAge = averageAge / people.length;

Refactored into two separate loops for clarity.

Encapsulate Variable

let defaultOwner = { firstName: "Martin", lastName: "Fowler" };

Encapsulated via getter/setter:

let defaultOwnerData = { firstName: "Martin", lastName: "Fowler" };
export function defaultOwner() { return defaultOwnerData; }
export function setDefaultOwner(arg) { defaultOwnerData = arg; }

Introduce Parameter Object

function amountInvoiced(startDate, endDate) { ... }
function amountReceived(startDate, endDate) { ... }

Combined into:

function amountInvoiced(aDateRange) { ... }
function amountReceived(aDateRange) { ... }

Simplify Conditional Logic

Replace Algorithm

function foundPerson(people) {
  for (let i = 0; i < people.length; i++) {
    if (people[i] === "Don") return "Don";
    if (people[i] === "John") return "John";
    if (people[i] === "Kent") return "Kent";
  }
  return "";
}

Refactored:

function foundPerson(people) {
  const candidates = ["Don", "John", "Kent"];
  return people.find(p => candidates.includes(p)) || '';
}

Guard Clauses

function getPayAmount() {
  if (isDead) return deadAmount();
  if (isSeparated) return separatedAmount();
  if (isRetired) return retiredAmount();
  return normalPayAmount();
}

Polymorphism over Switch

class EuropeanSwallow { get plumage() { return "average"; } }
class AfricanSwallow { get plumage() { return this.numberOfCoconuts > 2 ? "tired" : "average"; } }
class NorwegianBlueParrot { get plumage() { return this.voltage > 100 ? "scorched" : "beautiful"; } }

Conclusion

Must‑Do

Never trust anyone: validate all user input and backend responses.

Ensure variables used in the view cannot cause exceptions.

Write unit tests covering functional, boundary, and negative cases.

Use meaningful, consistent naming; avoid misleading names.

Avoid duplicate code and dead code.

Avoid overly long parameter lists, functions, or classes.

Recommendations

Follow the Single‑Responsibility Principle.

Apply the Open‑Closed Principle.

Eliminate insider‑trading style data exchanges.

Remove attachment complex relationships.

Resist over‑generalising for imagined future needs.

Encapsulate exported literals.

Further Reading

《代码整洁之道》 https://book.douban.com/subject/4199741/

《重构(第 2 版)》 https://book.douban.com/subject/30468597/

《编写可读代码的艺术》 https://book.douban.com/subject/10797189/

《React 性能优化》 https://juejin.cn/post/6935584878071119885

《敏捷软件开发 : 原则、模式与实践》 https://book.douban.com/subject/1140457/

《阿里巴巴 Java 开发手册》 https://kangroo.gitee.io/ajcg/#/naming-style

《naming‑cheatsheet》 https://github.com/kettanaito/naming-cheatsheet

software engineeringrefactoringDesign PrinciplesSOLIDKISS
Alipay Experience Technology
Written by

Alipay Experience Technology

Exploring ultimate user experience and best engineering practices

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.