jeudi 12 mai 2022

Database and Buisness Layer Design for Python App

I am trying to understand how to design a python app using UML class diagrams. Take the following database design as an example.

enter image description here

Now I am having troubles understanding how to create class diagrams out of this, specifically in the context of separating the Data layer (SQLAlchemy Models??) from business layer.

Would the data access layer be something like a SQL alchemy model for each table that inherits from some Base model with create, update, delete methods? What other sort of methods might I include in each model? Im assuming some high level function like send_message() would be in a separate class in a higher layer? Something like:

class UserModel(BaseModel):
    __tablename__ = 'user'
    username = Column(String(50), nullable=False)
    password = Column(String(200), nullable=False)


class ConversationUserModel(BaseModel):
    __tablename__ = 'conversation_user'
    user_id = Column(ForeignKey('user.id'), nullable=False)
    conversation_id = Column(ForeignKey('conversation.id'), nullable=False)
    unread_messages = Column(Integer)


class ConversationModel(BaseModel):
    __tablename__ = 'conversation'


class MessageModel(BaseModel):
    __tablename__ = 'user'
    text = Column(String(50), nullable=False)
    sender_id = Column(ForeignKey('user.id'), nullable=False)
    conversation_id = Column(ForeignKey('conversation.id'), nullable=False)

Where BaseModel contains attributes: created_at, updated_at, and methods: create, update, delete.

Now the part that confuses me even more, is how to create a business layer. Is this a completely separate set of classes with business related functions such as create_user(), send_message(), add_user_to_convo() etc.. Would these classes be separated by each individual entity (conversation, user, message)? And how would they instantiate the models? something like?:

class User:
    def __init__(self, user: UserModel = None):
        self.user = user
    
    def create_user(username: str, password: str, encoded_photo: str):
        # handle password hashing, photo storage, etc..
        pass

    def send_message(text: str, convo_id: int):
        # utilize MessageModel, ConversationModel to send a new message
        pass


class Conversation:
    def __init__(self, conversation: ConversationModel = None):
        self.conversation = conversation
    
    def add_user_to_convo(user_id):
        # do stuff
        pass

Or maybe this doesn't really make sense because its not based on what each entities actions are (eg. A user sends a message, but a user does not necessarily create a user. Likewise, a conversation does not add a user to a conversation, but instead a user adds a user to a conversation). If thats the case wouldn't the user class have almost all of the functions, as most of the actions of an application are invoked by a user. Then something like a Message class might not make sense since there is nothing that a message does.

On a related note, take this UML diagram for example, which is similar to almost every UML diagram I am trying to learn from: https://miro.medium.com/max/1200/1*Srh6QviwDT6LFFdSnyzelA.png. This UML diagram to me seems to squash the business and data layer together, as all the data exists as attributes of the class, and high level functions are also associated with each class. If thats the way I am supposed to implement some design given to me, how would that translate into code?

Aucun commentaire:

Enregistrer un commentaire