您的位置 首页 java

Java大坑盘点!代码注释没写好,损失过亿(案例分析)

备注:为了清楚表述问题,以下代码相较源码有所改动,但是并未改动代码逻辑。

先说说背景吧,项目需要用docker的java sdk做一个docker镜像的构建服务,允许用户输入构建目录,dockerfile的文件路径等等参数,构建服务根据用户输入的参数进行镜像构建。

构建的请求过程是:client将构建目录打成tar包发送至docker deamon,dockers deamon根据dockerfile参数找到dockerfile进行构建。其中实例化构建命令类 (BuildImageCmd) 的对象的示例代码如下:

 BuildImageCmd buildImageCmd = new BuildImageCmd.BuildImageCmdBuilder()
         .withDockerfile(dockerFile)  //dockerfile路径
         .withBaseDirectory(baseDir) //构建路径
         .build();  

由于docker build命令的参数较多,读者如果想深入了解,可以参考docker的帮助文档。

大家都知道,当一个实体类有很多的属性,这些属性有些是必选有些是可选时,我们一般会使用构建器来实例化实体类的对象。Docker build的参数这么多,有些可选有些必选,自然会选用构建器来实例化对象。具体BuildImageCmd的实现如下代码所示:

 public class BuildImageCmd {
    private InputStream tarInputStream;   //构建目录的tar包输入流
    private File dockerFile;      //dockerfile路径
    private File baseDirectory;     //构建路径
    public InputStream getInputStream() { return tarInputStream ;}
    public File getDockerFile() { return dockerFile;}
    public File getBaseDirectory() {return baseDirectory;}
    public static class BuildImageCmdBuilder{
        private InputStream tarInputStream;
        private File dockerFile;
        private File baseDirectory;
        public BuildImageCmdBuilder withTarInputStream(InputStream tarInputStream) {
            this.tarInputStream = tarInputStream;
            return this;
        }
        public BuildImageCmdBuilder withBaseDirectory(File baseDirectory) {
            this.baseDirectory = baseDirectory;
            return this;
        }
        public BuildImageCmdBuilder withDockerfile(File dockerfile) {
            if (!dockerfile. exists ()) {
                throw new IllegalArgumentException("Dockerfile does not exist");
            }
            if (!dockerfile.isFile()) {
                throw new IllegalArgumentException("Not a directory");
            }
            if (baseDirectory == null) {
                withBaseDirectory(dockerfile.getParentFile());
            }
            this.dockerFile = dockerfile;
            try {
                withTarInputStream(new Dockerfile(dockerfile, baseDirectory).parse().buildDockerFolderTar());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return this;
        }
        public BuildImageCmd builder() { return new BuildImageCmd(this);}
    }
    private BuildImageCmd(BuildImageCmdBuilder builder) {
       this.tarInputStream = builder.tarInputStream;
       this.baseDirectory = builder.baseDirectory;
       this.dockerFile = builder.dockerFile;
    }
}
  

我们重点看WithDockerfile(File dockerfile)方法

方法中,首先进行了参数校验,然后判断了baseDirectory这个属性是不是为空,如果为空,则设置baseDirectory为dockerfile的父目录,然后将构建目录baseDirectory目录下的所有文件打包。纳尼,如果没事先调用withBaseDirectory(File baseDirectory)方法,则会把构建目录设置为dockerfile的父目录,并且把构建内容(tarInputStream属性)也设置好???

那这不就是意味着假如我先设置了dockerfile,然后再设置baseDirectory或者tarInputStream就不起作用吗?嗯,实验证明,确实是这样的。

:实体类的属性之间相互有依赖的时候,切忌不要使用构建器当作实例化的方法。如果非要这样,请想好怎么解决相互之间的依赖带来的问题或者写好注释!!!

坑已经踩了,规避办法倒也简单,只需将withDockerfile(dockerFile)的调用置于withBaseDirectory(baseDir)的调用后面。但这是在踩了坑看了源代码之后发现的。如果别人再用,这个坑难免还是会踩到,那么如何从设计上根本解决这个问题呢?

其实解决问题的根本就是得保证baseDirectory和tarInputStream的设置先于dockerfile的设置。因此我们可以将这两个属性的设置置于Builder的构造方法里面,示例代码如下所示:

 public static class BuildImageCmdBuilder{
    private InputStream tarInputStream;
    private File dockerFile;
    private File baseDirectory;
    public BuildImageCmdBuilder(InputStream tarInputStream) {
        this.tarInputStream  = tarInputStream;
    }
    public BuildImageCmdBuilder(File baseDirectory) {
       this.baseDirectory = baseDirectory;
    }
    public BuildImageCmdBuilder withTarInputStream(InputStream tarInputStream){
       this.tarInputStream = tarInputStream;
       return this;
    }
    …   //其他代码省略
}
  

这样用户在用构建器实例化对象时,必须先设置tarInputStream或者baseDirectory。也就自然解决了上面由于属性相互依赖导致的问题了。

最后再说一遍,请写好代码注释,避免其他人不必要的踩坑!


私信来聊天!

因今日头条推荐流问题…为了避免 【一起来Java】 消失在大家的信息流中,小编这里欢迎大家多 评论 点赞 关注 哦~ 关注完之后 大家就可以每天正常收到我们的推送,愉快学习愉快聊天啦!

大家也可以将学习使用Java过程中不懂的困惑提出来,小编也会为大家解决疑惑的哦!

最近我也整理了一些Java资料,包含 面经分享、模拟试题和视频干货 ,都是免费的哦!如果感兴趣的话,欢迎 来私信~

文章来源:智云一二三科技

文章标题:Java大坑盘点!代码注释没写好,损失过亿(案例分析)

文章地址:https://www.zhihuclub.com/196936.shtml

关于作者: 智云科技

热门文章

网站地图