Разработка OO Spring REST API — преобразование или наследование формы

#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, и я не хочу иметь его в службе.

Что лучше? И, может быть, что-то еще?