Eu uso uma biblioteca de terceiros. Eles me passam um POJO que, para nossos propósitos e propósitos, provavelmente é implementado assim:
public class OurData {
private String foo;
private String bar;
private String baz;
private String quux;
// A lot more than this
// IMPORTANT: NOTE THAT THIS IS A PACKAGE PRIVATE CONSTRUCTOR
OurData(/* I don't know what they do */) {
// some stuff
}
public String getFoo() {
return foo;
}
// etc.
}
Por muitas razões, incluindo, entre outras, encapsular sua API e facilitar o teste de unidade, desejo agrupar seus dados. Mas não quero que minhas classes principais dependam de seus dados (novamente, por razões de teste)! Então agora eu tenho algo parecido com isto:
public class DataTypeOne implements DataInterface {
private String foo;
private int bar;
private double baz;
public DataTypeOne(String foo, int bar, double baz) {
this.foo = foo;
this.bar = bar;
this.baz = baz;
}
}
public class DataTypeTwo implements DataInterface {
private String foo;
private int bar;
private double baz;
public DataTypeOne(String foo, int bar, double baz, String quux) {
this.foo = foo;
this.bar = bar;
this.baz = baz;
this.quux = quux;
}
}
E então isso:
public class ThirdPartyAdapter {
public static makeMyData(OurData data) {
if(data.getQuux() == null) {
return new DataTypeOne(
data.getFoo(),
Integer.parseInt(data.getBar()),
Double.parseDouble(data.getBaz()),
);
} else {
return new DataTypeTwo(
data.getFoo(),
Integer.parseInt(data.getBar()),
Double.parseDouble(data.getBaz()),
data.getQuux();
);
}
}
Essa classe de adaptador é acoplada às outras poucas classes que DEVEM saber sobre a API de terceiros, limitando sua abrangência pelo restante do meu sistema. No entanto ... esta solução é GROSS! No Código Limpo, página 40:
Mais de três argumentos (poládicos) exigem justificativa muito especial - e, portanto, não devem ser usados de qualquer maneira.
Coisas que eu considerei:
- Criando um objeto de fábrica em vez de um método auxiliar estático
- Não resolve o problema de ter um bajilhão de argumentos
- Criando uma subclasse de DataTypeOne e DataTypeTwo que possui um construtor dependente
- Ainda possui um construtor protegido poládico
- Crie implementações totalmente separadas que estejam em conformidade com a mesma interface
- Múltiplas das idéias acima simultaneamente
Como essa situação deve ser tratada?
Observe que essa não é uma situação de camada anticorrupção . Não há nada errado com a API deles. Os problemas são:
- Não quero que minhas estruturas de dados tenham
import com.third.party.library.SomeDataStructure;
- Não consigo construir suas estruturas de dados nos meus casos de teste
- Minha solução atual resulta em contagens de argumentos muito muito altas. Eu quero manter a contagem de argumentos baixa, SEM passar em suas estruturas de dados.
- Essa pergunta é "o que é uma camada anticorrupção?". Minha pergunta é " como posso usar um padrão, qualquer padrão, para resolver esse cenário?"
Também não estou pedindo código (caso contrário, essa pergunta estaria no SO), apenas pedindo uma resposta suficiente para que eu possa escrever o código efetivamente (o que essa pergunta não fornece).
The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification — and then shouldn’t be used anyway.