It sliced, it dices, it looks up data, it bakes cookies, it does business logic...and more! It's the incredible security class!
I've always gotten a headache everytime I tried to understand the security logic inside this all-in-one class. That's bad since the original devs are long gone. Finally, I began to refactor the beast!
My ultimate goal is to move away from using cookies, or at least having a choice. But the work I've been doing offers so so much more.
Here's what I've done so far...
First, everything that consumed the cookie directly in the code now consumes a UserSecurityReader abstraction that has getters to read each value from the cache (that's as much as the consumer knows). This allows the consuming code to flow freely without having to know the details of how user settings are persisted. Also, it gives us the ability to swap out the caching model at any time in the future without having to update tons of consumer code.
Next up, the cookie setting logic. The app sets a cookie in the user agent on app startup. The global class consumes the security class which does everything in one shot. From a consumption standpoint, this is great! The implementation however is another matter.
I decided to pull out everything except for the cookie setting logic out of this class. I made a builder and what is effectively a lightweight model of a user. The builder processes most of the business logic for now. It gathers data, processes some business rules, and constructs the model. I wanted to keep any data access out of the model so that it can be passed around more freely. Also, it breaks some dependencies that could be issues for consumption.
Let's say we wanted to centralize the builder in a service. That service would need references to some other services. Whatever consumes the model, whether it caches the data or not, should not be forced to carry the same dependencies.
I did come across one business rule that crosses the boundary. My next step is to remedy that. I'm planning on either separating all of the security business logic from the builder, or finding another alternative. The first option seems best right now. However, there may be some redundant data access calls that I would like to avoid. Shouldn't be too difficult to put it all in the right order though.