Me acabo de encontrar con un patrón que he visto antes, y quería obtener opiniones al respecto. El código en cuestión consiste en una interfaz como esta:Secret Handshake Anti-Pattern
public interface MyCrazyAnalyzer {
public void setOptions(AnalyzerOptions options);
public void setText(String text);
public void initialize();
public int getOccurances(String query);
}
Y el uso previsto es la siguiente:
MyCrazyAnalyzer crazy = AnalyzerFactory.getAnalyzer();
crazy.setOptions(true);
crazy.initialize();
Map<String, Integer> results = new HashMap<String, Integer>();
for(String item : items) {
crazy.setText(item);
results.put(item, crazy.getOccurances);
}
Hay razones para algo de esto. El setText (...) y getOccurances (...) están ahí porque hay varias consultas que podría querer hacer después de hacer el mismo análisis costoso de los datos, pero esto puede refactorizarse a una clase de resultado.
Por qué creo que esto es tan malo: la implementación almacena el estado de una manera que no está claramente indicada por la interfaz. También he visto algo similar que implica una interfaz que requiere llamar a "prepareResult", luego "getResult". Ahora, puedo pensar en un código bien diseñado que emplee algunas de estas características. La interfaz de Hadoop Mapper amplía JobConfigurable y Closeable, pero veo una gran diferencia porque es un marco que utiliza el código de usuario que implementa esas interfaces, frente a un servicio que podría tener múltiples implementaciones. Supongo que todo lo relacionado con la inclusión de un método "cerrado" al que se debe llamar está justificado, ya que no hay otra forma razonable de hacerlo. En algunos casos, como JDBC, esto es una consecuencia de una abstracción con goteras, pero en los dos códigos en los que estoy pensando, es una clara consecuencia de los programadores que rápidamente agregaron una interfaz a una clase de código de spaghetti para limpiarlo.
Mis preguntas son:
- ¿Todos están de acuerdo en que esto es una interfaz mal diseñado?
- ¿Se trata de un antipatrón descrito?
- ¿Este tipo de inicialización pertenece alguna vez en una interfaz?
- ¿Esto me parece incorrecto porque prefiero el estilo funcional y la inmutabilidad?
Si esto es lo suficientemente común como para merecer un nombre, sugiero el anti-patrón "Secret Handshake" para una interfaz que obliga a llamar a múltiples métodos en un orden particular cuando la interfaz no es intrínsecamente Una colección).
Para ser honesto, este "patrón" me recuerda DataReaders en ADO.NET. Eso no significa que sea necesariamente una buena idea, pero se usa incluso en API serias. –
Buena antipatrón. Si los objetos se hubieran inicializado así, podríamos especificar constructores en las interfaces. También me gusta el término "apretón de manos secreto". – CurtainDog
Al menos es explícitamente malo, a diferencia de java.util.MessageFormat que usa el estado interno temporal durante llamadas de método único. –