2

我想知道我能做些什么来使它更具可读性和清洁性。可读性是指其他开发人员更容易阅读。

我真的不想两次使用相同的代码。我在想我可以做一些方法来缩短它,但我不确定......

@Override
public void dispatchEvent(Event event) {
    checkNotNull(event);

    CancellableEvent cancellableEvent = null;
    boolean cancellable;
    if (cancellable = event instanceof CancellableEvent) {
        cancellableEvent = (CancellableEvent) event;
        checkArgument(cancellableEvent.isCancelled());
    }

    // Ignore-cancellation event handlers will run
    for (EventPriority priority : EventPriority.values()) {
        Map<Method, EventListener> internalMapping = getRegistry().getMethodMap(event.getClass(), priority, true);
        if (internalMapping != null) {
            for (Entry<Method, EventListener> entry : internalMapping.entrySet()) {
                try {
                    entry.getKey().invoke(entry.getValue(), event);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    /*
                     * Delegate any exceptions that occur from
                     * the method to a runtime exception.
                     */
                    throw new RuntimeException(e);
                }
            }
        }
    }

    // Event handlers that consider cancellation will run
    for (EventPriority priority : EventPriority.values()) {
        Map<Method, EventListener> internalMapping = getRegistry().getMethodMap(event.getClass(), priority, false);
        if (internalMapping != null) {
            for (Entry<Method, EventListener> entry : internalMapping.entrySet()) {
                try {
                    entry.getKey().invoke(entry.getValue(), event);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    /*
                     * Delegate any exceptions that occur from
                     * the method to a runtime exception.
                     */
                    throw new RuntimeException(e);
                }
                // Immediately return in the case of the event being cancelled.
                if (cancellable && cancellableEvent.isCancelled()) {
                    return;
                }
            }
        }
    }
}
4

7 回答 7

3

如果您在谈论异常,那么在 java 7 中您可以加入异常。

这是有关使用 Java7 异常的文章

} catch (ParseException | IOException exception) {
// handle I/O problems.
}

关于迭代,您可以使用单独的方法来调用功能。

于 2012-09-26T18:48:40.123 回答
2

关于使某些代码更具可读性的建议是什么?长期以来,代码整洁的衡量标准之一是众所周知的:类应该尽可能小,方法应该尽可能小。

假设你可以做一些“提取方法”重构和提取,例如:

processIgnoreCancellationEventHandlers(); processEventHandlersWithPossibleCancellation();

如果可能的话,我会更进一步,使用不同的输入参数制作一种方法,例如:

processEventHandlers(noCancellationEventHandlers); processEventHandlers(CancellationAwareEventHandlers);

这样,您将获得两项成就:

  • 更简单、更短、更易读的代码,
  • 没有重复。
于 2012-09-26T18:58:21.083 回答
2

没有更多上下文很难知道,但这里有一些想法。

  • 两个循环的for (Entry<Method, EventListener> entry : internalMapping.entrySet()) {循环似乎相同。我会把它放在它自己的方法中。它会接受一个Map并且它将完成整个循环。那么你的两个for循环会小得多。

    private void runMap(Map<Method, EventListener> methodMap) {
        for (Entry<Method, EventListener> entry : methodMap.entrySet()) {
           ...
        }
    }
    

    然后你可以做一个循环:

    for (EventPriority priority : EventPriority.values()) {
       runMap(getRegistry().getMethodMap(event.getClass(), priority, true));
       runMap(getRegistry().getMethodMap(event.getClass(), priority, false));
    }
    
  • 当你在一个包含整个循环的循环中做某事时,if (internalMapping != null) {我倾向于使用if (internalMapper == null) continue;. 这减少了缩进级别。

  • 已经提到了异常处理。您也可以处理第InvocationTargetException一个,然后catch (Exception e)在它下面打印出所有其余部分。

于 2012-09-26T18:58:40.677 回答
2

我假设您真正想要做的是消除这两个循环。我会暴力破解它并提取一个包含所有必要参数的方法,例如:

  @Override
  public void dispatchEvent(Event event) {
      checkNotNull(event);

      CancellableEvent cancellableEvent = null;
      boolean cancellable;
      if (cancellable = event instanceof CancellableEvent) {
          cancellableEvent = (CancellableEvent) event;
          checkArgument(cancellableEvent.isCancelled());
      }

     fireEvents(false, event, cancellableEvent, cancellable);
     fireEvents(true, event, cancellableEvent, cancellable);

  }

  private void fireEvents(boolean considerCancellation, Event event, CancellableEvent cancellableEvent, boolean cancellable)
  {
     // Event handlers that consider cancellation will run
     for (EventPriority priority : EventPriority.values()) {
         Map<Method, EventListener> internalMapping = getRegistry().getMethodMap(event.getClass(), priority, ! considerCancellation);
         if (internalMapping != null) {
             for (Map.Entry<Method, EventListener> entry : internalMapping.entrySet()) {
                 try {
                     entry.getKey().invoke(entry.getValue(), event);
                 } catch (IllegalAccessException e) {
                     e.printStackTrace();
                 } catch (IllegalArgumentException e) {
                     e.printStackTrace();
                 } catch (InvocationTargetException e) {
                     /*
                      * Delegate any exceptions that occur from
                      * the method to a runtime exception.
                      */
                     throw new RuntimeException(e);
                 }
                 // Immediately return in the case of the event being cancelled.
                 if ( considerCancellation && cancellable && cancellableEvent.isCancelled()) {
                     return;
                 }
             }
         }
     }
  }

然后你可以重构新的 fireEvents 方法并清理它。

于 2012-09-26T19:02:26.010 回答
2

永远不要在 if 条件下进行赋值。这是容易出错的:

if (cancellable = event instanceof CancellableEvent) {
    ...
}

只需这样做:

boolean cancellable = event instanceof CancellableEvent;
if (cancellable) {
    ...
}
于 2012-09-26T19:08:06.147 回答
1

您可以将条目的调用重构为另一个方法。

private final void invokeEntry(Entry<Method, EventListener> entry, Event event) {
    try {
        entry.getKey().invoke(entry.getValue(), event);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        /*
         * Delegate any exceptions that occur from
         * the method to a runtime exception.
         */
        throw new RuntimeException(e);
    }
}

然后你可以用这个替换你的dispatchEvent方法:

@Override
public void dispatchEvent(Event event) {
    checkNotNull(event);

    CancellableEvent cancellableEvent = null;
    boolean cancellable;
    if (cancellable = event instanceof CancellableEvent) {
        cancellableEvent = (CancellableEvent) event;
        checkArgument(cancellableEvent.isCancelled());
    }

    // Ignore-cancellation event handlers will run
    for (EventPriority priority : EventPriority.values()) {
        Map<Method, EventListener> internalMapping = getRegistry().getMethodMap(event.getClass(), priority, true);
        if (internalMapping != null) {
            for (Entry<Method, EventListener> entry : internalMapping.entrySet()) {
                invokeEntry(entry, event);
            }
        }
    }

    // Event handlers that consider cancellation will run
    for (EventPriority priority : EventPriority.values()) {
        Map<Method, EventListener> internalMapping = getRegistry().getMethodMap(event.getClass(), priority, false);
        if (internalMapping != null) {
            for (Entry<Method, EventListener> entry : internalMapping.entrySet()) {
                invokeEntry(entry, event);
                // Immediately return in the case of the event being cancelled.
                if (cancellable && cancellableEvent.isCancelled()) {
                    return;
                }
            }
        }
    }
}
于 2012-09-26T18:59:23.920 回答
1

由于除了一个布尔值外,循环是相同的,所以我会先像这样拆分它们,然后在需要时进一步分解它们。

@Override
public void dispatchEvent(Event event) {
    checkNotNull(event);
    CancellableEvent cancellableEvent = null;
    boolean cancellable;
    if (cancellable = event instanceof CancellableEvent) {
        cancellableEvent = (CancellableEvent) event;
        checkArgument(cancellableEvent.isCancelled());
    }
    handleEvents(event, true);
    handleEvents(event, false, cancellableEvent);
}

public void handleEvents(Event event, boolean cancellable)
{
    handleEvents(event, cancellable, null);
}

public void handleEvents(Event event, boolean cancellable, CancellableEvent cancellableEvent)
{
    for (EventPriority priority : EventPriority.values()) {
        Map<Method, EventListener> internalMapping = getRegistry().getMethodMap(event.getClass(), priority, cancellable);
        if (internalMapping != null) {
            for (Entry<Method, EventListener> entry : internalMapping.entrySet()) {
                try {
                    entry.getKey().invoke(entry.getValue(), event);
                } catch (IllegalAccessException | IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    /*
                    * Delegate any exceptions that occur from
                    * the method to a runtime exception.
                    */
                    throw new RuntimeException(e);
                }
                // Immediately return in the case of the event being cancelled.
                if (cancellableEvent != null && cancellable && cancellableEvent.isCancelled()) {
                    return;
                }
            }
        }
    }
}
于 2012-09-26T19:05:20.270 回答