Code Smell Bloater’s Exercise
Code Smell Bloater’s Exercise
Code smells are indicators of poor code design that can lead to potential issues such as reduced maintainability, increased complexity, and decreased scalability. Blotter’s Exercise, a fictional scenario, serves as an example to identify and refactor code smells in a .NET Core project.
In this guide, we will delve into the Blotter’s Exercise source code, identify various code smells, and step-by-step refactor the code to improve its quality and maintainability.
using System;
using System.Collections.Generic;
namespace BlottersExercise
{
public class TaskManager
{
private List<Task> tasks;
public TaskManager()
{
tasks = new List<Task>();
}
public void AddTask(Task task)
{
tasks.Add(task);
}
public void UpdateTask(int index, Task updatedTask)
{
if (index >= 0 && index < tasks.Count)
{
tasks[index] = updatedTask;
}
else
{
Console.WriteLine("Invalid index.");
}
}
public void DeleteTask(int index)
{
if (index >= 0 && index < tasks.Count)
{
tasks.RemoveAt(index);
}
else
{
Console.WriteLine("Invalid index.");
}
}
public void PrintTasks()
{
foreach (var task in tasks)
{
Console.WriteLine(task.ToString());
}
}
}
public class Task
{
public string Description { get; set; }
public bool IsCompleted { get; set; }
public override string ToString()
{
return $"Description: {Description}, Completed: {IsCompleted}";
}
}
class Program
{
static void Main(string[] args)
{
TaskManager taskManager = new TaskManager();
taskManager.AddTask(new Task { Description = "Write blog post", IsCompleted = false });
taskManager.AddTask(new Task { Description = "Refactor source code", IsCompleted = false });
taskManager.AddTask(new Task { Description = "Run unit tests", IsCompleted = true });
taskManager.PrintTasks();
}
}
}
Identify some common code smells present in this code:
- Duplicated Code: The validation logic in
UpdateTask
andDeleteTask
methods is duplicated. - Long Methods: The
PrintTasks
method contains logic for printing tasks and is relatively long. - Primitive Obsession: The
Task
class uses primitive data types (string
andbool
) directly for task properties, which can lead to limited functionality and maintainability. - Inadequate Error Handling: Error handling in the
UpdateTask
andDeleteTask
methods is insufficient. - Violation of Single Responsibility Principle (SRP): The
TaskManager
class handles both managing tasks and printing them, violating SRP.
Let’s refactor this code to address these code smells:
using System;
using System.Collections.Generic;
namespace BlottersExercise
{
public class TaskManager
{
private List<Task> tasks;
public TaskManager()
{
tasks = new List<Task>();
}
public void AddTask(Task task)
{
tasks.Add(task);
}
public void UpdateTask(int index, Task updatedTask)
{
if (IsValidIndex(index))
{
tasks[index] = updatedTask;
}
else
{
Console.WriteLine("Invalid index.");
}
}
public void DeleteTask(int index)
{
if (IsValidIndex(index))
{
tasks.RemoveAt(index);
}
else
{
Console.WriteLine("Invalid index.");
}
}
private bool IsValidIndex(int index)
{
return index >= 0 && index < tasks.Count;
}
public void PrintTasks()
{
foreach (var task in tasks)
{
Console.WriteLine(task.ToString());
}
}
}
public class Task
{
public string Description { get; set; }
public bool IsCompleted { get; set; }
public override string ToString()
{
return $"Description: {Description}, Completed: {IsCompleted}";
}
}
class Program
{
static void Main(string[] args)
{
TaskManager taskManager = new TaskManager();
taskManager.AddTask(new Task { Description = "Write blog post", IsCompleted = false });
taskManager.AddTask(new Task { Description = "Refactor source code", IsCompleted = false });
taskManager.AddTask(new Task { Description = "Run unit tests", IsCompleted = true });
taskManager.PrintTasks();
}
}
}
In this refactored version, we’ve addressed the identified code smells:
- Duplicated code is eliminated by extracting the validation logic into a separate private method
IsValidIndex
. - The
PrintTasks
method remains unchanged for simplicity, but in a real-world scenario, it might be refactored further. - We haven’t addressed the Primitive Obsession smell in this example, but it could be improved by encapsulating task properties within a separate class.
- Error handling is improved by validating index values before performing update or delete operations.
- We haven’t addressed the SRP violation in this example, but separating concerns further might involve creating a separate class responsible for printing tasks.
Refactoring code in this manner improves readability, maintainability, and reduces the likelihood of introducing bugs in the future.
The source code is available at https://gitlab.com/mvineetsharma/Workshop/Exercise/codesmellbloatersexercise.git