Pular para conteúdo

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:

  1. Desacoplar o Domínio: Proteger a lógica de negócio das mudanças de versão do Moodle.
  2. Flexibilidade de Dados: Permitir a extensão de modelos de dados sem exigir alterações constantes no schema XMLDB (via EAV).
  3. Escalabilidade de Time: Permitir que diferentes funcionalidades sejam desenvolvidas em paralelo como extensions isoladas.
  4. 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 new em 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 é

  1. 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.
  2. Não substitui o Moodle: Ele vive dentro do Moodle e consome suas APIs. Não é um CMS ou LMS independente.
  3. Não é um ORM Genérico: Embora gerencie persistência, ele é otimizado para o modelo de Item/Meta do 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);
        // ...
    }
}