Patterns - Anti-patterns


In object-oriented programming (OOP), a design pattern is a general repeatable solution to a commonly occurring problem in software design. It represents a best practice for solving a particular problem or completing a certain task. Design patterns can speed up the development process by providing tested, proven development paradigms. They can also improve code readability and maintainability by promoting a clear structure and organization.

An anti-pattern, on the other hand, is a common solution to a recurring problem that leads to poor software design and can result in bad code practices. Anti-patterns are often counterproductive and may lead to maintainability issues, inefficiency, or other problems in the long run.

Let's look at an example of a design pattern and an anti-pattern:

Design Pattern: Singleton Pattern

Description: The Singleton pattern ensures that a class has only one instance and provides a global point of access to it.

public class Singleton
{
    private static Singleton _instance;

    private Singleton() { }

    public static Singleton Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new Singleton();
            }
            return _instance;
        }
    }
}

// Usage
Singleton singletonInstance1 = Singleton.Instance;
Singleton singletonInstance2 = Singleton.Instance;

Console.WriteLine(singletonInstance1 == singletonInstance2); // Output: True

Pros:

  • Provides a single point of access to the instance.
  • Lazy initialization for better performance.

Cons:

  • Can make testing difficult due to global state.
  • Violates the Single Responsibility Principle by handling both instance creation and the responsibility of the class.

Anti-pattern: God Object

Description: The God Object anti-pattern occurs when a single class knows and does too much, becoming a central point for various functionalities in a system.

Example:

public class GodObject
{
    private List<int> data = new List<int>();
    private Logger logger = new Logger();
    private Validator validator = new Validator();

    public int ProcessData(int input)
    {
        if (validator.Validate(input))
        {
            int processedData = Process(input);
            logger.Log("Data processed successfully.");
            return processedData;
        }
        else
        {
            logger.Log("Invalid data. Processing aborted.");
            return -1;
        }
    }

    private int Process(int data)
    {
        // Processing logic here
        return data * 2;
    }
}

public class Logger
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }
}

public class Validator
{
    public bool Validate(int data)
    {
        // Validation logic here
        return data > 0;
    }
}

Pros:

  • None. The God Object anti-pattern is generally considered harmful.

Cons:

  • Violates the Single Responsibility Principle.
  • Poor maintainability, as changes to one functionality may affect others.
  • Difficult to test and debug.

Real-life Example in Core Framework:

Design Pattern: Observer Pattern (used in C#'s WinForms)

The Observer pattern is commonly used in C#'s WinForms framework for event handling. Controls (observers) subscribe to events raised by other controls or objects (subjects). When an event occurs, the subscribed controls are notified, allowing them to respond accordingly.

Anti-pattern: Spaghetti Code

Spaghetti code is a common issue in legacy C# codebases where the flow of the program is excessively tangled and difficult to follow. Properly applying design patterns and refactoring can help alleviate spaghetti code problems in C# applications.


No files yet, migration hasn't completed yet!