0

I'm working on designing a shopping cart system that respects the single responsibility principle. However, I'm facing a challenge when it comes to handling cart creation and updating separately.

Scenario:

When a user logs into the website and adds products to the cart. Currently, the "add to cart" operation also implicitly creates a cart, which violates the single responsibility principle. I want to find a solution that respects the single responsibility of creating and updating the cart separately, without requiring the user to explicitly create the cart.

I'm considering a few approaches and would appreciate insights or alternative suggestions:

Approach 1: Domain Logic inside "Add to Cart" Service

If I, as the domain owner, decide to embed the cart creation logic within the "add to cart" service, allowing it to create the cart if it doesn't exist. it seems like a practical solution, but maybe not a good design.

Approach 2: Two Separate Services

Creating two services, one for cart creation and another for cart update seems like a clean separation of concerns. The create cart service would be invoked asynchronously via an event triggered by account creation. However, I'm concerned about potential overengineering, and the asynchronous event might fail and/or take some time to be processed, affecting the user experience.

Approach 3: Two services with Observer pattern

I'm considering using the observer pattern. After the user creates an account, a synchronous trigger would invoke the create cart service. Would this be a more straightforward solution in terms of implementation and user experience?

2
  • Perhaps a more useful viewpoint is: conceptually, every account/session already has an empty cart. You're just deferring storage until there's at least one item. The condition "cart storage must exist before an item can be added" sounds like an internal implementation detail, not like something that should be exposed via public APIs. Arguably, this is because of the SRP: maintaining its own data integrity must be the service's responsibility. It would violate SRP if clients are responsible for that. Possible exception: cart creation has business-level consequences, e.g. a paid subscription.
    – amon
    Commented Jan 8 at 7:30
  • the "add to cart" operation also implicitly creates a cart, which violates the single responsibility principle. -- That's not true at all. The SRP is informed by variations in your functional requirements; all you have here is one requirement (The requirement being that a cart must always exist before you can add something to it). Such a requirement cannot vary in any way; i.e. it is not possible to add something to a cart that doesn't exist, therefore you have no variations, therefore the creation of the cart and add/remove operations all fall under the same responsibility. Commented Jan 8 at 7:55

1 Answer 1

4

Never use SRP to this kind of degree. The SRP gets a fair amount of hate, specifically because of cases where it's used to such a granular degree that it becomes more a problem/obstacle than an actual solution or helpful guideline.

Simply put: no, creating a cart when none existed is not a violation of SRP. It's merely a violation of your overly strict interpretation of SRP. SRP was originally coined on a much higher level than this, e.g. if you were processing payments with a payment provider inside of the Cart class. You are nowhere near that kind of SRP violation.

It would be much more helpful in this instance to think of it in terms of reusability. It will automatically help you adhere to SRP. Note the following:

  • When you add the first item, you create a cart and then add the item to the (now) existing cart.
  • When you add further items, you add the item to the existing cart.

What you should conclude here is that in both cases, the logic for adding an item to a cart is the same, and therefore it should be reused. However, there's multiple ways to skin this cat.

The two main solutions are either to use a separated create/update use case, or to simply use cart creation as a small extra bit inside the "add to cart" use case. Both are valid solutions.

  • If you expect there to be more differences between the two use cases, keep them separate.
  • If you are confident that all your behavior can adequately be described as a single "add to cart" use case, then do that.

The short answer here is that you should just drop your current SRP focus and instead focus on your requirements. This isn't about right/wrong, this is about what your application requirements are and modeling your system to best implement those requirements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.