Nosso domínio do conhecimento envolve pessoas caminhando sobre uma placa de registro de pressão com os pés descalços. Fazemos reconhecimento de imagem que resulta em objetos da classe 'Foot', se um pé humano for reconhecido nos dados do sensor.
Existem vários cálculos que devem ser realizados nos dados do pé.
Agora, qual API seria melhor:
class Foot : public RecognizedObject {
MaxPressureFrame getMaxPressureFrame();
FootAxis getFootAxis();
AnatomicalZones getAnatomicalZones();
// + similar getters for other calculations
// ...
}
Ou:
class Foot : public RecognizedObject {
virtual CalculationBase getCalculation(QString aName);
// ...
}
Agora, há muitos prós e contras com os quais eu posso pensar, mas não consigo decidir quais são os mais importantes. Observe que este é um aplicativo de usuário final, não uma biblioteca de software que vendemos.
Algum conselho?
Alguns profissionais da primeira abordagem podem ser:
- BEIJO - tudo é muito concreto. A API, mas a implementação também.
- valores de retorno fortemente digitados.
- herdar dessa classe é à prova de idiotas. Nada pode ser substituído, apenas adicionado.
- A API está muito fechada, nada entra, nada pode ser substituído, portanto, menos pode dar errado.
Alguns contras:
- O número de getters aumentará, à medida que cada novo cálculo que inventamos for adicionado à lista
- É mais provável que a API mude e, se forem introduzidas alterações mais recentes, precisamos de uma nova versão da API, o Foot2.
- no caso de reutilização da classe em outros projetos, talvez não precisemos de todos os cálculos
Alguns profissionais da segunda abordagem:
- mais flexível
- é menos provável que a API mude (assumindo que a abstração esteja correta, caso contrário, a alteração custará mais)
Alguns contras:
- digitado livremente. Precisa de transmissões em todas as chamadas.
- o parâmetro string - tenho sentimentos ruins sobre isso (ramificação nos valores da string ...)
- Não há nenhum caso / requisito de uso atual que exija flexibilidade extra, mas pode haver no futuro.
- a API impõe restrições: todo cálculo precisa derivar de uma classe base. A obtenção de um cálculo será forçada através deste método 1, e a passagem de parâmetros extras será impossível, a menos que planejemos uma maneira ainda mais dinâmica e super flexível de passar parâmetros, o que aumenta ainda mais a complexidade.
getCalculation()
.
enum
e ativar seus valores. Ainda assim, acho que a segunda opção é má, porque se desvia do KISS.