#java #spring #rest #oop #api-design
#java #весна #rest #ооп #api-дизайн
Вопрос:
У меня есть следующий сценарий (упрощенный) в Spring REST API.
public class FooService
{
public void createFoo(FooData data) { ... }
}
public class FooController
{
public void makeFooAnymous(AnymousFooForm aif) { ... }
public void makeFooUser(UserFooForm uif) { ... }
}
Обе конечные точки makeIssueAnymous и makeIssueUser хотят вызвать createIssue, потому что они делают то же самое, но имеют некоторые различия в API.
Решение I
В контроллере обе конечные точки вызывают метод
private <T> void createFooUsing(T fooForm, Function<T, FooData> formToDataConverter)
{
// doSomeCommonConversionLogic
try
{
createSomeResource();
fooService.saveFoo(formToDataConverter.apply(fooForm), andMaybeAnotherParam);
} catch (SomeExcp e) { doSomeThingSpecial() }
}
И классы форм такие:
class UserFooForm
{
public String someData;
public FooData toFooData(String otherField) { ... }
}
class AnymousFooForm
{
public String someDatas;
public String otherField;
public FooData toFooData(int paramFromPath) { ... }
}
И код в методе cotroller выглядит следующим образом:
public void makeFooUser(@RequestBody UserFooForm fooForm)
{
return createFooUsing(fooForm, f -> f.toFooData("abc"));
}
public void makeFooAnymous(@RequestBody UserFooForm fooForm)
{
return createFooUsing(fooForm, f -> f.toFooData(123));
}
Решение II:
Превратите FooData в интерфейс
interface FooData {
String getSomeData();
String getOtherField();
}
И сделайте UserIssueForm и AnymousIssueForm реализующими интерфейс, скопируйте «doSomeCommonConversionLogic» и просто передайте его в метод createIssue service.
public void makeFooUser(@RequestBody UserFooForm fooForm)
{
// doSomeCommonConversionLogic
try
{
createSomeResource();
fooForm.prepare("abc");
fooService.saveFoo(fooForm, andMaybeAnotherParam);
} catch (SomeExcp e) { doSomeThingSpecial() }
}
public void makeFooAnymous(@RequestBody AnymousFooForm fooForm)
{
// doSomeCommonConversionLogic
try
{
createSomeResource();
fooForm.prepare(123);
fooService.saveFoo(fooForm, andMaybeAnotherParam);
} catch (SomeExc e) { doSomeThingSpecial() }
}
Это было бы здорово, если бы не было такого общего кода. Это связано с HTTP, и я не хочу иметь его в службе.
Что лучше? И, может быть, что-то еще?