更好的编写`checkOrElseThrow`通用函数的方式

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

Better way to write the checkOrElseThrow generic function

问题

我有两个函数调用,用于Employee和Address DAO类,我在这两个函数中检查雇员姓名或地址是否已被使用。

为了使其通用化以进行检查并抛出异常,我创建了以下通用函数

CommonUtil.java 中的 checkOrElseThrow

public static <R, C, T extends Throwable> R checkOrElseThrow(R rtn, C chk, Supplier<? extends T> ex) throws T
{
    if (chk != null)
    {
        throw ex.get();
    }
    return rtn;
}

上述通用函数在 EmployeeDAO.javaAddressDAO.java 中被调用,如下所示:

EmployeeDAO.java 中的 checkAndReturnEmployee

public Employee checkAndReturnEmployee(Employee employee) {
    return checkOrElseThrow(
        employee,
        employee.getAddressName(),
        () -> new EntityNotFoundException("Employee already in use for another address"));
}

AddressDAO.java 中的 checkAndReturnAddress

public Address checkAndReturnAddress(Address address) {
    return checkOrElseThrow(
        address,
        address.getEmployeeName(),
        () -> new EntityNotFoundException("Address already in use for another address"));
}

##问题

我的解决方案运行良好,但我想知道是否有其他更好的方法来重写我编写的通用函数(checkOrElseThrow)。

英文:

I have two function calls for Employee and Address DAO class where I check if the employee name or address is already in used

For making it generic to check and throw exception I have created the following generic function

checkOrElseThrow in CommonUtil.java

public static &lt;R, C, T extends Throwable&gt; R checkOrElseThrow(R rtn, C chk, Supplier&lt;? extends T&gt; ex) throws T
{
    if (chk != null)
    {
        throw ex.get();
    }
    return rtn;
}

and the above generic function is been called in EmployeeDAO.java and AddressDAO.java like as shown below

checkAndReturnEmployee in EmployeeDAO.java

public Employee checkAndReturnEmployee(Employee employee) {
    return checkOrElseThrow(
        employee,
        employee.getAddressName(),
        () -&gt; new EntityNotFoundException(&quot;Employee already in use for another address&quot;));
}

checkAndReturnAddress in AddressDAO.java

public Address checkAndReturnAddress(Address address) {
    return checkOrElseThrow(
        address,
        address.getEmployeeName(),
        () -&gt; new EntityNotFoundException(&quot;Address already in use for another address&quot;));
}

##Question

My solution is working fine, but I would like to know if there is any other better way to rewrite the generic function (checkOrElseThrow) which I have written

答案1

得分: 5

以下是翻译好的部分:

public Employee checkAndReturnEmployee(Employee employee) {
    if (employee.getAddressName() == null) {
        throw new EntityNotFoundException("Employee already in use for another address");
    }
    return employee;
}

上面的代码同样很简短,但更易读。清楚地表达了条件是什么,以及当条件不满足时会发生什么。

您的自定义函数只是试图为Java创建一种新的语法,这种语法其他人可能无法理解,而且您自己也可能很快就会忘记。

英文:

The best way to write this is to not.

public Employee checkAndReturnEmployee(Employee employee) {
    if (employee.getAddressName() == null) {
      throw new EntityNotFoundException(&quot;Employee already in use for another address&quot;));
    }
    return employee;
}

The code above is just as short, but far more readable. It's clearer what the condition is, and what happens when it is not met.

Your custom function only serves to attempt to create a new syntax for Java, one that other people will not understand, and you may soon forget also.

答案2

得分: 1

考虑使用 java.util.Optional,因为您尝试实现的行为已经存在于其中。我认为这比进行 if (smth != null) 检查要优雅得多。

Optional.ofNullable(employee)
    .map(Employee::getAddressName)
    .orElseThrow(() -> new EntityNotFoundException("Employee already in use for another address"));

通常情况下,我更喜欢使用 Optional,主要是因为如果还需要对 entity 进行空值检查(在这个问题中不需要),可能会嵌套多个 if 条件或链式条件。然后您可能会需要像 if (entity != null && entity.getAddress() == null) {throw ...} 这样的代码,这种写法比起使用 Optional 的链式版本更加难以阅读和理解。当然,后一种语句也涉及一些语法口味的因素。

英文:

Consider using java.util.Optional since the behavior that you are trying to achieve is already there. I find it far more elegant than if (smth != null) checks.

Optional.ofNullable(employee)
    .map(Employee::getAddressName)
    .orElseThrow(() -&gt; new EntityNotFoundException(&quot;Employee already in use for another address&quot;);

In general, I prefer Optional mainly because one would probably nest multiple ifs or chain the conditions if null check for entity was also needed (not the case for this question). Then you would need something like if (entity != null &amp;&amp; entity.getAddress() == null) {throw ...} which is ugly and far less readable than the chained version with Optional. The latter statement, of course, is also a bit of syntactic taste.

答案3

得分: 1

以下是您要翻译的内容:

由于问题更多地涉及通用实现,您可以修改您现有的实现以利用Predicate来测试任何条件,并按如下方式处理:

public <R, T extends Throwable> R checkOrElseThrow(R returnValue, Predicate<R> successCriteria,
                                                   Supplier<? extends T> ex) throws T {
    if (successCriteria.test(returnValue)) {
        return returnValue;
    }
    throw ex.get();
}

并在相应的地方进一步调用它,如下所示:

public Employee checkAndReturnEmployee(Employee employee) throws EntityNotFoundException {
    return checkOrElseThrow(employee, emp -> emp.getAddressName() != null,
            () -> new EntityNotFoundException("Employee already in use for another address"));
}

public Address checkAndReturnAddress(Address address) throws EntityNotFoundException {
    return checkOrElseThrow(address, add -> add.getEmployeeName() != null,
            () -> new EntityNotFoundException("Address already in use for another address"));
}
英文:

Since the question was more around the generic implementation, you could modify your existing implementation to make use of a Predicate to test out any criteria and work it out as:

public &lt;R, T extends Throwable&gt; R checkOrElseThrow(R returnValue, Predicate&lt;R&gt; successCriteria,
                                                   Supplier&lt;? extends T&gt; ex) throws T {
    if (successCriteria.test(returnValue)) {
        return returnValue;
    }
    throw ex.get();
}

and further invoke this in corresponding places as:

public Employee checkAndReturnEmployee(Employee employee) throws EntityNotFoundException {
    return checkOrElseThrow(employee, emp -&gt; emp.getAddressName() != null,
            () -&gt; new EntityNotFoundException(&quot;Employee already in use for another address&quot;));
}

public Address checkAndReturnAddress(Address address) throws EntityNotFoundException {
    return checkOrElseThrow(address, add -&gt; add.getEmployeeName() != null,
            () -&gt; new EntityNotFoundException(&quot;Address already in use for another address&quot;));
}

huangapple
  • 本文由 发表于 2020年4月5日 05:34:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/61035104.html
匿名

发表评论

匿名网友

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

确定