I am trying to learn the clean architecture by Uncle Bob. I wanted some basics and following this good post I tried to implement it in python with some minor differences.
class ValidationError(Exception):
pass
class Repository(object):
repositories = {}
@classmethod
def register(cls, type_, repo):
cls.repositories[type_] = repo
@classmethod
def get(cls, type_):
return cls.repositories[type_]
@classmethod
def all(cls):
return cls.repositories
class UserValidator(object):
def validate(self, user):
if not (user.name and user.email):
raise ValidationError
class UserRepo(object):
def __init__(self, validator=None):
self.users = {}
self.next_id = 1
self.validator = validator
def save(self, user):
self.validator.validate(user)
user.id = self.next_id
self.users[self.next_id] = user
self.next_id += 1
return user
def all(self):
return self.users
def get(self, id):
return self.users[id]
def delete(self, id):
return self.users.pop(id)
class CompanyRepo(object):
def __init__(self):
self.companies = {}
self.next_id = 1
def save(self, company):
company.id = self.next_id
self.companies[self.next_id] = company
self.next_id += 1
return company
def all(self):
return self.companies
def get(self, id):
return self.companies[id]
def delete(self, id):
return self.companies.pop(id)
class BaseEntity(object):
def __init__(self):
self.id = None
self.created_at = None
self.updated_at = None
class Company(BaseEntity):
def __init__(self, name, address):
self.name = name
self.address = address
super(Company, self).__init__()
class User(BaseEntity):
def __init__(self, name, email):
self.name = name
self.email = email
self.company_id = None
super(User, self).__init__()
def serialize(self):
return {'id': self.id, 'name': self.name, 'email': self.email, 'company_id': self.company_id}
def value(self):
return self.serialize()
class WorkerAdder(object):
def __init__(self, name, email):
self.user_repo = Repository.get('user')
self.company_repo = Repository.get('company')
self.company = self.company_repo.save(Company('FooBar', 'Dummy street'))
self.user = User(name, email)
def add(self):
try:
self.user.company_id = self.company.id
print self.user_repo.save(self.user).value()
print self.user_repo.all()
print self.user_repo.get(1)
print self.company_repo.all()
except ValidationError as ve:
print "Validation error!"
if __name__ == '__main__':
Repository.register('user', UserRepo(validator=UserValidator()))
Repository.register('company', CompanyRepo())
adder = WorkerAdder('Foo', 'foo@example.com')
adder.add()
O/P from above code:
{'company_id': 1, 'email': 'foo@example.com', 'id': 1, 'name': 'Foo'}
{1: <__main__.User object at 0x7f4b34139d50>}
<__main__.User object at 0x7f4b34139d50>
{1: <__main__.Company object at 0x7f4b34139d10>}
I have basically tried to implement the in memory repository pattern. I would like to hear from others what they think, and why there is so scarcity in the python community regarding the design patterns and different architectures as compared to ruby?
PS: The code above is just for learning purpose hence error handling and error cases are not handled properly.