title: Camada: Infraestrutura description: Implementação técnica, detalhes de banco de dados, adapters Moodle e persistência organizada em famílias.
Camada: Infraestrutura¶
A Camada de Infraestrutura (framework\infrastructure) é onde os conceitos abstratos do framework ganham vida tecnológica. É aqui que o código "suja as mãos" com SQL, queries do Moodle, caching e integrações externas.
O que é¶
É a camada que implementa os Contracts definidos pelo Domínio e pela Aplicação. Se o Domínio diz "eu preciso salvar um Item", a Infraestrutura diz "eu vou salvar este dado na tabela middag_items usando o $DB do Moodle".
Principais componentes: * Repositories: Fronteira oficial de acesso a dados (SQL/MUC Cache). * Mappers: Tradutores que convertem registros brutos (stdClass) em Entities ricas do Domínio. * Moodle Adapters: Wrappers para APIs do Moodle (DB, User, Course, Config, Files). * Transaction Managers: Coordinadores de transações de banco de dados. * Authorizers: Implementação técnica das checagens de permissão.
Por que existe¶
O Moodle possui um banco de dados relacional e APIs procedurais globais. O local_middag vive e respira a partir desses recursos, mas não deve se fundir a eles. A Infraestrutura existe para:
1. Encapsulamento Técnica: Proteger as camadas superiores da complexidade do SQL e das mudanças de schema (install.xml).
2. Organização de Famílias: Centralizar o acesso a dados em quatro naturezas distintas de persistência.
3. Substitutibilidade: Permitir trocar uma implementação real por um "mock" durante testes unitários.
Sem esta camada, o código ficaria repleto de $DB->get_record('middag_items', ...) misturado com regras de negócio, tornando o sistema impossível de manter.
Famílias de Persistência¶
A infraestrutura organiza a persistência do framework em quatro famílias arquiteturais independentes, cada uma com seu próprio Repository e política de escrita:
graph TD
INF[Camada de Infraestrutura]
subgraph "Famílias de Persistência"
IT[Item Repository: Estado Atual]
RV[Revision Repository: Histórico Imutável]
AU[Audit Repository: Log de Rastreabilidade]
JB[Job Repository: Governança de Execução]
end
MAP[Mappers: SQL para Domínio]
MUC[Cache MUC Decorator]
MOD[Moodle $DB Boundary]
IT --> MAP
RV --> MAP
AU --> MOD
JB --> MOD
MAP --> MOD
IT -.-> MUC
- Item Repository: Gerencia o estado operacional atual (EAV: itens e metadados).
- Revision Repository: Gerencia snapshots históricos (revisões vinculadas ao item).
- Audit Repository: Gerencia o log de trilha de auditoria (quem, quando e o que mudou).
- Job Repository: Gerencia a governança e status de execuções assíncronas.
Decisões de design¶
- Mappers Fortes: O framework não usa ORMs genéricos (como Eloquent ou Doctrine) por ser acoplado ao Moodle. Usamos Mappers manuais que garantem a reconstrução perfeita do objeto de Domínio a partir do SQL híbrido (Item/Meta).
- Cache via Decorator: O cache (MUC - Moodle Universal Cache) é anexado aos repositories via Decorator. Isso significa que o repository original não "sabe" que está sendo cacheado, mantendo a responsabilidade única de persistência.
- Transação Graceful: O Moodle 4.x introduziu mudanças que dificultam o uso de transações com
Throwable. A infraestrutura fornece omoodle_transaction_managere o métodoexecute_gracefulpara contornar essa limitação técnica de forma segura.
O que não é¶
- Não contém Regra de Negócio: A Infraestrutura não decide se um status pode mudar; ela apenas realiza a mudança que a camada superior solicitou.
- Não contém Orquestração: Ela não decide "se salvar o item, disparar o signal". Ela apenas salva o item.
- Não é Lugar de Validação de Domínio: Dados salvos na infraestrutura já devem vir validados pelas camadas de Domínio e Aplicação.
Perspectiva para builders de extensions¶
Para extensions que precisam de persistência:
1. Use os Repositories do Core: Na maioria dos casos, seu TYPE de Item deve ser salvo via item_repository global. Não crie tabelas SQL locais sem necessidade arquitetural comprovada.
2. Injete Contracts: Seua extension deve depender de item_repository_interface, não da classe concreta item_repository. Isso mantém seu código testável e desacoplado.
3. Aproveite o MUC Cache: Ao usar o repository oficial, sua extension ganha automaticamente o suporte ao MUC Cache configurado pelo administrador do Moodle.
Exemplo ilustrativo¶
Implementação de um Repository na Infraestrutura (Mapeamento SQL -> Domínio):
namespace local_middag\framework\infrastructure\persistence\repository;
final class item_repository implements item_repository_interface {
public function find_by_id(int $id): item_entity {
// Acesso técnico ao Moodle $DB
$record = $this->db->get_record('middag_items', ['id' => $id]);
$metadata = $this->db->get_records('middag_itemmeta', ['itemid' => $id]);
// Tradução via Mapper (Fronteira Física -> Domínio)
return $this->mapper->map_to_entity($record, $metadata);
}
}
Neste exemplo, a item_repository absorve o custo de acessar duas tabelas diferentes e devolver um único objeto limpo para o restante do framework.