Я работаю над дизайном программного обеспечения, и я застрял между отсутствием представления о том, что я делаю, и ощущением, будто я заново изобретаю колесо.
Моя ситуацияследующее: я разрабатываю научную утилиту с интерактивным интерфейсом.Пользовательский ввод должен вызывать визуальную обратную связь (дух), некоторую ее непосредственно, т. Е. Редактировать геометрию домена, а часть - как можно скорее, не блокируя взаимодействие с пользователем, скажем, путем решения некоторого PDE в указанном домене.
Если я нарисую диаграмму всех операций, которые мне нужно выполнить, я получу этот довольно плотный график, предоставляющий все виды возможностей для параллелизма и кеширования / повторного использования частичных результатов.Поэтому я хочу, прежде всего, использовать этот параллелизм прозрачным способом (выбранные подзадачи выполняются в отдельных процессах, в результате чего внешне «присоединяются» нижестоящие задачи, ожидающие готовности всех своих входных данных), плюс требуется только пересчитывать те входные ветви, которыена самом деле их входные данные изменились
pyutilib.workflow, кажется, наиболее близок к тому, что я ищу, за исключением, конечно, того, что это не так (кажется, для начала не выполнялось никаких подпроцесс).Это кажется довольно разочаровывающим;хотя я не инженер по программному обеспечению, я говорю, что я не прошу здесь ничего сумасшедшего.
Еще один сложный фактор - это желаемая тесная интеграция с пользовательским интерфейсом, которую другие научные решения для рабочих процессов кажутся не разработанными.обрабатывать.Например, я хотел бы передать событие перетаскивания через узел преобразования для дальнейшей обработки.Узел преобразования имеет два входа;порт ввода состояния аффинного преобразования и класс pointset, который знает, что с ним делать.Если входной порт аффинного преобразования «грязный» (ожидает обновления своих зависимостей), событие следует удерживать до тех пор, пока оно не станет доступным.Но когда событие прошло узел, порт входа события должен быть помечен как обработанный, поэтому он не обновляется, когда аффинное преобразование изменяется из-за дальнейшего ввода данных пользователем.Это просто пример одной из многих возникающих проблем, которые я не вижу, чтобы меня нигде не интересовали.Или что делать, когда долгожданная ветвь, соединяющая ветвления, получает новые входные данные, когда она находится в процессе обработки предыдущего ввода.
Итак, мой вопрос: вам не знакомы некоторые хорошие книги / статьи ошаблоны проектирования рабочего процесса, которые я должен прочитать?Или я пытаюсь втиснуть квадратный колышек в круглое отверстие, и вы знаете совершенно другой шаблон дизайна, о котором я должен знать?Или пакет python, который делает то, что я хочу, независимо от модных слов, в которые он одет?
Я использовал собственное решение поверх enthought.traits, но я тоже не совсем доволен этимКак это похоже на грубое и дрянное изобретение колеса.За исключением того, что я не могу найти какие-либо колеса в Интернете.
ПРИМЕЧАНИЕ. Я не ищу веб-фреймворков, графических дизайнеров рабочих процессов или каких-либо специальных инструментов.Просто концептуально что-то вроде pyutilib.workflow, но включающее в себя документацию и набор функций, с которыми я могу работать.
# # # РЕДАКТИРОВАТЬ: это то место, где я нахожусь после продолжительного чтения и размышлений над проблемой: # # #
Требования, предъявляемые к «архитектуре рабочего процесса», слишком разнообразны, чтобы существовать один ботинок, который подходит всем.Хотите ли вы тесную интеграцию с дисковым хранилищем, тесную интеграцию с веб-фреймворками, асинхронность, сочетание пользовательской логики конечного автомата для распределения задач?Все они являются действительными требованиями, и они в значительной степени несовместимы или создают бессмысленные миксы.
Однако не все потеряно. Поиск универсальной системы рабочего процесса для решения произвольной проблемы - это все равно, что искать универсальный итератор для решения вашей пользовательской задачи итерации. Итераторы в первую очередь не для повторного использования; Вы не можете повторно использовать итератор красно-черного дерева, чтобы перебрать свой тензор. Их сила заключается в четком разделении интересов и определении единого интерфейса.
То, что я ищу (и начал писать сам, будет довольно круто) будет выглядеть так: в его основе лежит общий не зависящий от реализации мини-язык объявления рабочих процессов, основанный на декораторах и некоторых метаданных -magic, чтобы преобразовать оператор, подобный приведенному ниже, в объявление рабочего процесса, содержащее всю необходимую информацию:
@composite_task(inputs(x=Int), outputs(z=Float))
class mycompositetask:
@task(inputs(x=Int), outputs(y=Float))
def mytask1(x):
return outputs( y = x*2 )
@task(inputs(x=Int, y=Float), outputs(z=Float))
def mytask2(x, y):
return outputs( z = x+y )
mytask1.y = mytask2.y #redundant, but for illustration; inputs/outputs matching in name and metadata autoconnect
То, что возвращают декораторы, это задача / compositetask / workflow объявление класс. Вместо просто ограничений типов, другие метаданные, необходимые для данного типа рабочего процесса, легко добавляются в синтаксис.
Теперь это краткое и питонное объявление может быть передано в фабрику экземпляров рабочего процесса, которая возвращает фактический экземпляр рабочего процесса. Этот язык объявлений является довольно общим и, вероятно, не должен сильно меняться в зависимости от различных требований к дизайну, но такая фабрика создания рабочих процессов полностью соответствует вашим требованиям / воображению к дизайну, за исключением общего интерфейса для доставки / извлечения ввода / вывода.
В простейшем воплощении wed имеет что-то вроде:
wf = workflow_factory(mycompositetask)
wf.z = lambda result: print result #register callback on z-output socket
wf.x = 1 #feed data into x input-socket
где wf - тривиальный экземпляр рабочего процесса, который ничего не делает, кроме как связывает все содержащиеся в одной функции тела вместе в одном потоке, как только все входы связаны. Довольно многословный способ связать две функции, но он иллюстрирует идею, и он уже достигает цели разделения задачи сохранения определения потока информации в центральном месте, а не распределения по всем классам, которые, скорее всего, не имеют ничего общего с делать с этим.
Это более или менее функциональность, которую я реализовал до сих пор, но это означает, что я могу продолжать работать над своим проектом и в свое время добавить поддержку для более интересных фабрик экземпляров рабочих процессов. Например, я имею в виду анализ графика зависимостей для определения разветвлений и объединений и отслеживание активности, генерируемой каждым входом, предоставленным на уровне экземпляра рабочего процесса, для элегантной балансировки нагрузки и отмены эффектов определенных потерянных входных данных. их актуальность, но ресурсы все еще не исчерпаны.
В любом случае, я думаю, что проект разделения декларации рабочего процесса, определения интерфейса и реализации реализации является стоящим усилием. Как только у меня будет работать несколько нетривиальных типов экземпляров рабочих процессов (мне нужно по крайней мере два для проекта, над которым я работаю, я понял *), я надеюсь найти время, чтобы опубликовать это как публичный проект, потому что, несмотря на то, что Разнообразие требований к проектированию в системах документооборота, с учетом этой основы, значительно упрощает реализацию ваших собственных требований. И вместо единой раздутой структуры рабочего процесса вокруг такого ядра может вырасти швейцарский армейский нож легко заменяемых пользовательских решений.
* Понимая, что мне нужно разделить мой код на два разных типа экземпляров рабочего процесса, а не пытаться объединить все мои требования к дизайну в одно решение, я превратил квадратный колышек и круглое отверстие, которые у меня в голове, в два совершенно взаимодополняющих отверстия и колышка .