Search code examples
javacode-readability

How can I make this more readable and cleaner?


I am wondering what I can do to make this more readable and clean. By readable, I mean easier to read for other developers.

I don't really want to have the same code twice. I am thinking that I could make some method or methods to make it shorter, but I'm not exactly sure...

@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;
                }
            }
        }
    }
}

Solution

  • I'm assuming that what you really want to do is eliminate those two loops. I would just brute force it and extract a method containing all the necessary arguments for example:

      @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;
                     }
                 }
             }
         }
      }
    

    Then you can refactor the new fireEvents method and clean it up.