个人精进系列-好的代码-审美/函数

2020-05-13  本文已影响0人  JayWu的架构笔记

个人精进系列-好的代码-审美/函数

审美

好的代码应当“看上去养眼”

一致性

public class PerformanceTester {

    public TcpConnectionSimulator wifi = new TcpConnectionSimulator(
                                            500,
                                            80);
                                            
    public TcpConnectionSimulator t3LongNameFiber = 
                new TcpConnectionSimulator(
                      45000,
                      10);

    public TcpConnectionSimulator cell = new TcpConnectionSimulator(    
                                            100,
                                            400);
}

调整

重新排版来保持一致和紧凑

public class PerformanceTester {    
 public TcpConnectionSimulator wifi = 
                new TcpConnectionSimulator(
                      500,
                      80);
 public TcpConnectionSimulator t3LongNameFiber = 
                new TcpConnectionSimulator(
                      45000,
                      10);
 public TcpConnectionSimulator cell = 
                new TcpConnectionSimulator(
                      100,
                      400);
}

换行

定义:

public ResourceHandlerMapping(ResourceLoader staticResourceLoader, String baseDir, String mappingPath)

使用:

new ResourceHandlerMapping(staticResourceLoader,"/Volumes/Mac/Users/jaywu/Documents/webapp/",DEFAULT_MAPPING_PATH);

调整

重新排版来保持一致和紧凑

public ResourceHandlerMapping(ResourceLoader staticResourceLoader,
                              String baseDir,
                              String mappingPath) 

使用:

new ResourceHandlerMapping(
        staticResourceLoader,
        "/Volumes/Mac/Users/jaywu/Documents/webapp/",
        DEFAULT_MAPPING_PATH
);

分组

例1

public class Demo {
    public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
    
    private MultipartResolver multipartResolver;
    
    private FlashMapManager flashMapManager;
    
    private LocaleResolver localeResolver;
    
    public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";

    private MultipartResolver multipartResolver;

    public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
}
调整

把声明按块组织起来

public class Demo {
    public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
    public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
    public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";

    private MultipartResolver multipartResolver;
    private LocaleResolver localeResolver;
    private MultipartResolver multipartResolver;
    
    private FlashMapManager flashMapManager;
}

例2

processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
    noHandlerFound(processedRequest, response);
    return;
}
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
调整

把代码分成“段落”

processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);

// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
    noHandlerFound(processedRequest, response);
    return;
}

// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}

// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

原则

按代码逻辑的关联、紧密程度分组

IDEA

函数

意图提取

将逻辑中的重要意图单独提取函数,使整体逻辑清晰,避免陷入细节。

if(a > 0 && b < 1) {
    c = 1;
    d = 2;
}

调整

if(isItemEnabled()) {
    changeOrderStatus();
}

函数参数

Line makeLine(String startX, 
              String startY,
              String endX,
              String endY);

调整

public class Point{
    double x;
    double y;
}

Line makeLine(Point start, Point end);

短小的函数

要写出精简的函数,可以牢记以下原则:

精简辅助代码

定义

必不可少的非核心代码即为辅助代码

重要性

减少对业务代码的干扰,防止淹没在辅助代码,直观地体现业务逻辑。

优化判空

判空代码非常干扰阅读流畅性

public void handle(A a) {
    String value = null;

    if (a != null) {
        B b = a.b();
        if (b != null) {
            C c = b.c();
            if (c != null) {
                D d = c.d();
                if (d != null) {
                    value = d.value();
                }
            }
        }
    }
    
    // 重要的业务代码
    ...
}

调整

意图提取,防止淹没业务代码

public void handle(A a) {
    String value = getValue(a)
    // 重要的业务代码
}

private String getValue(A a) {
    if (a != null) {
        B b = a.b();
        if (b != null) {
            C c = b.c();
            if (c != null) {
                D d = c.d();
                if (d != null) {
                   return d.value();
                }
            }
        }
    }
    
    return null;
}

尽早退出异常流程

private String getValue(A a) {
    if(a == null) {
        return null;
    }
    
    B b = a.b();
    if(b == null) {
        return null;
    }
    
    C c = b.c();
    if(c == null) {
        return null;
    }
    
    D d = c.d();
    if(d == null) {
        return null;
    }
    
    return d.value();
}
隐藏技术细节

组合函数模式

定义

将大函数拆成多个子函数的组合

public Source handle(Context context) {
    List<Source> sources = handlers.stream()
        .map(it -> it.handle(context))
        .filter(Objects::nonNull)
        .collect(Collectors.toList());

    if (sources.isEmpty()) {
        return null;
    }

    SelectorBinding selectorBinding = new ListBinding(
        sources.stream()
        .map(it -> it.getSourceType().value())
        .collect(Collectors.toList())
    );
    
    String selectedValue = selector.select(selectorConfigId(), selectorBinding);

    return sources.stream()
        .filter(it -> StrUtil.equals(it.getSourceType().value(), selectedValue))
        .findFirst()
        .orElse(null);
}

调整

public Source handle(Context context) {
    List<Source> sources = filterEffectiveSources(context);

    if (sources.isEmpty()) {
        return null;
    }

    String selectedValue = selectSourceValue(sources);

    return sourceOf(sources, selectedValue);
}

调整后

抽象层次一致性

public Source handle(Context context) {
    List<Source> sources = filterEffectiveSources(context);

    if (sources.isEmpty()) {
        return null;
    }

    SelectorBinding selectorBinding = new ListBinding(
        sources.stream()
        .map(it -> it.getSourceType().value())
        .collect(Collectors.toList())
    );
    
    String selectedValue = selector.select(selectorConfigId(), selectorBinding);

    return sourceOf(sources, selectedValue);
}

调整

public Source handle(Context context) {
    List<Source> sources = filterEffectiveSources(context);

    if (sources.isEmpty()) {
        return null;
    }

    String selectedValue = selectSourceValue(sources);

    return sourceOf(sources, selectedValue);
}

抽象层次一致性是指导函数拆分的重要原则。

函数式编程

Java的函数式编程

Stream
long count = 0;
List<Integer> list = Arrays.asList(1, 2, 3);
for (Integer it : list) {
    if (it > 2) {
        count++;
    }
}

调整

Stream.of(1, 2, 3)
    .filter(it -> it > 2)
    .count();
Optional
String value = null;

if (a != null) {
    B b = a.b();
    if (b != null) {
        C c = b.c();
        if (c != null) {
            D d = c.d();
            if (d != null) {
                value = d.value();
            }
        }
    }
}

调整

String value = Optional.ofNullable(a)
    .map(it->it.b())
    .map(it->it.c())
    .map(it->it.d())
    .map(it->it.value())
    .orElse(null)
总结

保持精进

上一篇下一篇

猜你喜欢

热点阅读