Arquitetura modular para pipeline de processamento

8

Estou tentando projetar a arquitetura de um sistema que implementarei em C ++ e fiquei pensando se as pessoas poderiam pensar em uma boa abordagem ou criticar a abordagem que eu projetei até agora.

Primeiro de tudo, o problema geral é um pipeline de processamento de imagens. Ele contém vários estágios, e o objetivo é projetar uma solução altamente modular, para que qualquer um dos estágios possa ser facilmente trocado e substituído por um código personalizado (para que o usuário possa ter um aumento de velocidade, se souber) que um certo estágio é restringido de uma certa maneira no seu problema).

O pensamento atual é algo como isto:

struct output; /*Contains the output values from the pipeline.*/

class input_routines{
    public:
    virtual foo stage1(...){...}
    virtual bar stage2(...){...}
    virtual qux stage3(...){...}
    ...
}

output pipeline(input_routines stages);

Isso permitiria que as pessoas subclassificassem as regras de entrada e substituíssem o estágio que desejassem. Dito isso, já trabalhei em sistemas como esse antes e acho que a subclasse e o material padrão tendem a ficar confusos e podem ser difíceis de usar, por isso não estou tonto em escrever um. Eu também estava pensando em uma abordagem mais STLish, na qual os diferentes estágios (existem 6 ou 7) seriam parâmetros de modelo padrão.

Alguém pode oferecer uma crítica ao padrão acima, pensamentos sobre a abordagem do modelo ou qualquer outra arquitetura que lhe vier à mente?

anjruu
fonte
1
Tem certeza de que não deseja usar uma linguagem da família Lisp para esse tipo de projeto?
Job
Ah, eu certamente quero usar uma linguagem da família Lisp para este projeto, tragicamente, estou adicionando funcionalidade a uma biblioteca de imagens C ++ existente.
anjruu

Respostas:

2

O design é altamente dependente do que os diferentes estágios realmente fazem. Prefiro principalmente funções virtuais puras do que funções virtuais não puras (classes abstratas).

Os estágios comuns podem ser agrupados em subclasses abstratas. Ao derivar da classe abstrata principal, você ainda pode ajustar todos os estágios, mas ao derivar de uma subclasse, é possível reutilizar o comportamento existente que já está escrito. Tende a ser menos confuso, como você menciona nos métodos virtuais.

Se os diferentes estágios também puderem existir sozinhos (fora de todo o pipeline), considere também escrever classes para separar esse comportamento.

Steven Jeuris
fonte
2

Talvez crie uma lista de functores em uma fábrica, que implementam os estágios. Pseudo-código:

functorFactory() {
  return [ foo(), bar(), baz() ]
}

Os usuários podem reimplementar a fábrica ou apenas manipular a lista de functores. Pseudo-código

myFactory() {
  return [ foo(), myBar() ]
}

ou

myFactory() {
  return functorFactory()[2] = myBar()
}

Quando a instalação estiver concluída, você poderá chamar cada functor usando o resultado do último.

LennyProgrammers
fonte
+1: isso oferece flexibilidade máxima, pois o usuário pode realmente adicionar etapas / remover etapas, se assim o desejar.
Matthieu M.
1
Parece ótimo, mas como eu implementaria isso em C ++? Eu não poderia ter uma matriz de ponteiros de função, pois cada ponteiro de função teria um tipo diferente se as funções retornassem coisas diferentes, e as matrizes só podem conter objetos do mesmo tipo. Obrigado!
anjruu
0

Dê uma olhada nas Mônadas, conforme implementadas em Haskell, que podem lhe dar uma boa idéia de como configurar as coisas. Haskell acertou esse tipo de coisa.

Zachary K
fonte
0

Eu definiria um tipo intermediário. Todas as imagens seriam convertidas para este formato; cada estágio pegaria um intermediário e retornaria um intermediário - não o mesmo, um novo.

Um estágio seria o seguinte:

Intermediate DoSomething(const Intermediate &i);

Geralmente evito soluções baseadas em herança em geral, a menos que sejam um mapa bastante óbvio para o problema, por exemplo, objetos em um mundo 3D.

Paul Nathan
fonte