Внутренние и Публичные API в Модульных Монолитах. Окончание
Начало
Раскрытие информации
Самая сложная часть проектирования публичных API — решить, что раскрывать:
1) Начните с того, что нет ничего публичного,
2) Открывайте только то, что другим модулям действительно нужно,
3) Проектируйте API вокруг вариантов использования, а не данных.
Вот как это выглядит на практике:
public interface IOrdersModule
{
// Не раскрываем CRUD-операции
// Раскрываем варианты использования
Task<ShippingOrder> GetShippingOrder(string id);
Task<PaymentOrder> GetPaymentOrder(string id);
Task<OrderSummary> GetOrderSummary(string id);
}
Защита данных модуля
Также нужно защитить данные модуля. Вот несколько советов.
1. Отдельные схемы: каждый модуль получает свою схему БД.
CREATE SCHEMA Orders;
CREATE SCHEMA Shipping;
-- Каждый модуль имеет доступ только к своей схеме
CREATE USER OrdersUser WITH DEFAULT_SCHEMA = Orders;
GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA Orders TO OrdersUser;
-- … Аналогично для схемы Shipping
Также мы блокируем доступ пользователя к изменению схемы, разрешив только чтение и запись данных.
2. Различные строки подключения: каждый модуль получает своего пользователя БД с соответствующей строкой подключения.
builder.Services.AddDbContext<OrdersDbContext>(
opts =>
opts.UseSqlServer(
builder.Configuration
.GetConnectionString("OrdersConnection")));
builder.Services.AddDbContext<ShippingDbContext>(
opts =>
opts.UseSqlServer(
builder.Configuration
.GetConnectionString("ShippingConnection")));
См. также «Использование Нескольких Контекстов EF Core»
3. Модели для чтения: специальная модель только для чтения для использования из других модулей.
internal class Order
{
// Полная внутренняя модель
}
public class ShippingOrder
{
// Публичное DTO для модуля Shipping
public string Id { get; init; }
public Address ShippingAddress { get; init; }
public List<ShippingItem> Items { get; init; }
}
Итого
Открытые API в модульных монолитах предназначены не для предотвращения связанности, а для её контроля. Каждый открытый API — это контракт, который гласит: «Да, эти модули связаны, и именно так они зависят друг от друга».
Цель не в том, чтобы устранить зависимости между модулями. Цель в том, чтобы сделать их явными, контролируемыми и поддерживаемыми.
Источник: https://www.milanjovanovic.tech/blog/internal-vs-public-apis-in-modular-monoliths