This repository contains the source code that can be used as the starting point for the Katas based on each of the SOLID principles. The katas are written in C# and VS projects are provided.
Within the SRP folder of the project, you will find a UserController
class providing some simple logic for managing users.
We will use as the base for our SRP katas.
Apply Single Responsibility to the caching logic in the UserController
class.
We found a bug, and the cache needs to be invalidated when a new user is added.
Let's take this chance to move the caching logic outside the UserController
into its own class.
- The controller shouldn't worry about the caching
- Makes testing issues with the caching(like this bug) harder than it should be.
- Add a repository interface
- Create a new repository decorator, moving the caching logic from the
UserController
- Fix the bug in the new decorator class
- Use the caching interface in the
UserController
class
Apply Single Responsibility to the validation logic
There is a new validation that needs to be implemented: User email is unique. The controller class needs to change due to this requirement.
Let's move the validation logic outside the UserController
- The
Add
method still has one too many responsibility - Testing the validation logic is still harder than it should be.
- Create a new
IEntityValidator<T>
interface - Copy validation logic to a new class
UserValidator
implementing the validation interface for T=User - Use the validation interface in the controller class
Within the OCP folder of the project, you will find an ActionExecutor
class which provides a method to execute a list of recording actions. Initially the system has only implemented 2 actions, StartRecordingAction
and StopRecordingAction
.
We will use it as the basis for the OCP katas.
We have found we need to add a new action for deleting a recording.
Let's apply the Open/Closed principle to close the ExecuteActions
function against new types of actions.
- Add a new
IRecordingAction
interface with a methodExecute(platform IPlatform)
, then change ExecuteActions to receive a list ofIRecordingAction
. - Move the code for executing each action from the
ExecuteActions
method to each action class (Create tests for each execute method of each class) - Update the
ExecuteActions
method to call execute on each action of the list (Create tests for the ExecuteActions function) - Add the
DeleteRecording
action class
We have just learned that some platforms might require actions to be executed in a particular order:
- Some legacy platforms require stop actions to be executed before the delete actions, because they dont know how to delete ongoing recordings
- Some budget platforms require delete actions to be executed before start actions, so they can allocate the space more efficiently
Let's apply the Open/Closed principle to close the ExecuteActions function against changes in the action ordering execution
- Add a new interface
IActionSorter
with singleIEnumerable<IRecordingAction> Sort(actions IEnumerable<IRecordingAction>)
method. - Update the
ActionExecutot
with a new optional dependency on the sorter. - Create a sorter implementation
LegacyPlatformActionSorter