dubbo有哪些不好看的代码

212 阅读15分钟

拿Dubbo源码为案例,来说说什么样的代码是优雅的。以下案例所用Dubbo源码版本2.6.4。

我先声明下哈,Dubbo是个好框架,我只是在鸡蛋里挑骨头,不是在指责它不好。

1.反向思维,尽快结束原则

我认为是方法或者函数最有指导价值的一个思想,放在第一个说。

要达到反向思维,尽快结束目的,我总结下3种方式

if判断反写,尽快return或者throw(最简单,最实用)

② 减少不必要的else,能不用则不用

③ 在循环中多使用breakcontinue等流程控制方式


案例1(if反写,多用流程控制语句)
// Dubbo 源码,RegistryDirectory.destroyUnusedInvokers
// 这个方法干了啥?把old列表跟new列表做一遍比对,把new列表中不存在元素,都做destory操作。也就是,循环old列表,然后逐个看new列表有没有,没有就记录到删除列表,然后循环删除列表逐个做destory操作
// 有哪些问题?看下面对应点的描述。
private void destroyUnusedInvokers(Map<String, Invoker<T>> oldUrlInvokerMap, Map<String, Invoker<T>> newUrlInvokerMap) {
    if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0) {
        destroyAllInvokers();
        return;
    }
    // check deleted invoker
    List<String> deleted = null;// 这个列表真的有必要吗?为什么不能在循环的过程中,比对命中就做destory操作
    if (oldUrlInvokerMap != null) {// 如果oldUrlInvokerMap为空,那下面deleted列表也必然为空,那为什么不做反向判断?当oldUrlInvokerMap == null,就直接return
        Collection<Invoker<T>> newInvokers = newUrlInvokerMap.values();
        for (Map.Entry<String, Invoker<T>> entry : oldUrlInvokerMap.entrySet()) {
            if (!newInvokers.contains(entry.getValue())) {
                if (deleted == null) {// 这边做懒加载的价值真的不大,正面价值节省不了多少性能,负面却是影响阅读体验,还有,每次过来都得做空判断。
                    deleted = new ArrayList<String>();
                }
                deleted.add(entry.getKey());
            }
        }
    }

    if (deleted != null) {// 如果上面不是懒加载,这边的这个判断就可以省了。
        for (String url : deleted) {
            if (url != null) {// 这边的判空有意义嘛?上面add进来的key从业务角度不可能为空,就算要做空判断,也应该放到add的入口那边,add的入口判空,如果是null就别给加进来了。
                Invoker<T> invoker = oldUrlInvokerMap.remove(url);
                if (invoker != null) {// invoker从业务上不可能为空,如果这边真的空了,那就是流程的上游有问题,应该尽快暴露,而不是通过判空来糊弄过去。
                    try {
                        invoker.destroy();
                        if (logger.isDebugEnabled()) {
                            logger.debug("destroy invoker[" + invoker.getUrl() + "] success. ");
                        }
                    } catch (Exception e) {
                        logger.warn("destroy invoker[" + invoker.getUrl() + "] faild. " + e.getMessage(), e);
                    }
                }
            }
        }
    }
}
// 重构后
// 上面的代码最深有5层,而重构过后最深只有2层。其次阅读起来也变得舒服多了。
private void destroyUnusedInvokers(Map<String, Invoker<T>> oldUrlInvokerMap, Map<String, Invoker<T>> newUrlInvokerMap) {
   if (newUrlInvokerMap == null || newUrlInvokerMap.size() == 0) {// 这边没有问题,还是正常照抄。
      destroyAllInvokers();
      return;
   }
		
   if (oldUrlInvokerMap == null || oldUrlInvokerMap.size() == 0) {// 如果old列表为空,后续操作就没有必要了。可以直接return。
      return;
   }

   // 如果仔细去看代码,会发现这个地方其实跟map里面的key没有任何关系。要销毁的是value(invoker)
   Collection<Invoker<T>> newInvokers = newUrlInvokerMap.values();
   for (Invoker<T> invoker : oldUrlInvokerMap.values()) {
      if (newInvokers.contains(invoker)) {// 如果new列表还存在,则不做destory,那么就continue,去搞下一个咯。
         continue;
      }
      try {
         invoker.destroy();// 做实际的destory
         if (logger.isDebugEnabled()) {
            logger.debug("destroy invoker[" + invoker.getUrl() + "] success. ");
         }
      } catch (Exception e) {
         logger.warn("destroy invoker[" + invoker.getUrl() + "] faild. " + e.getMessage(), e);
      }
   }
}

案例2(if反写)
// Dubbo 源码,ZookeeperRegistry.doUnsubscribe(不符合快速结束和减少if层次结构的原则)
// 有哪些问题?看下面对应点的描述。
protected void doUnsubscribe(URL url, NotifyListener listener) {
    ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
    if (listeners != null) {// 反向判断下,如果为空,不就可以直接return了嘛
        ChildListener zkListener = listeners.get(listener);
        if (zkListener != null) {// 反向判断下,如果为空,不就可以直接return了嘛
            if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
                String root = toRootPath();
                zkClient.removeChildListener(root, zkListener);// 下面加一行return,不就可以把else给省去了么
            } else {
                for (String path : toCategoriesPath(url)) {
                    zkClient.removeChildListener(path, zkListener);
                }
            }
        }
    }
}
// 重构后,会清晰很多,代码也整洁了,阅读感受会更好。
protected void doUnsubscribe(URL url, NotifyListener listener) {
    Map<NotifyListener, ChildListener> listeners = zkListeners.get(url);
    if (listeners == null || listeners.size() == 0) {
        return;
    }
  
    ChildListener zkListener = listeners.get(listener);
    if (zkListener == null || zkListener.size() == 0) {
        return;
    }
  
    if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
        String root = toRootPath();
        zkClient.removeChildListener(root, zkListener);
        return;
    }
  
    for (String path : toCategoriesPath(url)) {
        zookeeperClient.removeChildListener(path, zkListener);
    }
}

案例3(if反写)
// Dubbo 源码,ExtensionLoader.getAdaptiveExtension
public T getAdaptiveExtension() {
    Object instance = cachedAdaptiveInstance.get();
    if (instance == null) {// 反向判断,是否可以尽快return
        if (createAdaptiveInstanceError == null) {// 反向判断,是否可以尽快return
            synchronized (cachedAdaptiveInstance) {
                instance = cachedAdaptiveInstance.get();
                if (instance == null) {// 反向判断,是否可以尽快return
                    try {
                        instance = createAdaptiveExtension();
                        cachedAdaptiveInstance.set(instance);
                    } catch (Throwable t) {
                        createAdaptiveInstanceError = t;
                        throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
                    }
                }
            }
        } else {
            throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
        }
    }

    return (T) instance;
}
// 重构后,会有更好的阅读感受。
public T getAdaptiveExtension() {
    Object instance = cachedAdaptiveInstance.get();
    if (instance != null) {// 反向判断,尽快return,思路更加清晰明了
        return (T) instance;
    }

    if (createAdaptiveInstanceError != null) {// 反向判断,尽快return,思路更加清晰明了
        throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
    }

    synchronized (cachedAdaptiveInstance) {
        instance = cachedAdaptiveInstance.get();
        if (instance != null) {// 反向判断,尽快return,思路更加清晰明了
            return (T) instance;
        }
        try {
            instance = createAdaptiveExtension();
            cachedAdaptiveInstance.set(instance);
        } catch (Throwable t) {
            createAdaptiveInstanceError = t;
            throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
        }
    }
    return (T) instance;
}

案例4(if反写,多用流程控制语句)
// Dubbo 源码,ExtensionLoader.injectExtension
private T injectExtension(T instance) {
    try {
        if (objectFactory != null) {// 非空判断不可能throw异常,是否可以放到外面,并且反向判断
            for (Method method : instance.getClass().getMethods()) {
              	// 这个if有3个条件,是否可以单独提取出来,并且反向判断
                if (method.getName().startsWith("set")
                        && method.getParameterTypes().length == 1
                        && Modifier.isPublic(method.getModifiers())) {
                    Class<?> pt = method.getParameterTypes()[0];
                    try {
                        String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                        Object object = objectFactory.getExtension(pt, property);
                        if (object != null) {
                            method.invoke(instance, object);
                        }
                    } catch (Exception e) {
                        logger.error("fail to inject via method " + method.getName()
                                + " of interface " + type.getName() + ": " + e.getMessage(), e);
                    }
                }
            }
        }
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
    return instance;
}
// 重构后
private T injectExtension(T instance) {
    if (objectFactory == null) {// 提出来,单独判空,尽快return
        return instance;
    }

    try {
        for (Method method : instance.getClass().getMethods()) {
          	// 3个条件,单独提出boolean变量,并且从名字可以看出要判断啥东西,这个地方不怕名字过长。表意很重要
            boolean isSingleParamPublicSetMethod = method.getName().startsWith("set")
                    && method.getParameterTypes().length == 1
                    && Modifier.isPublic(method.getModifiers());
            if (!isSingleParamPublicSetMethod) {// 反向判断,阅读时会很容易理解,要不然得仔细阅读3个条件,还要适当猜一猜。不满足条件直接continue换下一个,简单明了。
                continue;
            }

            Class<?> pt = method.getParameterTypes()[0];
            try {
                String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                Object object = objectFactory.getExtension(pt, property);
                if (object != null) {// 这个地方没有再反写,是因为没有这个必要了,反写了也得不到啥特别的好处。适当平衡。
                    method.invoke(instance, object);
                }
            } catch (Exception e) {
                logger.error("fail to inject via method " + method.getName()
                        + " of interface " + type.getName() + ": " + e.getMessage(), e);
            }
        }
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
    return instance;
}

案例5(if反写)
// Dubbo 源码,ExtensionLoader.isMatchGroup
// 这个案例非常简单,我拿出来是想说明,编码过程要注重每一个简单的细节。
private boolean isMatchGroup(String group, String[] groups) {
    if (group == null || group.length() == 0) {
        return true;
    }
  	// 这个地方还是反写一下,会更优。
  	// 在CodeReview的时候,类似这种情况,coder就会说:我这么写没啥,也挺清晰,没必要那么计较。
  	// 是很清晰,大家也一眼就能看懂啥意思。
  	// 我想说的是,一大段复杂的代码是有由N个小的简单的代码拼凑出来的,请把每一个小的细节做到位。把每个小的细节都写的优雅了,你的整个架构,整个系统才会变得更加完美。
    if (groups != null && groups.length > 0) {
        for (String g : groups) {
            if (group.equals(g)) {
                return true;
            }
        }
    }
    return false;
}
// 重构后
private boolean isMatchGroup(String group, String[] groups) {
    if (group == null || group.length() == 0) {
        return true;
    }
    if (groups == null || groups.length == 0) {// 反写判断,直接return,大家一看就懂。
        return false;
    }
    for (String g : groups) {
        if (group.equals(g)) {
            return true;
        }
    }
    return false;
}

案例6(减少不必要的else)
// Dubbo 源码,RegistryProtocol.getFilteredKeys
// 这个类本身很简单,但是细纠,会觉得不太符合快速结束的原则
private static String[] getFilteredKeys(URL url) {
    Map<String, String> params = url.getParameters();
    if (params != null && !params.isEmpty()) {// if应该要反向判断
        List<String> filteredKeys = new ArrayList<String>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (entry != null && entry.getKey() != null && entry.getKey().startsWith(Constants.HIDE_KEY_PREFIX)) {
                filteredKeys.add(entry.getKey());
            }
        }
        return filteredKeys.toArray(new String[filteredKeys.size()]);// 这边没有必要给长度,给一个空数组即可
    } else {// 这个else是多余的
        return new String[]{};
    }
}
// 重构后
private static String[] getFilteredKeys(URL url) {
    Map<String, String> params = url.getParameters();
    if (params == null || params.isEmpty()) {// if反写,快速结束,省略了else
        return new String[]{};
    }

    List<String> filteredKeys = new ArrayList<>();
    for (Map.Entry<String, String> entry : params.entrySet()) {
        if (entry != null && entry.getKey() != null && entry.getKey().startsWith(Constants.HIDE_KEY_PREFIX)) {
            filteredKeys.add(entry.getKey());
        }
    }
    return filteredKeys.toArray(new String[0]);
}

案例7(减少不必要的else)
// Dubbo 源码,AbstractCodec.isClientSide
// 这个案例对于else的使用有很明显,是不必要的。
protected boolean isClientSide(Channel channel) {
    String side = (String) channel.getAttribute(Constants.SIDE_KEY);
    if ("client".equals(side)) {
        return true;// 都return了,还搞啥else呢?
    } else if ("server".equals(side)) {
        return false;// 都return了,还搞啥else呢?
    } else {
        InetSocketAddress address = channel.getRemoteAddress();
        URL url = channel.getUrl();
        boolean client = url.getPort() == address.getPort()
                && NetUtils.filterLocalHost(url.getIp()).equals(
                NetUtils.filterLocalHost(address.getAddress()
                        .getHostAddress()));
        channel.setAttribute(Constants.SIDE_KEY, client ? "client"
                : "server");
        return client;
    }
}
// 重构后
protected boolean isClientSide(Channel channel) {
    String side = (String) channel.getAttribute(Constants.SIDE_KEY);
    if ("client".equals(side)) {
        return true;// 很明显,那个else是没有必要的
    }
    if ("server".equals(side)) {
        return false;// 很明显,那个else是没有必要的
    }

    InetSocketAddress address = channel.getRemoteAddress();
    URL url = channel.getUrl();
    boolean client = url.getPort() == address.getPort()
            && NetUtils.filterLocalHost(url.getIp()).equals(
            NetUtils.filterLocalHost(address.getAddress()
                    .getHostAddress()));
    channel.setAttribute(Constants.SIDE_KEY, client ? "client" : "server");
    return client;
}

案例8(减少不必要的else)
// Dubbo 源码,ExchangeCodec.encodeResponse(方法中的代码片段)
if (t instanceof IOException) {
    throw (IOException) t;
} else if (t instanceof RuntimeException) {
    throw (RuntimeException) t;
} else if (t instanceof Error) {
    throw (Error) t;
} else {
    throw new RuntimeException(t.getMessage(), t);
}
// 重构后
if (t instanceof IOException) {
    throw (IOException) t;
}
if (t instanceof RuntimeException) {
    throw (RuntimeException) t;
}
if (t instanceof Error) {
    throw (Error) t;
}
throw new RuntimeException(t.getMessage(), t);

反向思维带来的好处

① 从思维上:把正向思路无限逼近一个狭小的空间,代码越往后,分支越少,思路越明了。使其变得更加透彻。

② 从代码结构上:把代码结构和思路都变得简单,降低if for等等的层次。

注意:并不是所有时候if反写都能带来好处,要看场景,可以参考案例4中,我没有做if反写的地方。适当平衡,平衡很重要。

第5个案例非常有代表性,代码很简单,我想就此再强调下。一大段复杂的代码是有由N个小的简单的代码拼凑出来的,请把每一个小的细节做到位。把每个小的细节都写的优雅了,你的整个架构,整个系统才会变得更加完美。

2.减少累赘的代码

Java足够严谨,但是不够简洁,想要把Java代码写的优雅,不要写费代码,不要拖沓。看案例


案例1(适当使用三目运算)
// Dubbo 源码,URL构造方法
public URL(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters) {
    if ((username == null || username.length() == 0)
            && password != null && password.length() > 0) {
        throw new IllegalArgumentException("Invalid url, password without username!");
    }
    this.protocol = protocol;
    this.username = username;
    this.password = password;
    this.host = host;
    this.port = (port < 0 ? 0 : port); // 比大小没必要这么写
    // trim the beginning "/"
    while (path != null && path.startsWith("/")) {
        path = path.substring(1);
    }
    this.path = path;
  	// 下面对parameters的判断处理过程有点累赘
    if (parameters == null) {
        parameters = new HashMap<String, String>();
    } else {
        parameters = new HashMap<String, String>(parameters);
    }
    this.parameters = Collections.unmodifiableMap(parameters);
}
// 重构后
public URL(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters) {
    if ((username == null || username.length() == 0) && password != null && password.length() > 0) {
        throw new IllegalArgumentException("Invalid url, password without username!");
    }
    this.protocol = protocol;
    this.username = username;
    this.password = password;
    this.host = host;
    this.port = Math.max(port, 0);// 比大小,这么写更加清晰
    this.parameters = Collections.unmodifiableMap(parameters == null ? new HashMap<>() : new HashMap<>(parameters));// 这边用三目运算符可以减少5行代码,而且也不难理解

    while (path != null && path.startsWith("/")) {
        path = path.substring(1);
    }
    this.path = path;
}

案例2(Map.computeIfAbsent挺好用的)
// Dubbo 源码,AbstractRegistry.subscribe(方法中的代码片段)
public void subscribe(URL url, NotifyListener listener) {
		// ---------------------省略一些代码------------------------
    Set<NotifyListener> listeners = subscribed.get(url);
    if (listeners == null) {
        subscribed.putIfAbsent(url, new ConcurrentHashSet<NotifyListener>());
        listeners = subscribed.get(url);
    }
    listeners.add(listener);
}
// 重构后
public void subscribe(URL url, NotifyListener listener) {
  	// 利用computeIfAbsent,只有当key不存在时,后续的表达式才会被执行。不会影响性能
  	// 其次得到的必然是最新的值。多写几次会比较适应这样的写法
    subscribed.computeIfAbsent(url, key -> new ConcurrentHashSet<>()).add(listener);
}

案例3
// Dubbo 源码,NettyClient.doOpen(方法中的代码片段)
// 问题1:getTimeout()如果大于3000,这个方法就会被调用2次。
// 问题2:用Math.max(3000, getTimeout())就能解决,if判断没有意义
protected void doOpen() throws Throwable {
    // ---------------------省略一些代码------------------------
    if (getTimeout() < 3000) {
        bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000);
    } else {
        bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getTimeout());
    }
    // ---------------------省略一些代码------------------------
}
// 重构后
protected void doOpen() throws Throwable {
  	// 使用Math.max(3000, getTimeout())就能变成一行代码。
  	bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Math.max(3000, getTimeout()));
}

案例4
// Dubbo 源码,Decodeable
// 从Dubbo的源码中不小心找到的,其他所有的接口声明都没有这问题,应该是不小心漏了
public interface Decodeable {
  	// 这个案例拿出来,还是强调细节,可能很多人觉得多写个public没什么,那怎么不把abstract也写上呢?
  	// 说到第还是习惯问题,不要写没有必要的废代码
  	// 这些细节idea是可以检查出来的,或者发布前全量扫描下代码也是可以修正的
    public void decode() throws Exception;
}
// 重构后,接口中的行为声明不要带上public
public interface Decodeable {
    void decode() throws Exception;
}

案例5
// Dubbo 源码,RpcResult
// 这个类中attachments是不可能为null的。这个从业务层面保证了的。所以这个方法中的判空是没有意义的。属于非代码
private Map<String, String> attachments = new HashMap<String, String>();
public void addAttachments(Map<String, String> map) {
    if (map == null) {
        return;
    }
  	// attachments不可能为null,判空没有意义。如果真为空了,反而要看看这个类的结构是否哪边出问题了。
    if (this.attachments == null) {
        this.attachments = new HashMap<String, String>();
    }
    this.attachments.putAll(map);
}
// 重构后,删除了对attachments的判空操作
private Map<String, String> attachments = new HashMap<String, String>();
public void addAttachments(Map<String, String> map) {
    if (map == null) {
        return;
    }
    this.attachments.putAll(map);
}

有人说,Java代码就像是老太太的裹脚布,又臭又长。我内心不想认同,当我接触了PythonGO语言后,对比发现有时候的确是这样。但我任然喜欢写Java。于此同时,我希望尽可能不要写费代码。合理利用封装,继承(不要排斥继承),多态,组合,完全能写出优雅的代码。

一些随机抽取的案例


案例1(没有必要的hash浪费)
// Dubbo 源码,SimpleDataStore.get
// 如果containsKey为true,则会出现2次hash操作(containsKey一次,get操作再一次)。浪费
public Object get(String componentName, String key) {
    if (!data.containsKey(componentName)) {
        return null;
    }
    return data.get(componentName).get(key);
}
// 重构后,用一个零时变量接一下,就不需要做2次hash了
public Object get(String componentName, String key) {
  	ConcurrentMap<String, Object> value = data.get(componentName);
  	if(value == null) {
      	return null;
    }
    return value.get(key);
}

案例2
// Dubbo 源码,ExtensionLoader.loadResource
// 这个方法写的挺奇怪的。两层try,没必要的。
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "utf-8"));
        try {// 对于资源处理,没有必要使用2层try
            String line;
            while ((line = reader.readLine()) != null) {
                final int ci = line.indexOf('#');
                if (ci >= 0) line = line.substring(0, ci);
                line = line.trim();
                if (line.length() > 0) {// 这边用if反写的方式,会更加清晰
                    try {
                        String name = null;
                        int i = line.indexOf('=');
                        if (i > 0) {
                            name = line.substring(0, i).trim();
                            line = line.substring(i + 1).trim();
                        }
                        if (line.length() > 0) {
                            loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
                        }
                    } catch (Throwable t) {
                        IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
                        exceptions.put(line, e);
                    }
                }
            }
        } finally {
            reader.close();
        }
    } catch (Throwable t) {
        logger.error("Exception when load extension class(interface: " +
                type + ", class file: " + resourceURL + ") in " + resourceURL, t);
    }
}
// 重构后
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
    BufferedReader reader;// 资源在外面申明,当然java7的方式放在try的括号中也是可以的。
    try {
        reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "utf-8"));

        String line;
        while ((line = reader.readLine()) != null) {
            final int ci = line.indexOf('#');
            if (ci >= 0) {
                line = line.substring(0, ci);
            }

            line = line.trim();
            if (line.length() <= 0) {// if反写,直接continue
                continue;
            }

            try {
                String name = null;
                int i = line.indexOf('=');
                if (i > 0) {
                    name = line.substring(0, i).trim();
                    line = line.substring(i + 1).trim();
                }
                if (line.length() > 0) {
                    loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
                }
            } catch (Throwable t) {
                IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
                exceptions.put(line, e);
            }
        }
    } catch (Throwable t) {
        logger.error("Exception when load extension class(interface: " +
                type + ", class file: " + resourceURL + ") in " + resourceURL, t);
    } finally {// 正常关闭资源
        reader.close();
    }
}

案例3(if内容体,任何时候都加上大括号)
// Dubbo 源码,ExtensionLoader.getExtensionLoader
// 前面2个if都是的内容体都是单行的。第二个加上了大括号,第一个却没有加
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
    if (type == null)// 没有加大括号
        throw new IllegalArgumentException("Extension type == null");
    if (!type.isInterface()) {
        throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
    }
    if (!withExtensionAnnotation(type)) {
        throw new IllegalArgumentException("Extension type(" + type +
                ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
    }

    ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
    if (loader == null) {
        EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
        loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
    }
    return loader;
}
// 重构后
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
    if (type == null) {// 任何时候都加上大括号。有助于阅读
        throw new IllegalArgumentException("Extension type == null");
    }
    if (!type.isInterface()) {
        throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
    }
    if (!withExtensionAnnotation(type)) {
        throw new IllegalArgumentException("Extension type(" + type +
                ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
    }

    ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
    if (loader == null) {
        EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
        loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
    }
    return loader;
}

案例4(来一段复杂的)
// Dubbo 源码,ServiceConfig.doExportUrlsFor1Protocol(方法太大,截取了一段比较复杂的来搞一搞)
// 我数了下,最深12层。这段代码不在里面瞎写了,太复杂,影响阅读
if (methods != null && !methods.isEmpty()) {
    for (MethodConfig method : methods) {
        appendParameters(map, method, method.getName());
        String retryKey = method.getName() + ".retry";
        if (map.containsKey(retryKey)) {
            String retryValue = map.remove(retryKey);
            if ("false".equals(retryValue)) {
                map.put(method.getName() + ".retries", "0");
            }
        }
        List<ArgumentConfig> arguments = method.getArguments();
        if (arguments != null && !arguments.isEmpty()) {
            for (ArgumentConfig argument : arguments) {
                // convert argument type
                if (argument.getType() != null && argument.getType().length() > 0) {
                    Method[] methods = interfaceClass.getMethods();
                    // visit all methods
                    if (methods != null && methods.length > 0) {
                        for (int i = 0; i < methods.length; i++) {
                            String methodName = methods[i].getName();
                            // target the method, and get its signature
                            if (methodName.equals(method.getName())) {
                                Class<?>[] argtypes = methods[i].getParameterTypes();
                                // one callback in the method
                                if (argument.getIndex() != -1) {
                                    if (argtypes[argument.getIndex()].getName().equals(argument.getType())) {
                                        appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                                    } else {
                                        throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                                    }
                                } else {
                                    // multiple callbacks in the method
                                    for (int j = 0; j < argtypes.length; j++) {
                                        Class<?> argclazz = argtypes[j];
                                        if (argclazz.getName().equals(argument.getType())) {
                                            appendParameters(map, argument, method.getName() + "." + j);
                                            if (argument.getIndex() != -1 && argument.getIndex() != j) {
                                                throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else if (argument.getIndex() != -1) {
                    appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                } else {
                    throw new IllegalArgumentException("argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");
                }

            }
        }
    } // end of methods for
}

// 重构后,最深变成了6层
// 多使用循环控制continue,break
if (methods != null && !methods.isEmpty()) {
    for (MethodConfig method : methods) {
        appendParameters(map, method, method.getName());
        String retryKey = method.getName() + ".retry";
        if (map.containsKey(retryKey)) {
            String retryValue = map.remove(retryKey);
            if ("false".equals(retryValue)) {
                map.put(method.getName() + ".retries", "0");
            }
        }
        List<ArgumentConfig> arguments = method.getArguments();
        if (arguments == null || arguments.isEmpty()) {
            continue;
        }

        for (ArgumentConfig argument : arguments) {
            boolean isArgumentTypeEmpty = argument.getType() == null || argument.getType().length() == 0;
            boolean argumentHasIndex = argument.getIndex() != -1;
            if (isArgumentTypeEmpty && !argumentHasIndex) {
                throw new IllegalArgumentException("argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");
            }
            if (isArgumentTypeEmpty) {
                appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                continue;
            }

            Method[] methods = interfaceClass.getMethods();
            if (methods == null || methods.length == 0) {
                continue;
            }
            for (int i = 0; i < methods.length; i++) {
                String methodName = methods[i].getName();
                if (!methodName.equals(method.getName())) {
                    continue;
                }
                Class<?>[] argtypes = methods[i].getParameterTypes();
                if (argument.getIndex() != -1) {
                    if (!argtypes[argument.getIndex()].getName().equals(argument.getType())) {
                        throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                    }
                    appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                    continue;
                }

                for (int j = 0; j < argtypes.length; j++) {
                    Class<?> argclazz = argtypes[j];
                    if (!argclazz.getName().equals(argument.getType())) {
                        continue;
                    }
                    if (argument.getIndex() != -1 && argument.getIndex() != j) {
                        throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                    }
                    appendParameters(map, argument, method.getName() + "." + j);
                }
            }
        }
    }
}

全部内容查看 优雅代码汇总篇