O Framework local_middag¶
O local_middag não é um plugin de negócio isolado, mas uma infraestrutura arquitetural reutilizável (framework) projetada para sustentar plugins e projetos avançados dentro do Moodle LMS. Ele resolve a complexidade de persistência flexível, gestão de dependências e reatividade, permitindo que as funcionalidades de negócio vivam de forma desacoplada em extensions.
O que é¶
O framework atua como uma fundação orientada a objetos que "envelopa" as APIs procedurais e globais do Moodle, oferecendo um ambiente com Injeção de Dependência (DI), persistência baseada em EAV (Entity-Attribute-Value), histórico imutável (Revision) e rastreabilidade nativa (Audit).
Ele é o motor central que coordena o ciclo de vida de múltiplos módulos pequenos e independentes, chamados de extensions, garantindo que uma falha em um módulo não comprometa a estabilidade de toda a plataforma.
Por que existe¶
Desenvolver plugins complexos diretamente sobre as APIs do Moodle frequentemente resulta em alto acoplamento, dificuldade de teste e rigidez no banco de dados. O local_middag foi criado para:
- Desacoplar o Domínio: Proteger a lógica de negócio das mudanças de versão do Moodle.
- Flexibilidade de Dados: Permitir a extensão de modelos de dados sem exigir alterações constantes no schema XMLDB (via EAV).
- Escalabilidade de Time: Permitir que diferentes funcionalidades sejam desenvolvidas em paralelo como extensions isoladas.
- Governança: Centralizar auditoria, autorização e tratamento de erros de forma transversal.
A alternativa descartada foi o desenvolvimento tradicional de plugins monolíticos, que se mostrou insustentável para o volume e a complexidade dos projetos MIDDAG.
Arquitetura de Camadas¶
O framework segue uma arquitetura em camadas onde a dependência flui sempre para dentro, em direção ao Domínio. O Moodle é tratado como um detalhe de infraestrutura na fronteira externa.
graph TD
subgraph "Zona de Consumo (Externa)"
EXT[Extensions]
TRD[Plugins Terceiros]
end
subgraph "API Pública (Estável)"
FAC[Facades]
CON_API[Contracts @api]
BASE[Classes-Base]
end
subgraph "Core do Framework"
APP[Aplicação: Casos de Uso]
DOM[Domínio: Regras e Invariantes]
INF[Infraestrutura: Repositories e DB]
KER[Kernel: Bootstrap e DI]
end
subgraph "Fronteira Moodle"
SUP[Support / Adapters]
MLD[Moodle LMS Core]
end
EXT --> FAC
EXT --> BASE
FAC --> APP
APP --> DOM
INF --> DOM
INF --> SUP
SUP --> MLD
KER --> APP
KER --> INF
Princípios de Engenharia¶
O design do framework é guiado por quatro pilares fundamentais:
- Imutabilidade por Padrão: Objetos de domínio e estados de persistência favorecem a imutabilidade. Alterações de estado geram novas instâncias (Wither Pattern), garantindo previsibilidade e histórico.
- Injeção de Dependência (DI): O container é o mecanismo oficial de criação de objetos. Services não devem ser instanciados com
newem fluxos estruturais, permitindo substituição e testabilidade. - Fail-Fast e Isolamento: O framework prefere falhar explicitamente do que continuar em estado inconsistente. O boot de extensions é isolado; se uma falha, as demais continuam.
- Segregação de Interface (ISP): Contracts são desenhados para serem pequenos e específicos. Um consumidor não deve ser forçado a depender de métodos que não utiliza.
Estrutura da Documentação¶
Navegue pelos conceitos do framework seguindo a tabela abaixo:
| Documento | O que cobre | Público-alvo |
|---|---|---|
| Glossário | Definições concisas dos termos canônicos (Item, Signal, Job, etc.) | Todos |
| Camada Kernel | Sequência de boot, compilação do container e ciclo de vida | Core Developers |
| Conceito: Item | A unidade canônica de persistência flexível baseada em EAV | Extension Builders |
| Audit & Revision | Como o framework garante rastreabilidade e histórico imutável | Extension Builders |
| Signals & Hooks | O sistema reativo de ocorrências e transformação de dados | Extension Builders |
| API Pública & Zonas | Regras de estabilidade, anotações @api e fronteiras | Todos |
| Infraestrutura | Persistência, Repositories e Adapters para o Moodle | Core Developers |
O que não é¶
- Não é um Repository de Negócio: O core do framework não contém regras de "Vendas", "Cursos" ou "Usuários". Ele fornece a estrutura para que as extensions implementem isso.
- Não substitui o Moodle: Ele vive dentro do Moodle e consome suas APIs. Não é um CMS ou LMS independente.
- Não é um ORM Genérico: Embora gerencie persistência, ele é otimizado para o modelo de
Item/Metado MIDDAG, não para mapear qualquer tabela SQL arbitrária.
Perspectiva para Extension Builders¶
Para quem constrói extensions, o framework deve ser visto como um provedor de serviços e contratos. Você não consome as classes internas do kernel, mas sim as Facades públicas e as Classes-Base.
Ao herdar de local_middag\base\extension, sua classe ganha acesso automático ao lifecycle de register() e boot(), permitindo que você injete suas dependências no container global sem se preocupar com a ordem de carregamento do Moodle.
Exemplo Ilustrativo¶
Consumo de uma funcionalidade do framework via Facade e Contract (o caminho recomendado para estabilidade):
// No ponto de entrada (Controller ou Hook)
use local_middag\facade\item; // Entrada pública estática
use local_middag\framework\contract\repository\item_repository_interface; // Contract @api
// Uso via Facade (Ergonomia simples)
$item_data = item::find_by_id(123);
// Uso via DI (Dentro de um Service da Extension)
final class my_service {
public function __construct(
private item_repository_interface $repository // Injetado pelo Container
) {}
public function process(int $id) {
$item = $this->repository->find_by_id($id);
// ...
}
}