良好的设计用于if-else对象映射。

huangapple go评论68阅读模式
英文:

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&lt;Foo&gt; optionalFoo = Optional.ofNullable(foo);
    
result.setId(optionalFoo.map(Foo::getId).orElseGet(bar::getId));
result.setName(optionalFoo.map(Foo::getName).orElseGet(bar::getName));
// ...

答案4

得分: 1

使用通用类/接口:

如果 FooBar 扩展了一个共同的基类/接口,你可以创建一个通用方法来将逻辑应用于任何属性。

例如,假设它们实现了这个接口:

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 &lt;T&gt; T getAttribute(IBaseInterface foo, IBaseInterface bar, Function&lt;IBaseInterface, T&gt; 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 &lt;T&gt; T getAttribute(Foo foo, Bar bar, Function&lt;Foo, T&gt; functionFoo, Function&lt;Bar, T&gt; 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);

huangapple
  • 本文由 发表于 2020年8月31日 17:15:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/63668015.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定