Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
AOP (Aspect-Oriented Programming) is a technique for modularising cross-cutting concerns such as profiling, persistence, transactions, access control lists, and exception handling. We can split an app into two parts, aspects and components. Components are parts we can easily encapsulate into code abstraction - methods, objects, or procedures. The application’s logic is an excellent example of a component.
Aspects, on the other hand, cannot be isolated in code. Aspects cross-cut the application when we use some persistence (e.g., a database) or network communication (such as ZMQ sockets). Our components need to know about it.
What is the use of AOP?
Imagine an application that stores code snippets. You can start one of the use cases in the following manner:
class Snip_Use_Case
attr_reader :repo, :log, :snippets
def set_values(snippets_repository = SnippetsRepository.new, log = Logger.new)
@repo = snippets_repository
@log = log
@snippets = []
end
def user_pushes(snip)
snippets << snip
repo.push(snip,
success: self.method(:user_pushed),
failure: self.method(:user_not_pushed))
end
def user_pushed(snip)
log.info "Pushed successfully: #{snip.name} (#{snip.language})"
end
def user_not_pushed(snip, push)
snippets.delete(snip)
log.error "Failed to push: #{push.error}."
end
end
You can also try this code with Online Ruby Compiler
Here we have a use case of inserting snippets into the application. To perform some SRP checks, we can see what the responsibility of this object is? It is an SRP-conformant object if it's responsible for pushing the snippets scenario.
A repository is an object which provides persistence to our snippets. Logger helps us track activity. The use case is a kind of a class that belongs to our logic. But it knows about aspects of our app - and we have to get rid of it to ease our pain!
How to Fix the Code using AOP?
The first step is to remove dependencies from our use case. We'll refactor the code to embrace aspect-oriented programming techniques. So, we delete constructor arguments, and our use case code after the change looks like this:
class SnippetsUseCase
attr_reader :snippets
def initialize
@snippets = []
end
def user_pushes(snippet)
snippets << snippet
end
def user_pushed(snippet); end
def user_fails_to_push(snippet, pushing)
snippets.delete(snippet)
end
end
You can also try this code with Online Ruby Compiler
We're maintaining the user_pushed method only to provide a join point for the solution. There will be many empty methods in code written in the AOP paradigm. Afterwards, we have to provide aspect code to link with our use case. So, we create the SnippetsUseCaseGlue class:
SnippetsUseCaseGlue class:
require 'aquarium'
class SnippetsUseCaseGlue
attr_reader :usecase, :repo, :log
include Aquarium::Aspects
def initialize(usecase, repo, log)
@usecase = usecase
@repo = repo
@log = log
end
Def inject!
Aspect.new(:after, obj: usecase, calls_to: :user_pushes) do |j, obj, snip|
repo.push(snip,
success: usecase.method(:user_pushed),
failure: usecase.method(:user_push_failed))
end
Aspect.new(:after, obj: usecase, calls_to: :user_pushed) do |j, obj, snip|
log.info("Successfully pushed: #{snip.name} (#{snip.language})")
end
Aspect.new(:after, obj: usecase, calls_to: :user_push_failed) do |j, obj, snip, pushing|
log.error "Failed to push our snip: #{pushing.error}"
end
end
end
You can also try this code with Online Ruby Compiler
Inside the advice block, there is a lot of info - including very general info about join point context (j), called obj, and all arguments of the invoked method.
class application
def initialize
@snippets = SnippetsUseCase.new
@snippets_repository = SnippetsRepository.new
@log = Logger.new
@snippets_glue = SnippetsUseCaseGlue.new(@snippets,
@snippets_repository,
@log)
@snippets_glue.inject!
# rest of logic
end
end
You can also try this code with Online Ruby Compiler
Here the use case is a pure domain object without knowing it's connected with some persistence and logging layer. We've eliminated aspects of knowledge from this object.
Frequently Asked Questions
What is the use of AOP?
AOP provides a new level of abstraction.
It helps in the modularisation of behavior.
It provides a clear syntax for describing points for injecting the code into the application.
What are some of the cross-cutting concerns?
Some of the concerns are listed below: -
Profiling
Persistence
Transactions
Access Control Lists
Exception Handling
What are scattered codes?
Aspects are scattered because a function, like logging, may be used in various unrelated functions, potentially in separate systems, in several source languages, etc. That implies that altering logging may necessitate changing all impacted modules.
What are tangled codes?
Aspects tangle not just with one another but also with the primary purpose of the systems in which they are manifested. This implies that altering one issue necessitates comprehending all related concerns or having a method for determining how alterations will affect things.
What is a joint-point model?
The join point model is the foundation of AOP. It consists of two components: pointcuts, a system for choosing join points, and join points, the places at which an application is executed.
Conclusion
In this article, we have extensively discussed Aspect-Oriented Programming in Ruby and its implementation
You can also check our previous blogs on Ruby Programming, Ruby Essentials, and Passing Arguments in Ruby. If you are eager to learn advanced front-end web development, Coding Ninjas is here with one of the best courses available, which you can find here.
Happy Learning!
Live masterclass
Multi-Agent AI Systems: Live Workshop for 25L+ CTC at Google
by Saurav Prateek
09 Feb, 2026
03:00 PM
Beginner to GenAI Engineer Roadmap for 30L+ CTC at Amazon