Я работаю над частью программного обеспечения, и я застрял между тем, что не знаю, что я делаю, и чувствую, что я изобретаю колесо.
Моя ситуация такова: я разрабатываю научную утилиту с интерактивным интерфейсом. Пользовательский ввод должен инициировать визуальную обратную связь (duh), некоторые из них непосредственно, то есть редактирование геометрии домена и некоторые из них как можно скорее, без блокировки взаимодействия с пользователем, скажем, при решении некоторых PDE по указанному домену.
Если я вычеркиваю диаграмму всех операций, которые мне нужно выполнить, я получаю этот довольно ужасный граф, раскрывая все возможности для parallelism и кеширования/повторного использования частичных результатов. Так что я хочу, прежде всего, использовать этот parallelism прозрачным способом (выбранные подзадачи, выполняемые в отдельных процессах, результаты изначально "присоединяются" к нисходящим задачам, ожидая, что все их входы будут готовы), плюс нужно только пересчитать эти входные данные ветки, которые на самом деле имеют свой вход, изменились
pyutilib.workflow, похоже, ближе всего к тому, что я ищу, за исключением того, что это не так (для начала не требуется никаких подпроцессов). Это кажется довольно разочаровывающим; в то время как я не инженер-программист, я говорю, что я не прошу ничего сумасшедшего здесь.
Другим осложняющим фактором является сложная интеграция с пользовательским интерфейсом, которую я желаю, какие другие решения для научного рабочего процесса, похоже, не предназначены для обработки. Например, я хотел бы передать событие перетаскивания через преобразование node для дальнейшей обработки. Преобразование node имеет два входа; входной порт состояния аффинного преобразования и класс точек, который знает, что с ним делать. Если входной порт аффинного преобразования "грязный" (ожидание обновления его зависимостей), событие следует удерживать до тех пор, пока оно не станет доступным. Но когда событие прошло node, порт eventinput должен быть помечен как обработанный, поэтому он не отказывается, когда аффинное преобразование изменяется из-за дальнейшего ввода пользователем. Это всего лишь пример одной из многих проблем, которые возникают из-за того, что я не вижу, чтобы меня обращали куда угодно. Или, что делать, когда длинная ветвь для соединения с вилкой получает новый вход, когда она находится в середине хрустания предыдущего ввода.
Итак, мой вопрос: знаете ли вы, что знаете хорошие книги/статьи о шаблонах проектирования рабочего процесса, которые я должен прочитать? Или я пытаюсь поместить квадратную привязку в круглое отверстие, и вы знаете совершенно другую модель дизайна, о которой я должен знать? Или пакет python, который делает то, что я хочу, независимо от того, что он надет на одежде?
Ive покатался по собственному решению на вершине enthought.traits, но я не совсем этому доволен, так как это похоже на грубое и дрянное переосмысление колеса. Кроме того, что я не могу найти какие-либо колеса в любом месте в Интернете.
ПРИМЕЧАНИЕ. Я не ищу webframeworks, графических дизайнеров рабочих процессов или каких-либо специальных инструментов. Просто что-то концептуально, как pyutilib.workflow, но включая документацию и набор функций, с которыми я могу работать.
# # # EDIT: здесь я нахожусь после более глубокого чтения и размышлений по этому вопросу: # # #
Требования, которые можно применить к "архитектуре рабочего процесса", слишком разнообразны, чтобы быть единственным обувью, который подходит всем. Вы хотите жесткую интеграцию с дисковым хранилищем, плотную интеграцию с веб-фреймворками, асинхронность, смешивание в пользовательской логике конечных автоматов для отправки задачи? Все они являются действительными требованиями, и они в значительной степени несовместимы или делают для бессмысленных смесей.
Однако не все потеряно. Поиск общей системы документооборота для решения произвольной проблемы - это поиск универсального итератора для решения вашей проблемы с итерацией. Итераторы не относятся в первую очередь к повторному использованию; вы не можете повторно использовать свой итератор красно-черного дерева для повторения вашего тензора. Их сила заключается в четком разделении проблем и определении однородного интерфейса.
То, что я ищу (и начал писать сам, это будет довольно круто), будет выглядеть так: на его основе представлен общий язык-декларация с использованием агностического описания рабочего процесса, основанный на декораторах и некоторых мета -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. Вместо просто ограничений типов другие метаданные, необходимые для типа рабочего процесса, легко добавляются к синтаксису.
Теперь это краткое и питоновское объявление может быть отправлено в экземпляр рабочего процесса factory, который возвращает экземпляр фактического рабочего процесса. Этот язык декларации довольно общий и, вероятно, не должен сильно меняться между различными требованиями к дизайну, но такой экземпляр рабочего процесса factory полностью соответствует вашим требованиям к дизайну/воображению, кроме общего интерфейса для доставки/получения ввода/вывода.
В своем простейшем воплощении 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 - тривиальный экземпляр рабочего процесса, который ничего не делает, кроме цепочки всех содержащихся тел функции в одном и том же потоке, как только все входы связаны. Довольно сложный способ связать две функции, но он иллюстрирует эту идею, и она уже достигает цели разделения вопроса о сохранении определения потока информации в центральном месте, а не распространении по всем классам, которые скорее не будут иметь ничего общего с сделайте с ним.
Это более или менее функциональность, которую я реализовал до сих пор, но это означает, что я могу продолжить работу над моим проектом и в свое время неплохо добавить поддержку для фабрик экземпляров бизнес-процессов fancier. Например, я собираюсь проанализировать график зависимостей для идентификации вилок и объединений и отслеживать активность, генерируемую каждым вводом, предоставленным на уровне экземпляра рабочего процесса, для элегантной балансировки нагрузки и отмены эффектов от отдельных потерянных данных их актуальность, но все еще остаются ресурсами для лечения.
В любом случае, я думаю, что проект разделения декларации рабочего процесса, определения интерфейса и реализации экземпляра - это стоящее усилие. Когда у меня есть несколько нетривиальных типов экземпляров рабочего процесса, которые работают хорошо (мне нужен как минимум два проекта, над которыми я работаю, я понял *), я надеюсь найти время, чтобы опубликовать это как публичный проект, потому что, несмотря на разнообразие требований к дизайну в системах документооборота, покрывая эту основу, значительно упрощает реализацию ваших собственных конкретных требований. И вместо единой раздутой структуры рабочего процесса, швейцарский армейский нож с легко переключаемыми пользовательскими решениями мог расти вокруг такого ядра.
* осознавая, что мне нужно разделить мой код на два разных типа экземпляра рабочего процесса, а не пытаться bash все мои требования к дизайну в одно решение, превратить квадратный штифт и круглое отверстие, которое у меня было на уме, в два совершенно дополнительных отверстия и колышки.