Some uncertainty in the implementation of the 3-structure model (domain object, data display device, and maintenance)

As the title suggests, I am having small problems when implementing a 3-structure model (Domain object, dataperper and service).

In the past, when someone registered on my site, I just did

$user->register($firstName, $lastName, $emailAddress, $username...); 

and this method will be executed with a step like this

 1. Check if the form sent was valid. 2. Check if all the required fields were filled. 3. Check the if the lengths of strings were valid and the range of integers etc. 4. Check if the input is in the correct format (regex). 5. Check if the username is already taken and if the email address already exists in the database 6. etc. etc. 

Everything works fine, but I'm trying to get away from this because I want my code to be more reusable and verifiable.

Now, with this 3-line model, the Domain Object and Data Map must communicate through the Service to isolate them from each other, so here is my idea of โ€‹โ€‹a user service

 class UserService { public function register($firstName, $lastName, $email...) { $userDO= $this->domainObjectFactory->build('User'); $mapper = $this->dataMapperFactory->build('User'); // Is this where I start doing my validation like in the steps above??? // And if this is where I start doing my checks, when I get to the part // where I have to check if the username they want is already taken how // how do I do that check? } } 

And then, to actually run, that I would do it from my controller, so

 $userService = $this->serviceFactory->get('user'); $result = $userService->register($_POST['firstName']....); 

The logic (if and else) should go in the register() method in my UserService class correctly? Because if they fall into the domain object, when I am in the stage of need for the database to perform some checks, for example, if the username already exists, how can I access the database? I really don't know, since the domain object should not know anything about the data source.

There should be access to the database for small queries, for example, checking for a username or email address and many other small queries that need to be completed.

I have a lot of domain objects / objects that have to do a lot of small queries, and in the past my model had access to the database from any method and could execute those queries, but this doesn't seem to be allowed with this 3, and I'm dying to find out how to do it right, because there must be a way.

I flew until I found out that the Model is a layer, divided into 3 structures.

Any help or push in the right direction would be very helpful, especially good examples of real life. There seems to be no such problems on the Internet for my particular problem.

Thanks.

+4
source share
2 answers

I am experiencing the same thing as you are now (funny enough, for this exact problem - registering / authorizing the user).

One tip that I have is that you should not limit your model to just three layers (in this case, 3 classes). The model should have as many classes as necessary to complete the work while maintaining the integrity of the SRP principle (principle of shared responsibility).

For example, you can also use the UserTableGateway class to compliment UserDataMapper and the UserCollection class to take advantage of the potential pagination or common user list functionality. All of these things can be part of your model and UserService level.

To answer your question about the logic specific to the registration process, yes, the most suitable place for it is in the registration methods of the UserService class.

All that has been said, you can think about your domain structure here. Is UserService the most suitable place for registration (and for extension, registration, password recovery, password change, etc.)?

Perhaps these things may be part of a completely different account model. A service class might be something like this:

 class Account { // Think of this as AccountService, it will have a number of collaborators, // including an Authenticator class for loggin in, a Session class for managing the session // and of course various persistence classes for storing the user, session and credentials public function register(UserInterface $user) {} public function login($email, $password) {} public function logout(UserInterface $user, $session_id) {} public function changePassword($user_id, $old_password, $new_password) {} public function recoverPassword($user_id, $email) {} } 

Given that there may potentially be dozens of other things that UserService may be responsible for, it makes sense to store everything related to the user account in its own class of service.

Conceptually, an account is in any case different from the user, and if it is conceptually different, it deserves its own class.

Now, to get the service class of the account of the dependencies that it needs, which is outside of me at this stage in my understanding of complex system design.

+1
source

This is an interesting question. I believe that your Data Mapper user has methods for searching and loading users based on some criteria (e.g. username). Therefore, in this case, I will do a check inside UserService :: register, trying to find the user with the provided username (if it exists):

 if ($mapper->findUserByUsername($username)) { // username is already taken, handle this special case } 

By the way, I donโ€™t know if you are reading this, but a very good guide is Martin Fowlerโ€™s book - Patterns of Enterprise Application Architecture . You will find answers to many of your questions.

0
source

All Articles