I would like to suggest you study this blog:
https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html
As per my understanding, I think that the name is confusing. It is functions that should have only one responsibility.
To me, SRP can be viewed as:
1). The objective of SRP is to achieve cohesion, to put closely related things into one class and the lesser ones to act as dependency and
code should try to have zero dependencies if possible though usually not possible.
So, if you use UserService for placeOrder() and addProductToBucket() then your code is less cohesive and thus violates SRP.
Cohesion can be seen with respect to Bounded context as mentioned in @DavidGuida's answer.
2). A class should not contain business logic for multiple Actors( I have explained it in the last paragraph).
Actor means a single user or group of users needed to be treated uniformly. Like we can have Admin and simple User as two different Actors.
Hence, the classes should be designed to be loosely coupled, with lesser dependencies, and to handle a single resource.
That is UserService should only handle user-specific tasks like registerUser(), updatePassword(), etc.
We can create OrderService to handle placeOrder() and ProductService and BucketService to handle addProductsToBasket().
BucketService can act as a dependency to ProductService or vice-versa.
ProductService Tasks could be:
- Checking if the product is available or not.
- Call BucketService to add products into the bucket.
- Decrease product count.
BucketService Tasks might be:
- Check if the bucket is full or not.
- Add product into the bucket.
- Increase the count for products in the bucket.
However, if placeOrder() can be called by Admin and by common user then SRP will come into play.
Then OrderService can act as Facade (rename to OrderFacade) and then it can do similar actions within it and for admin and user-specific actions, it can use Strategy Pattern.
Like We can create an interface OrderService having function create implemented by OrderServiceForAdmin and OrderServiceForUser classes.
Thus for an Admin-related change, we will update OrderServiceForAdmin and for user-related change, OrderServiceForUser will be modified.
References:
The blog mentioned above.
Books by Robert Martin. 1). Clean Code 2). Clean Architecture
NOTE: I am still learning these concepts and thoughts are welcome.