Pular para conteúdo

Estabilidade e Versionamento da API Pública

Esta página detalha a direção arquitetural esperada pelo ADR-0010.

O objetivo é separar com clareza:

  • API pública estável: exige compatibilidade e migration path;
  • camada de extensão controlada: também exige cuidado, mas com escopo guiado;
  • interno por padrão: pode mudar sem garantia externa;
  • ciclo rc: já segue a direção arquitetural, mas ainda não tem o mesmo rigor de congelamento do primeiro release estável.

Regra principal

A política rígida de compatibilidade pública passa a valer plenamente a partir do primeiro release estável.

Durante o ciclo rc, o projeto já deve respeitar a direção dos ADRs, mas ainda pode fazer refatorações profundas quando necessário para fechar a arquitetura.

O que entra na API estável do core

  • facade pública do core;
  • contract @api;
  • classe-base;
  • hook canônico documentado como público;
  • payload público documentado;
  • signal explicitamente promovido como público.

Exemplo de deprecation em facade pública

<?php

/**
 * @api
 * @deprecated since 5.1.0 use middag::dispatch() instead
 */
final class legacy_dispatch_facade extends facade
{
}

Leitura prática:

  • continua funcionando no minor;
  • já orienta a migração;
  • só pode sumir na próxima major.

Exemplo de hook público estável

<?php

middag::add_action('middag/extension/ecommerce/order_processed', static function (
    \local_middag\extensions\ecommerce\hook_payload\order_processed_payload $payload
): void {
    // consumo estável
});

Se esse hook for oficialmente documentado como público:

  • o nome canônico entra na política de compatibilidade;
  • o payload documentado também entra;
  • mudar ambos exige deprecation e migration path.

Exemplo de signal interno sem garantia

<?php

namespace local_middag\extensions\ecommerce\signal;

final class order_projection_rebuilt_signal
{
}

Se esse signal não for promovido explicitamente como público, ele continua interno por padrão.

Exemplo de facade pública de extension

<?php

namespace local_middag\extensions\sentry\facade;

final class sentry extends \local_middag\base\facade
{
    public static function get_facade_accessor(): string
    {
        return \local_middag\extensions\sentry\service\sentry_service::class;
    }
}

Essa facade pode ser pública e estável, mas:

  • a governança dela pertence à extension sentry;
  • o core do local_middag não assume compatibilidade sobre ela.

O que não entra automaticamente na estabilidade

  • classe interna por localização;
  • signal interno não promovido;
  • hook não documentado;
  • mapping interno entre signal e hook derivado;
  • storage físico, XMLDB e schema interno.

Regra prática

  • quero ponto estável do core -> documentar como público e anotar com @api quando aplicável
  • quero evoluir sem quebrar -> usar deprecation + migration path
  • quero manter algo livre para refactor -> deixar interno e documentar como tal
  • quero interface pública de extension -> a própria extension governa sua estabilidade