The goal of this kata is to learn and apply concepts from Domain-driven Design and Layered Architecture to some existing code.
- Checkout the project
git clone https://github.com/alonsogarciapablo/vue-js-refactoring-kata.git
- Install dependencies
npm install
- Run the tests
npm run test
- Run the app
npm run serve
- You're ready to go! 👏
- Define a
RegisterUser
class with an empty constructor and anexecute
method. - Copy the content of the
submit
function to the newexecute
method. Define a parameter for each of the missing variables (eg: refs) and define a variable to hold the return value (hint: the errors), removing any Vue.js code (eg: refs). - Create an instance of the
RegisterUser
class and use it in the submit function. - Extract the new class to its own file:
src/application/use-cases/register-user.ts
. - Take a moment to think how much easier it would be to replace Vue.js with something else now.
class RegisterUser {
constructor(...) {
…
}
execute(): ??? {
…
}
}
Solution: https://github.com/alonsogarciapablo/vue-js-refactoring-kata/compare/main...refactor-step-1
- Define a
UsersRepository
interface in the file whereInMemoryUsersRepository
is defined. - Make
InMemoryUserRepository
implement the newUserRepository
interface. - Extract
UserRepository
to its own file:src/domain/repositories/users-repository.ts
. - Use
UserRepository
inRegisterUser
. - Rename
inMemoryUsersRepository
tousersRepository
inSignupView
. - Use App-level provide to inject the
UserRepository
inSignupView
. Mock the provide/inject using global.provide in the tests. - Take a moment to think how easy it’d be to implement and use a different
UserRepository
.
interface UsersRepository {
add: (user: User) => void
…
}
class InMemoryUsersRepository
implements UsersRepository {
…
}
Solution: https://github.com/alonsogarciapablo/vue-js-refactoring-kata/compare/refactor-step-1...refactor-step-2
- Define an empty
User
class with aname
,email
,birthDate
andencryptedPassword
attributes. - Create an instance of the class.
- Define a
validate
method that returns an empty list validation errors. - Append the errors to the collection of errors in the view.
- One by one, move validations* to the
User
class. - Extract the
User
class to its own file:src/domain/models/user.ts
. - Use
User
ininMemoryUsersRepository
,UsersRepository
and the tests.
*
class User {
…
constructor(...) {
…
}
validate(): Array<string> {
…
}
}
- Define an empty
Email
class. - Create an instance of the class.
- Define a
validate
method that returns validation errors. - Append email errors to the collection of errors in the
User
class. - Move email validations to the
Email
class. - Extract the
Email
class to its own file:src/domain/models/email.ts
. - Move the instantiation of the
Email
to theUser
constructor
class Email {
constructor(...) {
…
}
validate(): Array<string> {
…
}
}
- Define an empty
UserRegistrationService
class. - Create an instance of the class in the view.
- Define an
isEmailTaken
method that returns a boolean. - Implement the
isEmailTaken
method (you will need to inject some dependencies first). - Use the new service/method in the view.
- Extract the
UserRegistrationService
class to its own file:src/domain/services/user-registration-service.ts
.
class UserRegistrationService {
constructor(...) {
…
}
isEmailTaken(email: string): boolean {
…
}
}
You made it! 👏
Full solution: https://github.com/alonsogarciapablo/vue-js-refactoring-kata/compare/main...refactor