1

When using data and domain models, where does validation take place? Both or just

For example:

class UsersDB():
 def create(self, user_data):
 # Create user here
 return insert_status
 def confirm_user(self, token):
 if token_date < today_start:
 # Token expired, return False
 return False
 if not self.collection.exists({'token':token}):
 # Token doesn't exist
 return False
 # Confirm user account
 self.collection.update_one({}, {})
class UserService():
 def __init__():
 self.users_db = UsersDb()
 def create(self, user_data):
 if self.users_db.exists(user_data['email']):
 self._set_error(status=409, error='This user already exists.')
 return False
 if self.users_db.create(user_data):
 EmailService().send_registration_email(user_data)
 AuditService().add_event('registration', ....)
 else:
 self._set_error(status=500, message='Unable to create user.'
 return False

Now, in the UsersDB.confirm_user(), if this method fails, it's impossible to determine why the method call fails, be it due to the non-existant token or the expired token. However, this is validation that I don't necessarily want mixed in with the business logic. I'd prefer to keep validation within the UsersDB wrapper.

Similarly, if I wanted to do some more advanced validation on the user_data parameter passed through to UserService.create(), then I'd need to do it at the UserService level in order to get any meaningful feedback to the user.

Should I just separate validation out of the UsersDB object and do the validation within the UserService methods before passing over to the UsersDB object, or is there a problem with the design that needs addressing?

Ideally, I'd like to keep the validation out of UserService so that it only handles calls to other services, but I'm not sure if that's a good idea.

asked Feb 10, 2020 at 16:22
1
  • Validation is one of those things that can/should/must end up in multiple locations. See this answer. Commented Feb 10, 2020 at 23:15

2 Answers 2

1

If you want to keep the validation logic out of UserService, but keep the reporting of errors to the user contained within that class, then you should look at other ways to internally communicate validation failures, rather than a boolean return value.

Either the UserDb methods should return an error code, or they should throw an exception for validation failures. The UserService class can then convert those internal indications into error responses for the user.

answered Feb 10, 2020 at 18:58
2
  • I did consider having a error attribute that is set on the object, and then if the method returns False, then pull the error string from the object. Thoughts? Commented Feb 10, 2020 at 19:06
  • @Slepton, that is a possibility. Commented Feb 10, 2020 at 19:09
0

I've come to the conclusion through both Bart van Ingen Schenau's answer and also this answer suggested in a comment by John Wu, that ideally there should be validation in all layers of the platform. My plan is to have an error attribute on UsersDB() that is set when a method() returns False. The service object can then access the error to get the reason.

answered Feb 11, 2020 at 9:49

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.