ITNEXT

ITNEXT is a platform for IT developers & software engineers to share knowledge, connect, collaborate, learn and experience next-gen technologies.

Follow publication

Cracking The Code Smells

Hossein Mousavi
ITNEXT
Published in
13 min readAug 22, 2023

Intro

Poor Naming 📛

// Poor Naming
const x = 42;
const data = ['apple', 'orange', 'banana'];

// Better Naming
const age = 42;
const fruitList = ['apple', 'orange', 'banana'];
// Poor Naming
function doSomething(a, b) {
// ...
}

// Better Naming
function calculateSum(num1, num2) {
// ...
}
// Poor Naming
class HandleData {
// ...
}

// Better Naming
class DataManager {
// ...
}
// Poor Naming
const maxVal = 100;
function calculate_value() {
// ...
}

// Better Naming
const maxValue = 100;
function calculateValue() {
// ...
}
// Poor Naming
const iMaxRequest: number = 100;

// Better Naming
const maxRequest: number = 100;
// Poor Naming
const listOfAcceptedApplicants: Array<Applicant>;

// Better Naming
const acceptedApplicants: Array<Applicant>;
Photo by Austin Kirk on Unsplash

Boolean Blindness 🔍

// Code Smell: Obscure Variable Naming
const isTrue = someCondition;
const hasPermission = canAccessResource;

// Improved: Clear Variable Naming
const isLoggedIn = someCondition;
const userHasAccess = canAccessResource;
// Code Smell: Complex Negations
if (!isNotAuthorized && (isEmployee || isAdmin)) {
// ...
}

// Improved: Simplified Logic
if (isAuthorized && (isEmployee || isAdmin)) {
// ...
}
// Code Smell: Overloaded Boolean Logic
if (isWeekend && (isHoliday || isWeatherGood) && (hasEnoughFuel || isCarElectric)) {
// ...
}

// Improved: Clear Conditions
const isOptimalWeather = isHoliday || isWeatherGood;
const canTravel = hasEnoughFuel || isCarElectric;

if (isWeekend && isOptimalWeather && canTravel) {
// ...
}
// Code Smell: Magic Booleans
if (isAllowed) {
// ...
}

// Improved: Descriptive Naming
const userIsAuthorized = isAllowed;

if (userIsAuthorized) {
// ...
}
// Code Smell: Inconsistent Usage
if (isEnabled) {
// ...
}

// Elsewhere in the code...
if (isActive) {
// ...
}

// Improved: Consistent Usage
if (userIsEnabled) {
// ...
}

// Elsewhere in the code...
if (userIsActive) {
// ...
}
Photo by Oscar Keys on Unsplash

Code Duplication 🖨️

// Code Duplication: Repeated Logic
function calculateTotalPrice(price: number, quantity: number): number {
return price * quantity;
}


function calculateTaxedPrice(price: number, quantity: number): number {
const taxRate = 0.1;
return (price * quantity) + (price * quantity * taxRate);
}
// Improved: Reusable Logic
function calculateTotalPrice(price: number, quantity: number): number {
return price * quantity;
}

function calculateTaxedPrice(price: number, quantity: number): number {
const taxRate = 0.1;
const total = calculateTotalPrice(price, quantity);
return total + (total * taxRate);
}
Photo by Rex Krithiran on Unsplash

Long Method and Function 🕰️

// Long Method Code Smell: Complex Calculation
function calculateTotalPrice(items: Array<Item>): number {
let totalPrice = 0;

for (const item of items) {
totalPrice += item.price * item.quantity;
}

return totalPrice;
}
// Improved: Shorter Method with Helper Functions
function calculateTotalPrice(items: Array<Item>): number {
return items.reduce((total, item) => total + calculateItemTotal(item), 0);
}

function calculateItemTotal(item: Item): number {
return item.price * item.quantity;
}
Photo by Alexis Fauvet on Unsplash

Spaghetti Code 🍝

// Spaghetti Code: Complex Flow
function processCustomerOrder(customer: Customer, products: Array<Product>): boolean {
let orderIsValid = false;

if (customer.status === 'active') {
if (customer.credit > 1000) {
for (const product of products) {
if (product.stock > 0) {
orderIsValid = true;
product.stock--;
} else {
orderIsValid = false;
break;
}
}
} else {
orderIsValid = false;
}
} else {
orderIsValid = false;
}

return orderIsValid;
}
// Improved: Simplified Logic
function processCustomerOrder(customer: Customer, products: Array<Product>): boolean {
if (isCustomerEligible(customer)) {
return tryPlaceOrder(products);
}

return false;
}

function isCustomerEligible(customer: Customer): boolean {
return customer.status === 'active' && customer.credit > 1000;
}

function tryPlaceOrder(products: Array<Product>): boolean {
for (const product of products) {
if (isProductAvailable(product)) {
product.stock--;
} else {
return false;
}
}
return true;
}

function isProductAvailable(product: Product): boolean {
return product.stock > 0;
}
Photo by Homescreenify on Unsplash

Primitive Obsession 🛠️

// Primitive Obsession: Overused Primitive
class Order {
private id: number;
private customerName: string;
private totalAmount: number;

constructor(id: number, customerName: string, totalAmount: number) {
this.id = id;
this.customerName = customerName;
this.totalAmount = totalAmount;
}

// Methods related to orders...
}
// Improved: Specialized Classes
class OrderId {
private value: number;

constructor(value: number) {
this.value = value;
}

// Methods related to order IDs...
}

class CustomerName {
private value: string;

constructor(value: string) {
this.value = value;
}

// Methods related to customer names...
}

class MoneyAmount {
private value: number;

constructor(value: number) {
this.value = value;
}

// Methods related to money amounts...
}

class Order {
private id: OrderId;
private customerName: CustomerName;
private totalAmount: MoneyAmount;

constructor(id: OrderId, customerName: CustomerName, totalAmount: MoneyAmount) {
this.id = id;
this.customerName = customerName;
this.totalAmount = totalAmount;
}

// Methods related to orders...
}
Photo by Clay Banks on Unsplash

Comments and Documentation Code Smells 📝

// Comments and Documentation Code Smells: Over-Commented Code
function calculateTotal(items: Array<Item>): number {
// Loop through items and calculate total
let total = 0;

for (const item of items) {
total += item.price * item.quantity;
}

return total; // Return the calculated total
}
// Improved: Self-Explanatory Code
function calculateTotal(items: Array<Item>): number {
let total = 0;

for (const item of items) {
total += item.price * item.quantity;
}

return total;
}
Photo by Wesley Tingey on Unsplash

Feature Envy 👀

// Feature Envy Code Smell: Overly Interested Method
class ShoppingCart {
private items: Array<Item>= [];

// ...

calculateTotalPrice(): number {
let totalPrice = 0;
for (const item of this.items) {
totalPrice += item.price * item.quantity;
}
return totalPrice;
}

isAffordable(): boolean {
const total = this.calculateTotalPrice();
return total <= 100;
}
}
// Improved: Balanced and Encapsulated Code
class ShoppingCart {
private items: Array<Item> = [];

// ...

calculateTotalPrice(): number {
let totalPrice = 0;
for (const item of this.items) {
totalPrice += item.price * item.quantity;
}
return totalPrice;
}
}

class PriceEvaluator {
private shoppingCart: ShoppingCart;

constructor(cart: ShoppingCart) {
this.shoppingCart = cart;
}

isAffordable(): boolean {
const total = this.shoppingCart.calculateTotalPrice();
return total <= 100;
}
}
Photo by Camila Franco on Unsplash

Data Clumps 🧶

// Data Clumps Code Smell: Scattered Data
function calculateTotal(order: Order): number {
const basePrice = order.items.reduce((total, item) => total + item.price, 0);
const tax = basePrice * 0.1; // 10% tax rate
return basePrice + tax;
}
// Improved: Grouped Data
class Order {
private items: Array<Item>;
private taxRate: number;

constructor(items: Item[], taxRate: number) {
this.items = items;
this.taxRate = taxRate;
}

calculateTotal(): number {
const basePrice = this.items.reduce((total, item) => total + item.price, 0);
const tax = basePrice * this.taxRate;
return basePrice + tax;
}
}
Photo by Héctor J. Rivas on Unsplash

Inappropriate Intimacy 👥

// Inappropriate Intimacy Code Smell: Tight Coupling
class Customer {
private name: string;

// ...

getInvoice(): Invoice {
return new Invoice(this);
}
}

class Invoice {
private customer: Customer;

constructor(customer: Customer) {
this.customer = customer;
}

// ...
}
// Improved: Looser Coupling
class Customer {
private name: string;

// ...

createInvoice(): Invoice {
return new Invoice(this);
}
}

class Invoice {
private customerName: string;

constructor(customer: Customer) {
this.customerName = customer.getName();
}

// ...
}
Photo by Tomas Sobek on Unsplash

Shotgun Surgery 🔫

// Shotgun Surgery Code Smell: Spread-Out Changes
class Account {
// ...

updateBalance(amount: number): void {
this.balance += amount;
this.updateLastTransaction();
this.notifyAccountHolder();
}

updateLastTransaction(): void {
// ...
}

notifyAccountHolder(): void {
// ...
}
}
// Improved: Centralized Change
class Account {
// ...

updateBalance(amount: number): void {
this.balance += amount;
this.processTransaction();
}

processTransaction(): void {
this.updateLastTransaction();
this.notifyAccountHolder();
}

updateLastTransaction(): void {
// ...
}

notifyAccountHolder(): void {
// ...
}
}
Photo by National Cancer Institute on Unsplash

Lazy Class and Dead Code 💤

// Lazy Class Smell: Unnecessary Class
class EmailAddress {
private address: string;

constructor(address: string) {
this.address = address;
}

validate(): boolean {
// Validation logic
}
}

// Dead Code Smell: Unused Function
function calculateDiscount(price: number): number {
// Calculation logic
}

function main() {
const totalPrice = 200;
const discount = calculateDiscount(totalPrice); // Unused calculation
// ...
}

main();
// Improved: Streamlined Code
// EmailAddress class removed

// Unused Function Removed
function main() {
const totalPrice = 200;
// ...
}

main();
Photo by Jordan Whitt on Unsplash

Switch Statements, Cyclomatic Complexity 🌀

// Switch Statements and Cyclomatic Complexity: Complex Control Flow
function getCategoryDiscount(item: Item, user: User): number {
switch (item.category) {
case 'electronics':
if (user.isPremium()) {
return 0.2;
} else {
return 0.1;
}
case 'clothing':
return 0.15;
case 'books':
return 0.05;
default:
return 0;
}
}
// Improved: Simplified Control Flow
class DiscountCalculator {
private item: Item;
private user: User;

constructor(item: Item, user: User) {
this.item = item;
this.user = user;
}

calculateDiscount(): number {
if (this.item.category === 'electronics') {
return this.calculateElectronicsDiscount();
} else if (this.item.category === 'clothing') {
return 0.15;
} else if (this.item.category === 'books') {
return 0.05;
} else {
return 0;
}
}

private calculateElectronicsDiscount(): number {
if (this.user.isPremium()) {
return 0.2;
} else {
return 0.1;
}
}
}
Photo by Lysander Yuen on Unsplash

Large Parameter List 📥

// Large Parameter List Code Smell: Overwhelming Inputs
function createOrder(
product: Product,
quantity: number,
customer: Customer,
address: Address,
paymentMethod: PaymentMethod
) {
// Order creation logic...
}
// Improved: Simplified Inputs
class Order {
constructor(
private product: Product,
private quantity: number,
private customer: Customer,
private address: Address,
private paymentMethod: PaymentMethod
) {
// Order creation logic...
}
}
Photo by Syed Ahmad on Unsplash

Temporary Fields 📦

// Temporary Fields Code Smell: Unnecessary Fields
class ShoppingCart {
private items: Item[] = [];
private tempSubtotal: number = 0; // Temporary field

addItem(item: Item): void {
this.items.push(item);
this.tempSubtotal += item.price;
}

getSubtotal(): number {
return this.tempSubtotal; // Return the temporary field
}
}
// Improved: Streamlined Structure
class ShoppingCart {
private items: Item[] = [];

addItem(item: Item): void {
this.items.push(item);
}

calculateSubtotal(): number {
let subtotal = 0;
for (const item of this.items) {
subtotal += item.price;
}
return subtotal;
}
}
Photo by Adam Winger on Unsplash

Parallel Inheritance Hierarchies 🏗️

// Parallel Inheritance Hierarchies Code Smell: Interdependent Hierarchies
class Employee {
// ...
}

class FullTimeEmployee extends Employee {
// ...
}

class ContractEmployee extends Employee {
// ...
}

class Payment {
// ...
}

class FullTimePayment extends Payment {
// ...
}

class ContractPayment extends Payment {
// ...
}
// Improved: Aligned Hierarchies
class Employee {
// ...
getPayment(): Payment {
// Get payment logic...
}
}

class FullTimeEmployee extends Employee {
// ...
}

class ContractEmployee extends Employee {
// ...
}

class Payment {
// ...
}

class FullTimePayment extends Payment {
// ...
}

class ContractPayment extends Payment {
// ...
}
Photo by Paul Hanaoka on Unsplash

Navigating Code Smells to Improve Your Craft 🌟

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in ITNEXT

ITNEXT is a platform for IT developers & software engineers to share knowledge, connect, collaborate, learn and experience next-gen technologies.

Responses (1)