Aspect Oriented Programming (AOP)
Aspect Oriented Programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It does this by adding additional behavior to existing code (an "advice") without modifying the code itself.
1. Cross-Cutting Concerns
In standard Object Oriented Programming (OOP), classes are modularized based on their primary responsibility. However, some functionalities span across multiple unrelated modules.
- Core Concerns: The primary business logic (e.g.,
calculateTax,saveUser). - Cross-Cutting Concerns: Logic that is needed everywhere (e.g., Logging, Security, Caching, Transaction Management).
Without AOP, you end up with Code Tangling (business logic mixed with logging) and Code Scattering (logging logic duplicated in 50 files).
2. Key Concepts
- Aspect: A module that encapsulates a cross-cutting concern (e.g., a
LoggingAspectclass). - Join Point: A point during the execution of a program, such as the execution of a method or the handling of an exception.
- Advice: The action taken by an aspect at a particular join point.
- Before: Run before the method executes.
- After: Run after the method completes.
- Around: Wraps the method (can run before, after, or prevent execution).
- Pointcut: A predicate that matches join points. It defines where the advice should run (e.g., "All methods starting with
save").
3. Implementation Example (TypeScript Decorators)
In many modern languages, AOP is implemented using Decorators or Proxies.
// The Aspect (Advice)
function LogExecutionTime(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
// Replacing the original method with a wrapper
descriptor.value = function (...args: any[]) {
console.log(`Starting ${propertyKey}...`);
const start = performance.now();
const result = originalMethod.apply(this, args);
const end = performance.now();
console.log(`Finished ${propertyKey} in ${end - start}ms`);
return result;
};
return descriptor;
}
class UserService {
@LogExecutionTime // Applying the Aspect
saveUser(name: string) {
// Business logic only! No logging code here.
console.log(`Saving user ${name} to DB...`);
}
}
programming/object-oriented-programming programming/javascript/typescript/decorators programming/dependency-injection