🏛️ CAPÍTULO 12: DIAGRAMA DE CLASSES (CONCEITOS)


🎯 1. Objetivos de Aprendizagem & Competências

Estimativa de Dedicação: 2 horas de estudo autoguiado.
Ao final deste capítulo, você será capaz de:

  • 🔹 Compreender a estrutura do Diagrama de Classes da UML como pilar fundamental da modelagem estática e da Programação Orientada a Objetos (POO).
  • 🔹 Dominar a representação dos três compartimentos canônicos: Nome da Classe, Atributos Tipados e Métodos com Assinaturas de Retorno.
  • 🔹 Aplicar os modificadores de visibilidade da UML: Público (+), Privado (-), Protegido (#) e Pacote (~).
  • 🔹 Mapear classes UML para código Python 3.11+ utilizando propriedades protegidas (@property) e modelos do SQLAlchemy 2.0.

🏢 2. Cenário Corporativo & Estudo de Caso (TecProExpress)

Na TecProExpress, a equipe financeira identificou um bug crítico: funções espalhadas pelo sistema alteravam diretamente a variável saldo de motoristas parceiros sem registrar o log de auditoria e sem validar se o valor ficaria negativo.

O Desafio: Como Arquiteto de Software, você deve redesenhar o domínio aplicando o princípio do Encapsulamento. A classe CarteiraDigital deve manter o saldo estritamente privado (-), expondo apenas métodos públicos de depósito e saque com validação defensiva de integridade.


🧠 3. Fundamentação Teórica & Modelos Visuais

3.1. Anatomia da Classe na UML 2.5

Uma classe é representada na UML por um retângulo com três compartimentos horizontais:

classDiagram
    class CarteiraDigital {
        -String idCarteira
        -Decimal saldoPrivado
        #String idTitular
        +depositar(Decimal valor) bool
        +sacar(Decimal valor) bool
        +consultarSaldo() Decimal
    }

3.2. Modificadores de Visibilidade e Encapsulamento

Símbolo UMLVisibilidadeSemântica de EngenhariaEquivalente em Python 3.11+
+Público (Public)Acessível por qualquer classe ou módulo da aplicação.def consultar_saldo(self):
-Privado (Private)Acessível única e exclusivamente por métodos da própria classe.self.__saldo = saldo (Name Mangling)
#Protegido (Protected)Acessível pela própria classe e por suas subclasses derivadas.self._titular = titular (Convenção)
~Pacote (Package)Acessível por classes pertencentes ao mesmo pacote/módulo.Módulos internos (_internal.py)

💻 4. Aplicação Prática & Código Executável (Python 3.11+)

📋 Pré-requisitos e Instalação

Este exemplo utiliza exclusivamente módulos da biblioteca padrão do Python (decimal), não necessitando de bibliotecas de terceiros:

python --version  # Requer Python 3.11 ou superior

💻 Código Completo e Autocontido (carteira_digital.py)

Transposição da classe modelada na UML para código Python com encapsulamento defensivo e validações de invariantes de negócio:

"""
Módulo: carteira_digital.py
Domínio: Encapsulamento e proteção de saldo financeiro.
"""
from decimal import Decimal

class CarteiraDigital:
    def __init__(self, id_carteira: str, titular: str, saldo_inicial: Decimal = Decimal("0.00")):
        self.id_carteira: str = id_carteira          # + Público
        self._titular: str = titular                 # # Protegido
        self.__saldo: Decimal = saldo_inicial        # - Privado

    def depositar(self, valor: Decimal) -> bool:
        """+ Método Público para entrada de recursos com validação."""
        if valor <= Decimal("0.00"):
            raise ValueError("O valor de depósito deve ser estritamente positivo.")
        self.__saldo += valor
        return True

    def sacar(self, valor: Decimal) -> bool:
        """+ Método Público com trava de saldo insuficiente."""
        if valor <= Decimal("0.00"):
            raise ValueError("Valor de saque inválido.")
        if valor > self.__saldo:
            raise PermissionError("❌ Saldo insuficiente na carteira.")
        self.__saldo -= valor
        return True

    @property
    def saldo(self) -> Decimal:
        """+ Getter público controlado."""
        return self.__saldo

if __name__ == "__main__":
    print("--- Teste de Encapsulamento da Carteira Digital ---")
    carteira = CarteiraDigital("CRT-2026-99", "Marcos Silva", Decimal("500.00"))
    carteira.depositar(Decimal("250.00"))
    carteira.sacar(Decimal("100.00"))
    print(f"Titular: {carteira._titular}")
    print(f"✅ Saldo da Carteira {carteira.id_carteira}: R$ {carteira.saldo:.2f}")

    # Teste de violação de regra de negócio
    try:
        carteira.sacar(Decimal("1000.00"))
    except PermissionError as e:
        print(f"Validação defensiva disparada: {e}")

🚀 Como Executar

Execute o script diretamente no terminal:

python carteira_digital.py

🖥️ Saída Esperada no Terminal

--- Teste de Encapsulamento da Carteira Digital ---
Titular: Marcos Silva
✅ Saldo da Carteira CRT-2026-99: R$ 650.00
Validação defensiva disparada: ❌ Saldo insuficiente na carteira.

💡 5. Checkpoint de Engenharia & Boas Práticas

Boas Práticas & Anti-Patterns

  • Encapsulamento é Segurança: Nunca deixe atributos críticos (preço, saldo, estoque) acessíveis diretamente de fora da classe. Use métodos de negócio (adicionar_item(), processar_baixa()) para garantir que as regras e invariantes sejam sempre validadas.
  • Anti-Pattern Anemic Domain Model: Evite criar classes que são apenas "sacos de getters e setters" sem qualquer lógica de negócio, espalhando cálculos e regras em funções utilitárias desordenadas.

🔗 6. Conexão com os Projetos Integradores

Projeto IntegradorComo o conceito deste capítulo é aplicado no PI
PI-03: PDVLiteClasse Venda com encapsulamento do cálculo do total de itens e aplicação de desconto fiscal.
PI-09: FinLiteClasse ContaBancaria protegendo o saldo contábil contra baixas não autorizadas.

🧪 7. Quiz de Fixação e Autoavaliação (Formative Assessment)

🧪 Quiz de Autoavaliação — Capítulo 12

1. No diagrama de classes da UML, qual símbolo gráfico representa que um atributo possui visibilidade 'Privada' (Private)?

  • A) + (Mais)
  • B) - (Menos)
  • C) # (Cerquilha/Hash)
  • D) ~ (Til)
💡 Ver Resposta e Justificativa

Resposta Correta: B
Justificativa: O símbolo - representa visibilidade Privada (Private), garantindo que apenas métodos internos da própria classe possam acessar e modificar o atributo.


2. O que caracteriza o princípio da Orientação a Objetos conhecido como 'Encapsulamento'?

  • A) Permitir que qualquer script altere variáveis globais sem restrições.
  • B) Ocultar os detalhes internos de implementação e proteger o estado do objeto, permitindo acesso apenas através de uma interface pública validada.
  • C) Transformar todo o banco de dados em arquivos CSV.
  • D) Executar múltiplos programas na mesma máquina virtual.
💡 Ver Resposta e Justificativa

Resposta Correta: B
Justificativa: O encapsulamento blinda o estado interno do objeto contra manipulações externas indevidas, mantendo a integridade e coesão das regras de negócio.


3. Na representação de um método na UML + calcularTotal(desconto: Decimal): Decimal, o tipo após os dois pontos no final indica:

  • A) O nome da tabela do banco de dados.
  • B) O tipo de dado do primeiro parâmetro.
  • C) O tipo de dado do valor de retorno do método.
  • D) A versão do compilador.
💡 Ver Resposta e Justificativa

Resposta Correta: C
Justificativa: Na sintaxe da UML, o tipo após os dois pontos da assinatura do método especifica o tipo de retorno retornado pela função.


🛠️ 8. Ponte para a Ação: Laboratório Prático

🎯 Próximo Passo Prático

Coloque esta teoria em prática executando o roteiro de laboratório autoguiado:
👉 ATIVIDADE 07: DIAGRAMA DE CLASSES (UML)


📌 9. Resumo Executivo & Key Takeaways

  • Planta Estática: O Diagrama de Classes define a estrutura de dados e as operações fundamentais do sistema.
  • 3 Compartimentos: Nome da Classe, Atributos Tipados e Métodos com assinaturas.
  • Encapsulamento Estrito: Atributos devem ser privados (-) ou protegidos (#); métodos de negócio compõem a interface pública (+).
  • Mapeamento ORM: Classes UML conectam-se diretamente às tabelas relacionais do SQLAlchemy e schemas do Pydantic.