Добавьте дополнительные аргументы к внедренным сервисам, чтобы они были готовы к работе - PullRequest
0 голосов
/ 04 июля 2019

Мне нужен сканер, который находит документы из одной системы и сохраняет их для последующей синхронизации. Искатель создается ServiceContainer, который разрешает все зависимости в конструкторе искателя. Может быть, мое понимание или подход к моей архитектуре совершенно неверно, но я постараюсь описать свою структуру. Мои так называемые «сервисы» - это на самом деле просто классы, зарегистрированные как синглтоны в ServiceContainer. Это решение было принято для обеспечения того, чтобы «разделение интересов» не нарушалось.

Итак, сканер зависит от:

  • SOAP-сервис для подключения к исходной системе
  • a "NodeService", чтобы сообщить сканеру, возвращены ли данные (узел) из SOAP это либо документ, либо каталог (возможно больше типов, поэтому здесь необходимо явное сравнение)
  • a DocumentService, который выполняет работу с любым возвращенным документом.

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

Для этого «DocumentService» снова зависит от двух сервисов "MetaDataService" и "DocumentVersionService".

Метод обхода сканера выполняется рекурсивно, и на каждой итерации возвращаемый «узел» передается в «NodeService» и «DocumentService», которые были внедрены в конструктор сканеров.

// CRAWLER
function __construct(
        SOAPService $css,
        NodeService $ncs,
        DocumentService $ds
    ) {
        $this->css = $css;
        $this->node = $ncs;
        $this->document = $ds;
    }

    public function init($entryPoint)
    {
        $this->setEntryPoint($entryPoint);
        $this->setDocType();
        if ($this->isNotRunning())
        {
            $this->currentProcess = Crawl::create(['doc_type' => $this->docType]);
            $this->processingTime = microtime(true);
            Document::where('document_type', $this->docType)->update(['seen' => 0]);
        }
        else
        {
            throw new CrawlerAlreadyRunningException();
        }
    }

    public function crawlDirectory($path = array())
    {
        if (empty($path)) {
            $path[] = $this->docType;
        }
        $children = $this->css->getChildNodes($this->entryPoint);
        foreach ($children as $child)
        {
            $this->node->set($child);
            if($this->node->isDirectory())
            {
                $newPath = array_merge($path, array($child->Name));
                $this->entryPoint = $child->ID;
                $this->crawlDirectory($newPath);
            }
            else if ($this->node->isDocument())
            {
                $this->document->set($child);
                $this->document->toIndex($this->docType, $path);

                if ($this->document->isNew())
                {
                    $this->document->toQueue('new');
                }
                if ($this->document->hasChangedMeta())
                {
                    $this->document->toQueue('meta');
                }
                if ($this->document->hasNewVersion())
                {
                    $this->document->toQueue('version');
                }
            }
        }
    }

DocumentService знает, где в «узле» хранится информация о версии и метаданных, и отправляет их в следующие внедренные службы, называемые «MetaDataService» и «DocumentVersionService». См. «SoC» выше, «DocumentService» не должен знать, как на самом деле структурируются данные для версий или метаданных или как их извлекать (и если есть какие-либо другие правила, которые должны применяться). Он только выбрасывает кучу данных в другой сервис и получает результат. В соответствии с этим, может быть, даже сбор соответствующих данных является нарушением SOC вместо того, чтобы толкать весь «узел» в чересстрочные сервисы.

class DocumentService
{
    private $documentVersion;
    private $currentDocument;
    private $documentMeta;
    private $attributeMap;
    private $versionAttributes;
    private $possibleArrays;
    private $sync;

    function __construct(
        DocumentVersionService $dvs,
        MetaDataService $mds
    )
    {
        $this->documentVersion = $dvs;
        $this->documentMeta = $mds;
        $this->attributeMap = config('soap.attributeMaps.documents.attributes');
        $this->versionAttributes = config('soap.attributeMaps.documents.version');
        $this->sync = false;
    }

    public function set($node)
    {
        $this->node = $node;
        $this->documentVersion->set($node->VersionInfo->Versions);
        $this->documentMeta->set($node->Metadata->AttributeGroups);
        $this->initDocument();
    }

Поскольку эти службы внедряются через конструктор, я не могу передать никакие дополнительные аргументы этим службам. Для этого я добавил метод «set», чтобы привести соответствующий сервис в правильное состояние для операций текущей итерации.

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

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

Я думал о том, чтобы сделать все методы в этих службах закрытыми и вызывать их косвенно с помощью волшебного __call () - mehtod. Только метод set () будет общедоступным. Затем в методе __call () я могу убедиться, что служба готова выполнить запрошенное действие.

Facepalm
Сейчас, когда я пишу это, я понимаю, что даже этот подход не может удовлетворить мои требования, чтобы гарантировать правильные текущие данные в каждой итерации. Я мог только проверить, присутствуют ли какие-либо данные в экземпляре службы. Другими словами, если это было инициализировано когда-либо прежде.

Заключение
Я думаю, что мне не хватает некоторых очень фундаментальных аспектов в этой архитектуре. Я был бы очень рад, если бы кто-нибудь мог дать мне совет, как это будет сделано "правильным образом".

...