Learning about Command and Query Handlers
Background
I created the Light Show Extender application as a project to add functionality to my Christmas Light Show. The problem that I have is one that is similar to many other C# applications that utilize the Clean Architecture or Onion Architecture structure. That the more code that the application has, the harder it is to find and make updates to the application. Why is this the case? Because those architecture patterns organize code by their technical concern instead of by their feature or functionality as it relates to the application.
Structure
By structuring the project based on the feature and functionality, when changes to the code have to be made, they are easier to do when all or most of the code is next to each other. I decided to refactor the existing application to be more like CQRS pattern. CQRS stands for Command Query Responsibility Segregation.
Commands are things that typically change state in the application. Also they do not return values from the operations that they perform. Queries usually retrieve values from the application and return them.
ChatGPT with the Assist
With some assistance from ChatGPT, I create a class and corresponding method for each use case. Originally I had created static methods for each use case, but after realizing that each has a number of dependencies, I changed each to be a sealed class that utilizes Dependency Injection. That way, I do not have to pass in each of the objects that is needed by each class. One problem, is that since the application that I created is a background worker application, the worker class has a lot of dependencies because of the number of handlers.
Conclusion
I intent on using this design pattern in future projects. May consider refactoring existing projects to use this manner so that they are easier to maintain. There are some additional improvements that I have identified that I want to do to improve the structure of the application. This includes adding more interfaces and making the handlers run as Scoped instead of Singletons.