- Lab
-
Libraries: If you want this lab, consider one of these libraries.
- Core Tech
Guided: Refactor Java Notification Application Using SOLID Principles
In this Code Lab, students will refactor a simple Java notification application to adhere to SOLID principles. Starting with a single class that violates these principles, they will step by step transform it into a well-designed, maintainable, and extensible system.
Lab Info
Table of Contents
-
Challenge
Step 1: Introduction and Initial Setup
Welcome to the SOLID principles Code Lab! In software engineering, SOLID is a mnemonic acronym for five design principles intended to make software designs more understandable, flexible, and maintainable.
In this first step, you will become familiar with the project structure and run the initial set of tests. The starter code contains a
NotificationServiceclass (located atsrc/main/java/com/solid/notification/NotificationService.java) that works but violates several SOLID principles. The goal is to refactor it step by step. > This lab experience was developed by the Pluralsight team using Forge, an internally developed AI tool utilizing Gemini technology. All sections were verified by human experts for accuracy prior to publication. For issue reporting, please contact us. -
Challenge
Step 2: The Single Responsibility Principle (SRP)
The Single Responsibility Principle states that a class should have only one reason to change. The current
NotificationServiceclass (insrc/main/java/com/solid/notification/NotificationService.java) is responsible for sending both emails and SMS messages. If the SMS sending logic needs to change, a class that also contains email logic must be modified. This is a clear violation of SRP.In this step, the
NotificationServicewill be refactored into smaller, more focused classes:EmailServiceandSmsService. -
Challenge
Step 3: The Open/Closed Principle (OCP)
The Open/Closed Principle asserts that software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. This means it should be possible to add new functionality without changing existing code.
To adhere to OCP, a
Notificationinterface will be introduced atsrc/main/java/com/solid/notification/interfaces/Notification.java. All notification services (EmailService,SmsService, and the newPushNotificationService) will implement this interface, allowing new services to be added in the future without altering the code that uses these services. -
Challenge
Step 4: Liskov Substitution (LSP) and Interface Segregation (ISP)
The Interface Segregation Principle (ISP) states that no client should be forced to depend on methods it does not use. The current
Notificationinterface is simple, but what if some notifications support video and others don't? Forcing all classes to have asendVideomethod violates ISP.The Liskov Substitution Principle (LSP) states that objects of a superclass should be replaceable with objects of its subclasses without breaking the application.
In this step, more specific interfaces will be created:
TextNotification(insrc/main/java/com/solid/notification/interfaces/TextNotification.java) andMultimediaNotification(insrc/main/java/com/solid/notification/interfaces/MultimediaNotification.java) to follow ISP and ensure the class hierarchy respects LSP. -
Challenge
Step 5: The Dependency Inversion Principle (DIP)
The Dependency Inversion Principle states that high-level modules should not depend on low-level modules. Both should depend on abstractions. Also, abstractions should not depend on details. Details should depend on abstractions.
A high-level
NotificationManager(insrc/main/java/com/solid/notification/NotificationManager.java) will be created that depends on theNotificationinterface (an abstraction), not on concrete classes likeEmailService. The specific service to use will be 'injected'. Finally, the application insrc/main/java/com/solid/notification/Main.javawill be updated to see everything working together. -
Challenge
Step 6: Compilation and Execution
Congratulations! In this lab, you've successfully transformed a poorly designed notification application into a well-architected system that embodies all five SOLID principles.
You started with a monolithic NotificationService class and systematically refactored it by applying the Single Responsibility Principle to separate concerns, the Open/Closed Principle to enable extensibility, the Liskov Substitution and Interface Segregation Principles to create focused, substitutable contracts, and the Dependency Inversion Principle to decouple high-level logic from concrete implementations.
Through this hands-on experience, you've learned how to write Java code that is more maintainable, testable, and adaptable to change, skills that are fundamental to professional software engineering.
About the author
Real skill practice before real-world application
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Learn by doing
Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.
Follow your guide
All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.
Turn time into mastery
On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.