Korzystam z biblioteki strony trzeciej. Przekazują mi POJO, które dla naszych celów i celów jest prawdopodobnie realizowane w następujący sposób:
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.
}
Z wielu powodów, w tym między innymi enkapsulacji API i ułatwiania testów jednostkowych, chcę opakować ich dane. Ale nie chcę, aby moje podstawowe klasy były zależne od ich danych (ponownie, z powodów testowych)! Więc teraz mam coś takiego:
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;
}
}
A potem to:
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();
);
}
}
Ta klasa adaptera jest połączona z kilkoma innymi klasami, które MUSZĄ wiedzieć o interfejsie API innej firmy, ograniczając jej wszechobecność w pozostałej części mojego systemu. Jednak ... to rozwiązanie jest BRUTTO! W Clean Code, strona 40:
Więcej niż trzy argumenty (poliadowe) wymagają bardzo specjalnego uzasadnienia - i i tak nie powinny być używane.
Rzeczy, które rozważałem:
- Tworzenie obiektu fabrycznego zamiast statycznej metody pomocniczej
- Nie rozwiązuje problemu posiadania bajillionowych argumentów
- Tworzenie podklasy DataTypeOne i DataTypeTwo, która ma zależny konstruktor
- Nadal ma chroniony poliadycznie konstruktor
- Twórz całkowicie osobne implementacje zgodne z tym samym interfejsem
- Wiele powyższych pomysłów jednocześnie
Jak sobie z tym poradzić?
Uwaga: nie jest to sytuacja warstwy antykorupcyjnej . Nie ma nic złego w ich API. Problemy są następujące:
- Nie chcę mieć MOICH struktur danych
import com.third.party.library.SomeDataStructure;
- Nie mogę zbudować ich struktur danych w moich testowych przypadkach
- Moje obecne rozwiązanie skutkuje bardzo bardzo dużą liczbą argumentów. Chcę, aby liczba argumentów była niska, BEZ przekazywania ich struktur danych.
- To pytanie brzmi „ czym jest warstwa antykorupcyjna?”. Moje pytanie brzmi: „ Jak mogę użyć wzoru, dowolnego wzoru, aby rozwiązać ten scenariusz?”
Nie pytam też o kod (inaczej to pytanie byłoby na SO), po prostu proszę o wystarczającą odpowiedź, aby umożliwić mi skuteczne napisanie kodu (czego to pytanie nie zapewnia).
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.