Шаблон проектирования для перевода нескольких форматов данных из нескольких источников в один формат

Я работаю в компании, которая имеет несколько веб-сайтов, и существующая инфраструктура... ну, ужасно.

Прямо сейчас у каждого магазина есть своя таблица, которая различается по структуре. Это быстро становится проблемой (если это еще не было).

Поэтому мне нужно найти способ принимать заказы из нескольких каналов, форматировать их в единый, унифицированный способ, сохранять их с нашей стороны и переводить обратно в формат, ожидаемый API хранилища (который может быть любым: от RESTful JSON до МЫЛО).

Моей первоначальной реакцией на интуицию была смесь шаблонов фабрики, посетителя и строителя (плюс некоторый умный полиморфизм), но она стала слишком сложной слишком быстро. Прежде чем я пойду и закодирую себя в углу с решением, которое может быть неоптимальным, обслуживаемым или расширяемым, есть ли шаблон или набор шаблонов, которые были бы более эффективными?

В принципе, я думаю, что это будет что-то вроде:

Source -> Translator -> Our Format
Our Format -> Translator -> Source

Мне не нужен переводчик, чтобы фактически действовать на основе данных. Все, за что он должен отвечать, - это получить его в правильном формате, и мы можем получить его из пункта А в пункт Б (и наоборот).

Несколько предположений о системе:

  1. Формат с нашей стороны вряд ли изменится, и поэтому наши объекты вряд ли изменятся
  2. Когда данные переведены обратно в исходный источник, мы можем предположить, что все, что требуется, будет там. Фактическое поведение для исходящих запросов является небольшим, сфокусированным и четко определенным

3 ответа

Адаптер Pattern ваш друг. Допустим, у вас есть унаследованный класс Customer.

public class CustomerLegacy
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public DateTime Birthday { get; set; }
}

Первое, что вы можете сделать, это извлечь этот класс. Этот шаг не является обязательным, но он делает новый класс тестируемым. Итак, у вас будет интерфейс ICustomerLegacy, который выглядит как показано ниже.

public interface ICustomerLegacy
{
    string FirstName { get; set; }

    string LastName { get; set; }

    DateTime Birthday { get; set; }
}

Затем рефакторинг CustomerLegacy класс для реализации нового интерфейса.

public class CustomerLegacy
    : ICustomerLegacy

Следующим шагом является создание адаптера, который принимает ICustomerLegacy в качестве аргумента конструктора. Вы можете добавить новые свойства для удовлетворения ваших потребностей.

public class CustomerAdapter
{
    private readonly ICustomerLegacy customer;

    public CustomerAdapter(ICustomerLegacy customer)
    {
        this.customer = customer;
    }

    public string FullName
    {
        get
        {
            return this.customer.FirstName + " " + this.customer.LastName;
        }
    }

    public int Age
    {
        get
        {
            return DateTime.UtcNow.Year - this.customer.Birthday.Year;
        }
        set
        {
            // your logic here.
        }
    }

    public void Save()
    {
        //this.customer.DoSomething();
    }
}

Как видите, Adapter Pattern может помочь вам реорганизовать существующий продукт, сделать его тестируемым и привести в порядок устаревший код в одном месте.

Насколько я вижу, вы должны быть в состоянии использовать простой подход для решения этой ситуации, с фабрикой и интерфейсом,

class IStore
{
   void Place(Order order);

   ....other methods
}

class AmazonStore : IStore
{
   ...implement methods
}

class EbayStore : IStore
{
    ...implement methods
}

Здесь объект Order должен быть переведен в конкретный API внутри фактической реализации, а также наоборот для любых методов, извлекающих данные.

и затем фабрика может использоваться для создания соответствующего хранилища на основе либо константы, либо на основе Enum.

В одной из моих предыдущих компаний мы работали над аналогичным проектом. Мы принимаем архитектуру труб и фильтров.

Используйте архитектурный стиль "Трубы и фильтры", чтобы разделить большую задачу обработки на последовательность меньших независимых шагов обработки ("Фильтры"), которые связаны каналами ("Трубы").

Каждый фильтр предоставляет очень простой интерфейс: он получает сообщения во входящем канале, обрабатывает сообщение и публикует результаты в исходящем канале. Канал соединяет один фильтр с другим, отправляя выходные сообщения от одного фильтра другому. Поскольку все компоненты используют один и тот же внешний интерфейс, их можно объединить в разные решения, подключив компоненты к разным каналам. Мы можем добавить новые фильтры, опустить существующие или переставить их в новую последовательность - и все это без необходимости менять сами фильтры. Соединение между фильтром и трубой иногда называют портом. В базовой форме каждый компонент фильтра имеет один входной порт и один выходной порт.

Думайте об этом как о своем Source это насос, ваш Translator это фильтр. Любая функциональность, добавленная в фильтры, будет основана на соответствующем бизнес-домене. Большая картина выглядит так:

введите описание изображения здесь

Другие вопросы по тегам