Pular para conteúdo

Camada de Domínio (Domain Layer)

A Camada de Domínio é onde residem as regras de negócio, a representação dos dados e a lógica fundamental do MIDDAG.

Diferente do desenvolvimento tradicional em Moodle (que utiliza stdClass genéricos e arrays soltos), o MIDDAG utiliza Entidades Ricas e Objetos de Valor (Value Objects). Esta camada é completamente agnóstica à infraestrutura: ela não sabe salvar no banco de dados, não sabe gerar HTML e não conhece o conceito de HTTP Request.


Entidade Base: Item

A classe fundamental do sistema é local_middag\core\domain\entity\item.

Todo dado gerenciado pelo plugin (seja um Curso agrupado, uma Trilha de aprendizagem ou um registro de Matrícula) é, em essência, um item.

Estrutura de Classes

O diagrama abaixo ilustra como as funcionalidades são compostas através de Traits (Concerns), mantendo a herança limpa para as extensões.

classDiagram
    class Item {
        -int id
        -string type
        -string status
        +get_id()
        +get_type()
        +to_array()
    }

    class HasMetadata {
        <>
        +get_meta(key)
        +with_meta(key, val)
    }

    class HasRelations {
        <>
        +get_relation(name)
        +set_relation(name, obj)
    }

    class HasStatus {
        <>
        +is_active()
        +is_draft()
    }

    class CourseItem {
        +TYPE = 'course'
        +get_start_date()
    }

    Item ..|> HasMetadata : uses
    Item ..|> HasRelations : uses
    Item ..|> HasStatus : uses
    Item <|-- CourseItem : extends

Imutabilidade e Padrão "Wither"

Uma das decisões arquiteturais mais importantes do MIDDAG é que Entidades de Domínio são Imutáveis.

Isso significa que, uma vez criado, um objeto item nunca muda seu estado interno. Você não encontrará métodos set_fullname() que alteram a propriedade $this->fullname.

Por que Imutabilidade?

Em sistemas complexos com muitos Eventos e Hooks, objetos mutáveis causam efeitos colaterais imprevisíveis (ex: um listener altera o ID do curso e quebra o resto do processo). Com objetos imutáveis, temos certeza de que os dados são consistentes do início ao fim do ciclo de vida.

Como modificar dados?

Utilizamos o padrão Wither (semelhante ao PSR-7). Métodos with_ clonam o objeto atual, aplicam a mudança na cópia e retornam a nova instância.

Exemplo:

<?php

$original = $repository->find(1); // Item "Antigo"

// O original permanece intacto. $atualizado é um novo objeto na memória.
$atualizado = $original
    ->with_fullname('Novo Nome')
    ->with_status('published');

// Persistência explícita necessária
$repository->save($atualizado); 

Metadados (Metadata)

O Moodle possui tabelas com colunas fixas. O MIDDAG resolve a necessidade de campos dinâmicos (ex: "Data de Validade", "SKU", "Professor Responsável") através do Trait has_metadata.

Os metadados são carregados automaticamente (Eager Loading) pelos repositórios, evitando o problema de N+1 Queries.

<?php

// Acesso seguro (retorna null se não existir)
$sku = $item->get_meta('product_sku');

// Modificação (retorna clone)
$newItem = $item->with_meta('product_sku', 'PROD-123');

DTOs vs Entidades

Para garantir a imutabilidade das Entidades, utilizamos DTOs (Data Transfer Objects) para transportar dados de entrada (Formulários, API) até o Domínio.

Característica Entity (item) DTO (item_dto)
Objetivo Representar um dado válido e consistente do negócio. Transportar dados brutos (input) entre camadas.
Mutabilidade Imutável. Mutável (Público).
Origem Nascem no Repositório (banco) ou Factory. Nascem no Controller ou API.
Regras Garante consistência (ex: visibilidade >= 0). Não possui validação de negócio.

Fluxo de Atualização

  1. O Controller recebe o Request e cria um item_dto mutável.
  2. O Service valida o DTO.
  3. O Repository recebe o DTO, aplica sobre a Entidade original (gerando uma nova Entidade) e salva no banco.

Registry de Tipos (item_types)

Como o MIDDAG lida com polimorfismo (vários tipos de itens na mesma tabela), precisamos de um registro central que diga ao sistema qual classe PHP usar para cada string type no banco de dados.

Isso é gerenciado pela classe local_middag\core\domain\registry\item_types.

Exemplo de Registro (no bootstrap.php de uma extensão):

<?php

use local_middag\core\domain\registry\item_types;
use local_middag\extensions\learning\domain\course_item;

item_types::register('course', course_item::class);

Quando o repositório busca um registro onde type = 'course', ele automaticamente hidrata uma instância de course_item em vez de um item genérico.