Modeling the user registration process
"gbilodeau" <[email protected]>
| Newsgroups | gmane.comp.programming.domain-driven-design |
|---|---|
| Message-ID | <[email protected]> |
Hi all, I'm looking for some basic feedback on the very standard user registration process. Here we go. Domain ====== . In order to access some restricted features of the application, a person needs to create an account for the application. . During this registration process, the person enters his full name, his email address, a password of his choice and, optionally, a profile photo. A thumbnail of the profile photo must be presented to other users in various situations. . At this point, the person cannot yet log in using his email address and password. . The person's email address must then be verified. A random alphanumeric token is generated and sent to the person's email address, along with an application URL. . The person then opens this application URL and enters the given token. In case of a match, the person's email is considered verified and his account is activated. The person can now login with his email address and password. Design ====== The following packages, classes and resources have been created. Interfaces are marked by (I), classes by (C), enums by (E) and files by (F). com.company.project.commons.media (I) ThumbnailProducer (C) AwtThumbnailProducer com.company.project.application.user (I) UserAccountService (C) UserAccountServiceImpl com.company.project.application.user.verification (C) EmailVerificationTokenMailer (C) MailingTokenEmailVerificationStrategy (I) TokenBasedEmailVerificationStrategy (F) registration_html_en.template (F) registration_text_en.template com.company.project.domain.token (C) InvalidTokenException (C) RandomAlphanumericTokenFactory (C) Token (I) TokenFactory (I) TokenRepository (E) TokenType com.company.project.domain.user (I) ProfilePhotoRepository (C) ProfilePhotoThumbnailProducer (C) UserAccount (C) UserAccountBuilder (C) UserAccountRegistrationRequest (C) UserAccountRegistrationService (I) UserAccountRepository (E) UserAccountStatus com.company.project.infrastructure.persistence (C) DelegatingProfilePhotoRepository (I) MediaStorage com.company.project.infrastructure.persistence.filesystem (C) LocalFileSystemMediaStorage com.company.project.infrastructure.persistence.jpa (C) JpaTokenRepository (C) JpaUserAccountRepository com.company.project.web.user (C) UserAccountRegistrationController (C) UserAccountEmailVerificationController Technical constraints ===================== This application is developed using a common Java stack: Spring MVC, Spring IoC, Spring Security, JPA / Hibernate with a relational Postgres database. Profile photos are to be stored on a locally accessible network area storage. Explanations ============ . UserAccountService/Impl is an application service that manages everything related to user management. . UserAccount is a domain entity. . UserAccountRegistrationRequest is a (mutable) value object that represents the registration request. . UserAccountBuilder is a domain service that builds a UserAccount from this UserAccountRegistrationRequest. . UserAccountRepository is a domain repository that manages UserAccount persistence. Its implementing JpaUserAccountRepository is an infrastructure service. . There is no ProfilePhoto domain object. . ProfilePhotoRepository is a domain repository that manages profile photo persistence and lookup. Its implementing DelegatingProfilePhotoRepository is an infrastructure service. DelegatingProfilePhotoRepository delegates these operations to MediaStorage and its implementing LocalFileSystemMediaStorage. Methods deal in byte[] and URLs. . ProfilePhotoThumbnailProducer is a domain service that produces thumbnails of a given profile photo's byte[] using a ThumbnailProducer and its implementing AwtThumbnailProducer. . UserAccount maintains references to his full-size and thumbnail-sized profile photos using URLs produced by the ProfilePhotoRepository. . UserAccountRegistrationService is a domain service that manages the registration process. Invoked by UserAccountServiceImpl. . Token is a domain entity. Token has a UserAccount owner; UserAccount has no knowledge of the tokens he owns. . TokenFactory is a domain factory. It produces Token instances. RandomAlphanumericTokenFactory is a TokenFactory that uses a random algorithm to achieve this. . TokenRepository is a domain repository that manages Token persistence. Its implementing JpaTokenRepository is an infrastructure service. . TokenBasedEmailVerificationStrategy is an application service that manages email verification. MailingTokenBasedEmailVerification implements this interface by producing a Token, assigning it to its UserAccount owner, and sending it to the owner through the EmailVerificationTokenMailer. It also verifies the later-submitted Token. . EmailVerificationTokenMailer produces the email message using the registration_html_en.template and registration_text_en.template templates. It then sends them using the JavaMail API. Questions ========= I think that this is an adequate model. However, I would like some feedback. 1. Should there be a UserAccount entity at all? Or just a User / Person / Party / Actor entity? 2. How does the packaging look like? 3. Am I completely lost when it comes to distinguishing application vs domain vs infrastructure services? 4. What does the (Delegating)ProfilePhotoRepository to (LocalFileSystem)MediaStorage strategy look like? 5. Should there be a ProfilePhoto domain object? 6. Is MailingTokenBasedEmailVerification really an application service? Or should it be considered a domain service? 7. Is EmailVerificationTokenMailer an application, domain or service or infrastructure service? It looks like an application process, but it speaks of domain entities and integrates with the mailing infrastructure. Not clear to me what this is. I consider the JavaMail API to be the infrastructure service here. 8. Is the UserAccountRegistrationService really necessary, or can the UserAccountServiceImpl orchestrate account registration using the appropriate domain objects? Any feedback would be greatly appreciated :) Thanks a bunch! ------------------------------------