Visão Geral da Arquitetura¶
O MIDDAG é um plugin Moodle com um framework interno e um modelo de extensões. Sua arquitetura adota princípios inspirados em Ports and Adapters, organização em camadas e práticas comuns de frameworks modernos, adaptadas ao ecossistema procedural do Moodle.
O objetivo principal é desacoplar regras de negócio e módulos funcionais da infraestrutura do Moodle, concentrando esse contato em camadas e contratos mais previsíveis.
Fluxo de Requisição¶
Diferente de plugins tradicionais que misturam HTML, SQL e lógica em arquivos .php soltos, o MIDDAG centraliza o fluxo de execução por um núcleo de framework.
O diagrama abaixo ilustra como uma requisição sai do Moodle e trafega pelas camadas do plugin até retornar uma resposta:
graph TD
subgraph Moodle_Environment [Ambiente Moodle]
User((Usuário)) -->|Requisição HTTP| MoodleCore[Moodle Core / Lib.php]
MoodleCore -->|Hook / Entry Point| Entry[Entry Point do plugin]
end
subgraph MIDDAG_Core [Camada de Aplicação]
Entry -->|init & handle| Kernel[Kernel]
Kernel -->|Boot| Container[DI Container]
Kernel -->|Match Route| Router[Route Manager]
Router -->|Dispatch| Controller[Base Controller]
Controller -->|Call| Service[Service Layer]
end
subgraph Domain_Layer [Camada de Domínio]
Service -->|Orchestrate| DomainEntity["Domain Entity (Item)"]
Service -->|Use| QueryBuilder[Query Builder]
end
subgraph Infrastructure_Layer [Camada de Infraestrutura]
QueryBuilder -->|Build SQL| Repository[Repository]
Repository -->|Hydrate| Mapper[Data Mapper]
Repository -->|Execute SQL| MoodleDB[(Moodle Database)]
end
Repository -->|Return Entity| Service
Service -->|Return DTO/Result| Controller
Controller -->|Return Response| MoodleCore
Camadas da Aplicação¶
A arquitetura é dividida em 4 camadas principais. A intenção é manter dependências orientadas de fora para dentro, reduzindo acoplamento entre entrada, orquestração, domínio e infraestrutura.
1. Camada de Interface¶
Responsável por receber a entrada do usuário ou do Moodle e convertê-la em chamadas entendidas pela aplicação.
- Controllers: Recebem
Request, validam permissões (Auth) e delegam para Services. - API: Endpoints REST/Ajax que retornam JSON estrito.
- Console/CLI: Comandos de terminal para manutenção.
2. Camada de Aplicação¶
É a "cola" do sistema. Contém a lógica de orquestração, mas não a lógica de negócio pura.
- Services: Coordenam operações e casos de uso.
- Lifecycle de extensions: Gerencia registro, boot e integração entre módulos internos.
3. Camada de Domínio¶
O coração do software. Aqui residem regras, invariantes, contratos internos e representação dos dados. Esta camada evita depender de HTML, globais do Moodle e detalhes de persistência.
- Entities: Objetos com identidade única (ex:
item). São imutáveis ou controlados. - Value Objects: Objetos definidos por seus atributos (ex:
pagination,sorting). - Contracts e regras internas: Pontos de variação controlada e consistência de comportamento.
4. Camada de Infraestrutura (Infrastructure)¶
Implementa os detalhes técnicos para persistir e recuperar dados.
- Repositories: Traduzem comandos de domínio para SQL do Moodle.
- Mappers: Convertem
stdClass(banco) paraEntity(domínio). - Query Engine: Construtor fluente de SQL complexo.
Princípios de Engenharia¶
Para manter consistência entre framework, extensions e integrações, o MIDDAG adota princípios estruturais claros:
Imutabilidade (Immutability)¶
Objetos de Domínio e Query Builders são imutáveis. Métodos que alteram estado retornam novas instâncias (Wither Pattern).
- Por que? Previne efeitos colaterais indesejados onde um serviço altera um objeto que está sendo usado por outro.
Fail-Fast¶
Não silenciamos erros. Se uma classe é instanciada incorretamente ou um serviço não existe, lançamos uma coding_exception ou RuntimeException imediatamente.
- Por que? Erros silenciosos no Moodle (ex: null returns) causam bugs difíceis de rastrear em produção.
Injeção de Dependência (DI)¶
O container é o mecanismo oficial para resolver dependências estruturais do framework e das extensões que seguem seu modelo.
- Por que? Facilita testes, substituição controlada e previsibilidade de ciclo de vida.
Segregação de Interfaces (ISP)¶
Preferimos interfaces pequenas e específicas (extension_interface, event_service_interface) a classes gigantescas.
Padrões de Projeto Utilizados¶
| Padrão | Onde é usado | Objetivo |
|---|---|---|
| Facade | API pública estática do framework | Simplificar o acesso as interfaces públicas quando essa ergonomia for desejada. |
| Builder | Query, DiffBuilder |
Construir objetos complexos passo-a-passo de forma fluente. |
| Repository | item_repository |
Abstrair a camada de dados (SQL). |
| Data Mapper | item_mapper |
Converter dados relacionais em objetos. |
| Strategy | Extensions e pontos de variação | Permitir que comportamentos variados sejam plugados no núcleo. |