Card 07/ 08
Practice: Splitting a User Account Class
Sign-up rules, password hashing, a welcome email and a CSV export in one class.
Splitting a class by reason to change starts with naming its actors. This exercise gives you a UserAccount class from a sign-up service. First list the groups of people who could ask for each part to change, then propose the classes you would split it into.
import hashlib
class UserAccount:
def __init__(self, email, password):
if "@" not in email:
raise ValueError("invalid email")
if len(password) < 8:
raise ValueError("password too short")
self.email = email
self.password_hash = hashlib.sha256(password.encode()).hexdigest()
def send_welcome_email(self):
print(f"MAIL to {self.email}: Welcome aboard!")
def to_csv_row(self):
return f"{self.email},{self.password_hash[:8]}"
account = UserAccount("[email protected]", "correct horse")
account.send_welcome_email()
print(account.to_csv_row())MAIL to [email protected]: Welcome aboard!
[email protected],4104d36fWork through it in two passes. For every method and every check inside the constructor, write down who would ask for it to change. Then group the pieces by those names; each group is a candidate class. Check that nothing you put together would ever change for two different groups.
Show one good answer
| Part | Actor | New home |
|---|---|---|
| Email must contain @ | Product team (sign-up rules) | SignUpRules |
| Password at least 8 characters | Security team | PasswordPolicy |
| SHA-256 hashing | Security team | PasswordPolicy |
| Welcome email text | Marketing team | WelcomeMailer |
| CSV export columns | Data team | AccountCsvExport |
Four actors means four classes, plus a plain UserAccount that only holds the email and the hash. The password length rule and the hashing go together even though they are different methods, because the security team changes both. (Plain SHA-256 is also too fast for real passwords; that would be the security team's first change.)
← → move through sections and cards