英文:
Good Design for if else object mapping
问题
我有这个逻辑:
public void method(Boo result, Foo foo, Bar bar) {
   if(foo != null) {
      if(foo.getId() != null){
         result.setId(foo.getId());
      } else {
         result.setId(bar.getId());
      }
      if(foo.getName() != null){
         boo.setName(foo.getName());
      } else {
         result.setName(bar.getName());
      }
      // 以及许多类似的属性
   } else {
      result.setId(bar.getId());
      result.setName(bar.getName());
      // 以及许多类似的属性
   }
}
我发现这种方式很丑陋,是否有办法进行更好的设计?我知道使用MapStruct会更好,但在这个项目中我不能使用。
英文:
I have this logic:
public void method(Boo result, Foo foo, Bar bar) {
   if(foo != null) {
      if(foo.getId() != null){
         result.setId(foo.getId());
      } else {
         result.setId(bar.getId());
      }
      if(foo.getName() != null){
         boo.setName(foo.getName());
      } else {
         result.setName(bar.getName());
      }
      // and many similar attributes
   } else {
      result.setId(bar.getId());
      result.setName(bar.getName());
      // and many similar attributes
   }
}
I find this way ugly, is there any way to make it in better design. I know that is better to use mapstruct, but in this project I can't.
答案1
得分: 2
我会调整测试顺序。 这样会更清晰一些,但仍然会显得混乱。
public void method(Boo result, Foo foo, Bar bar) {
    setResult(result, bar);
    if (foo != null) { setResult(result, foo); }
}
private void setResult(Boo result, Bar bar) {
    result.setId(bar.getId());
    ...
}
private void setResult(Boo result, Foo foo) {
    if (foo.getId != null) { result.setId(foo.getId()); }
    ...
}
英文:
I'd switch the tests around. It's a little cleaner, but it's still going to look messy.
public void method(Boo result, Foo foo, Bar bar) {
    setResult(result, bar);
    if (foo != null) { setResult(result, foo); }
}
private void setResult(Boo result, Bar bar) {
    result.setId(bar.getId());
    ...
}
private void setResult(Boo result, Foo foo) {
    if (foo.getId != null) { result.setId(foo.getId()); }
    ...
} 
答案2
得分: 1
我使用ObjectUtils::firstNonNull来避免使用if else,代码如下:
public void method(Boo result, Foo foo, Bar bar) {
   if(foo != null) {
      result.setId(ObjectUtils.firstNonNull(foo.getId(), bar.getId()));
      result.setId(ObjectUtils.firstNonNull(foo.getName(), bar.getName()));
      // 以及许多类似的属性
   } else {
      result.setId(bar.getId());
      result.setName(bar.getName());
      // 以及许多类似的属性
   }
}
我欢迎其他建议!
英文:
I avoid the if else using ObjectUtils::firstNonNull as bellow:
public void method(Boo result, Foo foo, Bar bar) {
   if(foo != null) {
      result.setId(ObjectUtils.firstNonNull(foo.getId(), bar.getId()));
      result.setId(ObjectUtils.firstNonNull(foo.getName(), bar.getName()));
      // and many similar attributes
   } else {
      result.setId(bar.getId());
      result.setName(bar.getName());
      // and many similar attributes
   }
}
I'm open for other suggests!
答案3
得分: 1
通过将 foo 作为一个 Optional,您可以像这样简化您的代码:
Optional<Foo> optionalFoo = Optional.ofNullable(foo);
result.setId(optionalFoo.map(Foo::getId).orElseGet(bar::getId));
result.setName(optionalFoo.map(Foo::getName).orElseGet(bar::getName));
// ...
英文:
By having foo as an Optional you could simplify your code like this:
Optional<Foo> optionalFoo = Optional.ofNullable(foo);
    
result.setId(optionalFoo.map(Foo::getId).orElseGet(bar::getId));
result.setName(optionalFoo.map(Foo::getName).orElseGet(bar::getName));
// ...
答案4
得分: 1
使用通用类/接口:
如果 Foo 和 Bar 扩展了一个共同的基类/接口,你可以创建一个通用方法来将逻辑应用于任何属性。
例如,假设它们实现了这个接口:
public interface IBaseInterface {
    Long getId();
    String getName();
}
然后,我们可以创建这个通用方法:
public static <T> T getAttribute(IBaseInterface foo, IBaseInterface bar, Function<IBaseInterface, T> function) {
    if (foo != null) {
        T attribute = function.apply(foo);
        if (attribute != null) {
            return attribute;
        }
    }
    return function.apply(bar);
}
并像这样使用它:
result.setId(getAttribute(foo, bar, IBaseInterface::getId));
result.setName(getAttribute(foo, bar, IBaseInterface::getName));
没有共同的类/接口:
如果它们没有扩展共同的基类/接口,你仍然可以使用这个技术,但需要向方法传递另一个参数:
public static <T> T getAttribute(Foo foo, Bar bar, Function<Foo, T> functionFoo, Function<Bar, T> functionBar) {
    if (foo != null) {
        T attribute = functionFoo.apply(foo);
        if (attribute != null) {
            return attribute;
        }
    }
    return functionBar.apply(bar);
}
并像这样使用它:
result.setId(getAttribute(foo, bar, Foo::getId, Bar::getId));
result.setName(getAttribute(foo, bar, Foo::getName, Bar::getName));
英文:
With common class/interface:
If Foo and Bar extend a common base class/interface you could create a generic method to apply the logic to any attribute.
For example lets say that they implement this interface:
public interface IBaseInterface {
    Long getId();
    String getName();
}
Then we could create this generic method:
public static <T> T getAttribute(IBaseInterface foo, IBaseInterface bar, Function<IBaseInterface, T> function) {
    if(foo != null) {
        T attribute = function.apply(foo);
        if(attribute != null) {
            return attribute;
        }
    }
    return function.apply(bar);
}
And use it like this:
result.setId(getAttribute(foo, bar, IBaseInterface::getId));
result.setName(getAttribute(foo, bar, IBaseInterface::getName));
Without common class/interface:
If they don't extend a common base class/interface you could still use this technique but you'd have to pass another parameter to the method:
public static <T> T getAttribute(Foo foo, Bar bar, Function<Foo, T> functionFoo, Function<Bar, T> functionBar) {
    if(foo != null) {
        T attribute = functionFoo.apply(foo);
        if(attribute != null) {
            return attribute;
        }
    }
    return functionBar.apply(bar);
}
And use it like this:
result.setId(getAttribute(foo, bar, Foo::getId, Bar::getId));
result.setName(getAttribute(foo, bar, Foo::getName, Bar::getName));
答案5
得分: 0
if语句后面只有一个语句时,不需要使用花括号{}。可以将{...}视为包裹着许多其他语句的单个语句。
此外,Java并不会在意空格和缩进,因此您可以将多个语句放在同一行。
有了这个知识,您可以让代码看起来更漂亮,就像这样:
public void method(Boo result, Foo foo, Bar bar) {
    if (foo != null) {
        if (foo.getId() != null) result.setId(foo.getId());
        else result.setId(bar.getId());
        if (foo.getName() != null) boo.setName(foo.getName());
        else result.setName(bar.getName());
    } else {
        result.setId(bar.getId());
        result.setName(bar.getName());
   }
}
或者至少去掉花括号{}:
public void method(Boo result, Foo foo, Bar bar) {
    if (foo != null) {
        if (foo.getId() != null)
            result.setId(foo.getId());
        else 
            result.setId(bar.getId());
        if (foo.getName() != null)
            boo.setName(foo.getName());
        else 
            esult.setName(bar.getName());
    } else {
        result.setId(bar.getId());
        result.setName(bar.getName());
   }
}
英文:
if statements don't need curly brackets {} when there there is a single statement afterwards. Think of it as {...} as a single statement wrapping many other inside it.
<br>Also Java doesn't really care about whitespaces and indentation so you can put multiple statements in the same line.
With this knowledge you can make the code prettier like this:
public void method(Boo result, Foo foo, Bar bar) {
    if (foo != null) {
        if (foo.getId() != null) result.setId(foo.getId());
        else result.setId(bar.getId());
        if (foo.getName() != null) boo.setName(foo.getName());
        else result.setName(bar.getName());
    } else {
        result.setId(bar.getId());
        result.setName(bar.getName());
   }
}
or at the very least remove the {}:
public void method(Boo result, Foo foo, Bar bar) {
    if (foo != null) {
        if (foo.getId() != null)
            result.setId(foo.getId());
        else 
            result.setId(bar.getId());
        if (foo.getName() != null)
            boo.setName(foo.getName());
        else 
            esult.setName(bar.getName());
    } else {
        result.setId(bar.getId());
        result.setName(bar.getName());
   }
}
答案6
得分: 0
如果映射对象具有相同的属性,并且项目依赖中有Spring Bean,可以使用BeanUtils.copyProperties(source, destination)。
英文:
If the mapping objects are having same properties, and if you have spring beans in your project dependency, BeanUtils.copyProperties(source, destination);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论