NicolasMendesMO (discussão | contribs)
 
(19 revisões intermediárias por 2 usuários não estão sendo mostradas)
Linha 15: Linha 15:


[RF002] Implementar match
[RF002] Implementar match


== Requisitos Não-Funcionais ==
== Requisitos Não-Funcionais ==
<br>
<br>
[RNF] O sistema deve possuir respostas rápidas com menos de 1s de latência


== Melhores práticas ==
== Melhores práticas ==
Linha 167: Linha 167:
</pre>
</pre>


<br>
 
<b>Clean Code</b>
<b>Clean Code</b>
O código foi pensado para possuir métodos simples e fáceis de entender e dar manutenção, além de possuir variáveis com nomes que refletem as propriedades do objeto facilitando assim o entendimento da lógica do código.
O código foi pensado para possuir métodos simples e fáceis de entender e dar manutenção, além de possuir variáveis com nomes que refletem as propriedades do objeto facilitando assim o entendimento da lógica do código.


= Evolução do projeto =
= CRONOGRAMA =


{| class="wikitable"
{| class="wikitable"
Linha 185: Linha 185:
| 4 || 14/11/2025 || Especificar RFs e RNFs - Fase 2 || 100%
| 4 || 14/11/2025 || Especificar RFs e RNFs - Fase 2 || 100%
|-
|-
| 5 || 17/11/2025 || RF01: Implementar visualização de detalhes || 25%
| 5 || 17/11/2025 || RF01: Implementar visualização de detalhes || 20%
|-
|-
| x || 24/11/2025 || TeckWeek ||
| x || 24/11/2025 || TeckWeek ||
|-
|-
| 6 || 01/12/2025 || Melhores Práticas ||
| 6 || 01/12/2025 || Melhores Práticas || 100%
|-
|-
| 7 || 01/12/2025 || RF01: Implementar visualização de detalhes ||
| 7 || 01/12/2025 || RF01: Implementar visualização de detalhes da vaga || 100%
|-
|-
| 8 || 01/12/2025 || RF02: Implementar match ||
| 8 || 01/12/2025 || RF02: Implementar matching || 35%
|-
|-
| 9 || || Desenvolver 3o RF ||
| 9 || 08/12/2025 || RF03: Implementar visualização de detalhes do usuário || 100%
|-
|-
| 10 || || Desenvolver 4o RF ||
| 10 || 08/12/2025 || RF04: Implementar guardrail listagem de usuários || 20%
|-
| 11 || || Incrementar diferencial tecnológico ||
|-
|-
| 11 || 08/12/2025 || RF05: Implementar cálculo de score baseado nas preferências || 25%
|-
| 12 || 08/12/2025 || RF06: Implementar criação de chat sem comunicação síncrona || 0%
|-
| 13 || 15/12/2025 || 2a. entrega - Video pelo Teams até 19/12/2025 - RFs 1, 2 e 3 ||
|-
| 14 || || Incrementar diferencial tecnológico ||
|-
| 15 || 19/12/2025 || Vídeo demo encaminhado para cliente || Aguardando avaliação
|-
|}
{| class="wikitable"
|-
! Item !! Data !! Atividades Room Match !! Responsável
|-
| 1 || 09/02/2026 || xx ||
|-
| 2 || 23/02/2026 || xx ||
|-
| 3 || 02/03/2026 || xx ||
|-
| 4 || 09/03/2026 || xx ||
|-
| 5 || 16/03/2026 || xx ||
|-
|}
|}

Edição atual tal como às 20h57min de 9 de fevereiro de 2026

Fase 2


Escopo


  • Desenvolver um sistema que facilite o encontro entre pessoas que estão à procura de um quarto para alugar e as que já possuem o quarto disponível para locação em seus imóveis
  • A proposta é criar uma plataforma digital (via web) que funcione como um matchmaking de moradia, similar ao funcionamento de apps de relacionamento, com base em critérios como localização, orçamento, perfil de convivência e preferências pessoais


Requisitos Funcionais


[RF001] Implementar visualização de detalhes (quarto e perfil)

[RF002] Implementar match

Requisitos Não-Funcionais


[RNF] O sistema deve possuir respostas rápidas com menos de 1s de latência

Melhores práticas


Single Responsibility Principle - Responsabilidade Única

A classe class UserRepository(BaseRepository) possui métodos de responsabilidade única como mostrado abaixo:

    def get_user_by_id(self, user_id: int) -> Optional[User]:
        """Busca um usuário pelo ID."""
        stmt = select(User).where(User.id == user_id)
        result = self.execute_stmt(stmt)
        return result.scalar_one_or_none()

Essa função tem uma única responsabilidade que é obter o usuário do repositório não aplicando sobre o usuário nenhum tipo de regra de negócio ou modificação.


Open/Closed Principle - Aberto para Extensão, Fechado para Modificação

A classe class UserService tem métodos que estão fechados para modificação mas a classe pode ser extendida adicionando novos métodos, como mostrado abaixo:

class UserService:
    def __init__(self, user_repository: UserRepository):
        self.user_repository = user_repository

    def create_user(self, name: str, email: str, senha: str, birthday: Date, profile_picture_path: str, description: str = None) -> User:
        # Verificar se já existe um usuário com este e-mail
        existing_user = self.user_repository.get_user_by_email(email)
        if existing_user:
            raise ValueError("Este e-mail já está cadastrado")

        # Hash the password before storing
        hashed_password = bcrypt.hashpw(senha.encode('utf-8'), bcrypt.gensalt())
        return self.user_repository.create_user(
            name=name,
            email=email,
            senha=hashed_password.decode('utf-8'),
            birthday=birthday,
            profile_picture_path=profile_picture_path,
            description=description
        )

    def get_user_by_id(self, user_id: int) -> Optional[User]:
        return self.user_repository.get_user_by_id(user_id)

    def update_user(self, user_id: int, **kwargs) -> Optional[User]:
        return self.user_repository.update_user(user_id, **kwargs)

    def delete_user(self, user_id: int) -> bool:
        return self.user_repository.delete_user(user_id)
    
    def get_user_by_email(self, email: str) -> Optional[User]:
        """Busca um usuário pelo email."""
        return self.user_repository.get_user_by_email(email)

    def authenticate_user(self, email: str, senha: str) -> Optional[User]:
        """Autentica um usuário verificando email e senha"""
        user = self.user_repository.get_user_by_email(email)
        if not user:
            return None
        
        if not bcrypt.checkpw(senha.encode('utf-8'), user.senha.encode('utf-8')):
            return None
        
        return user


Liskov Substitution Principle - Substituição de Liskov

Todas as classes que fazem parte de um repositório herdam/implementam BaseRepository, como exemplo temos a classe UserRepository.

class UserRepository(BaseRepository):
    def __init__(self, session: Session):
        super().__init__(session)

class BaseRepository:
    """
    Repositório base que recebe uma sessão como dependência.
    Segue o princípio de Inversão de Dependência.
    """
    
    def __init__(self, session: Session):
        """
        Inicializa o repositório com uma sessão do banco de dados.
        
        Args:
            session: Sessão do SQLAlchemy gerenciada externamente
        """
        self.session = session
    
    def execute_stmt(self, stmt: Any):
        """
        Executa um statement SQLAlchemy usando a sessão injetada.
        
        Args:
            stmt: Statement SQLAlchemy (select, insert, update, delete, etc.)
            
        Returns:
            Resultado da execução do statement
        """
        return self.session.execute(stmt)


Interface Segregation Principle - Segregação de Interfaces

A linguagem Python não implementa interfaces que expõe métodos, com isso não foi possível aplicar esse princípio no projeto


Dependency Inversion Principle - Inversão de Dependência

Mesmo sem a presença se interfaces o que facilita a inversão de depedência, conseguimos aplicar este princípio criando um classe referente a repositório que faz a instanciação do banco de dados assim que a classe é criada não sendo necessário repetir o código novamente.

class UserRepository(BaseRepository):
    def __init__(self, session: Session):
        super().__init__(session)

class BaseRepository:
    """
    Repositório base que recebe uma sessão como dependência.
    Segue o princípio de Inversão de Dependência.
    """
    
    def __init__(self, session: Session):
        """
        Inicializa o repositório com uma sessão do banco de dados.
        
        Args:
            session: Sessão do SQLAlchemy gerenciada externamente
        """
        self.session = session
    
    def execute_stmt(self, stmt: Any):
        """
        Executa um statement SQLAlchemy usando a sessão injetada.
        
        Args:
            stmt: Statement SQLAlchemy (select, insert, update, delete, etc.)
            
        Returns:
            Resultado da execução do statement
        """
        return self.session.execute(stmt)


Clean Code O código foi pensado para possuir métodos simples e fáceis de entender e dar manutenção, além de possuir variáveis com nomes que refletem as propriedades do objeto facilitando assim o entendimento da lógica do código.

CRONOGRAMA

Item Data Atividades Room Match Realizado
1 14/11/2025 Documentar tópico Investigação 0%
2 14/11/2025 Definir Proposta de Projeto 0%
3 14/11/2025 Validar Visão do Usuário 0%
4 14/11/2025 Especificar RFs e RNFs - Fase 2 100%
5 17/11/2025 RF01: Implementar visualização de detalhes 20%
x 24/11/2025 TeckWeek
6 01/12/2025 Melhores Práticas 100%
7 01/12/2025 RF01: Implementar visualização de detalhes da vaga 100%
8 01/12/2025 RF02: Implementar matching 35%
9 08/12/2025 RF03: Implementar visualização de detalhes do usuário 100%
10 08/12/2025 RF04: Implementar guardrail listagem de usuários 20%
11 08/12/2025 RF05: Implementar cálculo de score baseado nas preferências 25%
12 08/12/2025 RF06: Implementar criação de chat sem comunicação síncrona 0%
13 15/12/2025 2a. entrega - Video pelo Teams até 19/12/2025 - RFs 1, 2 e 3
14 Incrementar diferencial tecnológico
15 19/12/2025 Vídeo demo encaminhado para cliente Aguardando avaliação
Item Data Atividades Room Match Responsável
1 09/02/2026 xx
2 23/02/2026 xx
3 02/03/2026 xx
4 09/03/2026 xx
5 16/03/2026 xx