代码整洁之道 万字总结+个人项目经验

  • 软件工程作为一门学科,他们的目的是为了多人合作可以写出好的代码,同时也是为了我们的代码能够更方便的修改和维护,如果我们对某种架构设计有想不通的地方,不妨在这个方向思考一下
  • 我们不可能了解一个大型系统的全貌,那我们执行自己的任务,但是不影响系统的整体稳定呢?
  • 系统在开发的过程中,我们一般会遇到如下几种情况
    • 本来很简单的需求,却要进行长时间的改动
    • 本来改几行代码的事情,缺影响到了其他模块的运行
  • 什么是整洁的代码?
    • 代码的逻辑应该直接了当,命名应该相当贴近实际,加缺陷难以隐藏
    • 尽一切可能的减少代码的耦合
      • 我发现即使到现在,我对这个概念也只是停留在概念之上,我其实并不知道,什么是耦合,怎么设计可以减少耦合
      • todo
    • 依据某种分层战略完善
      • 经历了从面向过程到面向对象的思维转变,我对分层理解仅仅是每一层的职责明确,像流水线只处理自己的事情,还有就是可以替换成其他作用相同的层,具有组装
      • todo
  • 命名规范真的非常重要,它能我们能够更加清楚的编写我们的代码,让我们感觉不像是编程,而像是和计算机对话,而且命名要统一,不要出现同一事物的命名规范不同
  • 整洁的代码只做好一件事
    • 一个类只处理一个类应该处理的事情,当我们用了一个类的get和set方法的时候,我们应该考虑,这个事情能不能让那个类自己处理。调用类的多个方法实现某个功能的时候,我们也要这样考虑。
    • 比如我们的service层的业务逻辑,我们调用了想多的方法,其实其中有好多方法都是重复的,这样的贫血模型何谈整洁
    • 以及controller层的参数校验,我认为应该单独抽取一个对象出来,有时候我们直接把DO放入,我们还得在文档中指明,哪些参数不用传递,然后还得做默认值。
    • 对象的转换怎么做,我们可以用构造方法,也可以定义一个静态方法,获取对象的示例,后者的语义更明确一些
    • 这里面有一个问题,就是容易忘记属性的赋值,我们最好的办法就是在挨着自己对象的属性,一个一个赋值,如果自己对象中没有相关的属性,那我们赋值还有什么意义
      • 关于赋值这块,谈两点经验,一个是方法的get和set方法,我们得确定这个对象完成是由我们自己管理的,一旦涉及到和json的互换,数据库的互换,那些框架可能调用我们的方法(利用反射)做一些我们意向不到的事情,那我们要换名字吗?不,我们可以加注解让他们在反射的时候绕过我们的这些方法,我这里这样说,主要是为了提醒你,应当注意这些内容,出现错误的时候,可以从这里着手解决问题
      • 一个是,一旦我们新加了属性怎么办,我只能说,太好办了,因为我们关于这个对象的转化都在这个对象本身,所以相关的细节都由我们来决定,删除一个属性呢,那更好办,甚至都不需要我们去关注具体某个对象的修改(所以我们最好在这些方法注释这是关于哪些对象的转换),直接把他们报错的删掉即可
      • 关于DDD,它抽象出了一套领域模型,我们完全可以把它理解为BO对象,我们可以用建造者的设计模式,用几个类去手动的传入并得到他,我们也可以用mapper直接把他们多表查询查询出来,甚至我们可以根据业务的需要,个性化的定制这些内容
    • 如果你在考虑那种方式更好,那么你最好想想,在这个需求不断变换的时代,什么样的设计方式,能够以不变应万变
    • 一个函数就应该只处理好自己的事情
      • 对于哪些能抽离出去的函数,我们在service层面就应该抽离出去
      • 其实最好的应该让类来完成那些功能,我们直接操作数据库其实并不多
        • 这里你要注意一点,是否应该抛出异常让service来处理,还是service无法处理,直接让全局异常处理器来处理,但是,你要特别的注意事务,尽量那些让service自己处理的,抛出Exception方法,而哪些程序无法进行的,让他们抛出运行时异常,让事务回滚
      • 而且最好抽离出来的小方法最好也是public,那种可以被别人复用的方法
      • 谈一下日志的处理,日志的目的是为了让我们快速的定位到问题,那我们在对象里面做了处理,怎么处理日志呢
      • todo
    • 每一层应该着重处理自己的事情,我谈谈mvc三层架构,每一层应该处理的事情,以及这样处理的原因
      • controller层
        • 参数校验
          1. 参数的校验和业务逻辑无关
          2. 这种参数校验基本是没有性能损耗的,可以快速失败,返回结果
          3. 可能我们多个controller调用的service相同,但是校验的方法不同(
          4. 最好让对象自己校验参数,然后提供updateCheck和saveCheck,可以是返回单个,或者返回多个,可以是抛出异常,或者返回一个列表,下面给出最佳实践
            • todo小问题,有时间再好好想一想
            • 字符串不能为空,字符串长度有限制,字符串前后的空格要减掉
        • 对象转换
          • 比如我在controller层用对象接受了一个json,然后我们调用的方法是普通参数,我们可以在这里做转换,或者反过来。
            • 为什么要这么做,我们应该思考一下,对象和普通参数的区别,很简单,那就是对象是有方法的,比如我们保存的时候可以直接保存这个对象,但是这个对象的很多参数都是不需要传递的,我们可以选择用json也可以用两个简单的参数,但是json需要转换,参数不需要,但是对象可以有方法,这个得依据实际情况权衡
          • 还有就是VO对象的转换,用流转换
            • 我们的查询service,返回的数据应该尽可能丰富,然后我们在controller层面做对应的转换,把部分业务逻辑转义到controller层,这样的设计有问题吗?
              • 思考一下,如果我突然多了一个参数需要获取,我们得重写service查询,那其他地方会受影响吗,我想说,不会,因为你没有修改和删除,只做了添加
              • 删除呢,更不影响了,直接删掉字段,把爆红的方法删除就可以了
              • 其实你不用太担心这个问题,这种情况出现的并不多,无非就是一个字段,在不同的地方,显示的要求不同,大不了,我们再加一个service来查询
              • 那种一个resultmap就能查询出来的,我们当然通过servie获取mapper然后直接调用vo方法,这样需要修改的地方,还是比较少的,当然不排除mybatis不能实现复杂的东西,我们再包装一层service,做一步逻辑处理,这种逻辑处理就不要在controller里面做了
      • service层
        • 处理业务逻辑
          • 在这里写业务逻辑,是可以复用在多个controller里面,或者其他组件(切面或拦截器等等甚至可以是实体类),或者核心业务的service里面的
          • 而且这里的业务逻辑支持dubbo的远程调用
          • 但是controller统统没有这些有点
        • 事务控制及回滚
          • 复杂的事务控制就是在这里实现的
        • 并发控制
          • controller的事务控制粒度太粗了,不适合做精确到并发控制,因为一次只能让一个人来访问,所以这里的控制粒度要求还是比较高的
        • 缓存
          • 查询接口加上缓存是再好不过了,他能让你的系统处理能力上一个台阶
      • mapper层
        • 这里完成增删改查的方法
        • 说一些个人经验
          • 不要在SQL里面出现常量,尽量不要用SQL提供的now(),我们可以在service里面为这些内容赋初始值,但是你要记住,这么做的目的是为了让SQL复用的程度比较高,如果我们的SQL的常量不是这个,那这个SQL毫无意义,那最好还是写成常量吧
          • 但是now这种最好自己传递一个日期进去,因为数据库的时间有时间并不可靠,他的时区可能是错误的,我们最好自己弄,我这时区方法吃过亏,没想到本地导出的SQL时区竟然不是东8
          • 此外,想彻底解决时区问题,我们存时间戳,时间戳是没有时区问题的,而且我们把时间戳返回给前端,前段可以根据当地的时区做国际化处理
          • 我们知道mybatis有条件构造器,我举一个例子,比如查询考试,我们可以指定某一天的,可以指定某个时间段的,而且可以只指定一端。虽然只有where条件不同,但是我还是建议你把他们分开写,配置一个resultMap就可以了
  • 思考到一个问题,就是我们是应该调用函数还是应该重新写一份
    • 这个问题扩展一下,就是我们应该是使用调用同一个,还是各自复制一份
    • 无论在什么情况下,他们直接都是精密关联的,要修改一个就直接修改另一个,这样的放在函数里面最好,推荐重写,重写并没有错,只是为了修改的时候不影响其他,但是!你有没有想过,即使我们一开始用的函数,然后我们发现某个地方调用这个函数需要特殊处理一下,我们其实完全可以另外写一个函数,然后做对应的事情,我也回忆起来,高聚合低耦合,正是我学习函数的时候所了解到的。如果有问题,我觉得很大的原因就是,一个函数干的事情太多了!
  • 可扩展是代码设计的难点,一般是用接口实现的,spring中是自定义bean和继承某个类然后重写方法,这是一个大型框架必不可少的
  • 代码整洁从消除重复代码出发,不要让我们的类都是public方法,适当的private方法能让我们的代码更加清晰,一句话,重复是一切思维的本源
  • idea提供了Extract 功能,可以很方便的帮助我们抽取方法,而且可以修改其他冗余出来的方法,都是全自动的,还是就是命名,想改就改,这种修改借助idea重构,对代码毫无影响,甚至还有包的位置,随便改,至少,我们在新建或寻找一个类的时候,能够很方便的找到,他在哪里
  • 程序等于数据+算法,对象就是属性+方法,那你有没有想过,属性在方法可以包裹在多个类中呢,通俗一点来讲,我们其实可以把类分解成更多的类,这样我们代码的可读性会进一步提高,而实现后续复杂功能的时候,也更加方便,唯一专一于一件事情,我们才能支撑起更复杂的要求
  • 用函数和面向对象的特性消除重复,用良好的命名来提高代码的表达能力,这是代码整洁之道和核心所在
  • 还有就是抽象,这个比较难,我打算在接下来的阅读中慢慢体会
  • 突然想到了接口的一个好处,做一下记录,希望以后能将这种思想用到其他地方
    • 我返回给前端的数据是有统一格式的,所以用一个类包装了一下
    • 我后面发现了一些新的需求,比如我传递一个errEnum,或者抛出一个自定义的异常,我有如下几种选择
      1. 在函数中处理一下,把这些变化成统一返回类可以接受的参数
        • 这个明显不行,重复的代码太多了
        • 弄个函数?
        • 给一个非常好的建议,你在弄函数的时候,最好想一想,这个函数弄在某个类内部,会不会更好一些
      2. 统一返回类继续重载一些方法,就是我上面提到的把方法在类内部,目前是怎么用的
      3. 今天我突然想到,能不能用接口实现这个扩充,我们让枚举或异常类实现一个接口,这个接口用来构造我们的统一返回类,我们在统一返回类重载一个方法,传入这个接口,然后调用接口的方法构造我们的目标类。这样我们只需要在接口层面扩充,会非常方便,这就是接口的强大之处
  • 后期有很多工作还是修改维护和添加新的功能,这就需要我们去读前面所写的代码,所以让代码更易读,是能让我们后期写代码,加功能更轻松的手段
  • 命名
    • 名副其实
      • 甚至可以为了更好的命名,用工具替换原有的命名
      • 类名要加分类后缀,主名称要提现他的作用,或者他承载了哪些数据
      • 名副其实到不需要注释来补充的状态,中文的注释,该加还得加
      • 尤其是那种逻辑比较复杂的,你会发现变量名起名很重要
        • 代表它在这个逻辑下的含义,在其他逻辑的地方可以不一样(考试调换的双方)
        • 名字不要怕太长,长没有任何问题,但是你起的名字不能有太大的冲突,就是一个逻辑(函数)内,有两个相似的命名,一旦混在一起,还是非常麻烦的,最好前缀区别开,因为前缀一般是我们最先输入的字符
      • 函数名要能一眼看出他的功能是什么
      • 名称中不要出现那些抽象的命名,要具体一些,所以我们在起名的时候,要特别留意一下,只有你不断地留意名称,你的代码才会写的更好,有意的琢磨一下命名
      • 不要出现任何常量,用静态变量指过来,这样修改和看代码的时候会非常方便,所以,不要出现常量,你在看机器人足球代码的时候就会发现,常量真的非常让人讨厌,很难读懂这些常量是干什么的,所以,不要这样做,不要出现常量
      • 逻辑判断,我们逻辑判断的语句,尤其是那些复杂的,要提取出来,这样读者可以下看懂你这个if想要判断是什么样的逻辑,有意的抽取if判断中的复杂逻辑,注意我指的是别人一下看不懂的核心业务逻辑
      • 学会把代码中的一些内容抽象出来,让一个对象来负责,加大面向对象特性的利用,用对象抽象代码逻辑就是把一部分逻辑交给一个对象来处理
      • 说一些,额外的要求
        • 英语要好好学一下,我们的词汇量必须足够丰富,不懂的上网查,然后记住它
        • 命名的时候一定要好好琢磨一下,这个真的太重要了
    • 如果包含xx的容器并非一个真的list,那不要用xxlist来给程序起名称,因为list对我们来说有特殊的含义,我们会认为list包含有add或者其他集合方法
    • 不要用数字来区别,不要用Info,Data这种毫无意义的词汇来修饰
    • 不要在命名中出现废话,比如NameString这样的变量名,我们知道Name一定是一个String
    • 你要知道,编译器是有搜索功能的,所以我们在命名的时候,最好不要太短,就是不要一个字母或者这个单词很容易组合在别的单词中,不好搜索的那种
    • 相同的概念尽可能使用相同的词汇,要形成自己的命名规范
    • 不过,命名冲突的可能性确实很大,所以我们可以用后缀来区别这些内容
  • 有些简短的复用性不高的代码,我们其实可以用注释来说明一下,注释还是要有的
  • 函数
    • 短小,我们每个函数要尽可能的短小,但是不要因为这个而增加代码的复杂度,你有想过,如果我们想在这里弄个不合法消息返回给前端,该怎么设计吗
    • 抽象层级,每个函数只处理自己抽象层级的事情,其实你做的mvc三层架构就是这样,流水线生产
    • 给函数的命名最好要能指出这个函数干了什么事情,所以我们的函数最好短小一点,当函数短小的时候,我们才能够方便命名我们的函数
    • 我发现自己没有主动使用函数的习惯,平时要多加使用和体会函数
    • 我们函数的参数数量越少越好,这一定程度也就意味着,我们函数的职责比较单一
    • 尽量不要出现那种,把一个参数丢进一个函数,然后这个参数的属性发送变化的函数,因为这个很难让人想象到你是这么设计,而且,如果你这么设计,你完全可以把这个函数当成那个参数对象的方法
    • 标识参数,很不推荐这样做,这种就应该被扼杀在底层,比如sort,最好是sortAsc和sortDesc
    • 函数的参数是会产生排序问题的,所以函数的参数尽量越少越好
    • 那么这么减少函数的参数呢
      • 把比较相近的函数抽象成类
      • 把传递类的函数,改变成一个类的方法
    • 不要在函数中做多余的事情,因为你在调用这个函数的时候,有可能会发生一些意味,最好的是,你用另一个函数把两个小功能合并在一起
    • 从一个简单的角度考虑,增删改查肯定是不能放到一个函数中去实现的,我们最好把这些分开,对于字典来说,我知道现在编程语言提供了一些saveOfupdate之类的便利,但是可读性最好的还是先查找,然后再操作,比如数量统计的字典,这样的效率很高
    • 用异常来代替错误码,错误码需要我们去判断,但是异常可以让jvm托管,我们从来不在乎这些指令执行的性能损耗,真正会损耗的性能的是磁盘读写和网络io以及并发锁粒度,也就是说,你做的很多优化,对于用户来说是体验不出来的,除非你做了缓存,算法做了优化
    • 对于那些可能发生异常的函数,我们要用Try-catch来处理它,这个时候要主动抛出异常,是让系统处理还是让函数处理,我们在一开始就应该想明白。Throwable才java的顶级异常类,如果你抛出运行时异常,那么java是不会捕获的,在事务中抛出运行时异常来回滚
    • 重复是我们优化代码的根源
    • 好的代码不是一次写出来的,而是不断的琢磨自己写的函数,然后去修改它,所以,现在就可以看看自己以前写的代码,然后想办法去优化它,我们尽可能的一次性写出,这样我在写的过程中会很舒服,具体来说,小步快跑我们写好一个函数,就赶紧投入修改,然后开始测试,只有我们确定现在写的代码没有问题,我们才能写出稳定而完善的系统
    • 函数有一个好处就是他能够随时return而终止这个函数,如果我们纯写代码的话,可能需要弄一个flag然后写一些比较麻烦的判断
    • 链式编程很好,但是那种不给中间变量起名字,然后把他们贸然拼在一个语段中不是一种好的行为
    • 你的函数不要有太多的缩进,太多的缩进说明你写的逻辑判断太过复杂,这个时候就需要学会抽取函数来化简了
  • 注释
    • 改代码的时候,注释也要改,我们提供的注释万万不能和代码想要表达的含义相反,因为如果这个函数不出错的话,我们肯定是会优先看注释而不是去阅读一个函数
    • TODO注释很重要,我们可以利用现代编译器做好多事情,而且我们要不定期的看和处理这些注释
    • 代码表达力不够就用注释来弥补,我不太赞同作者的观点,毕竟我们是中国人,看中文还是会更爽的
    • 有的时候,因为java没有运算符重载,所以我们加一些运算符注释也是不错的
    • 不要加废话注释,如果你的代码别人一眼就能看懂,那就不要注释
  • 你得学会使用git每次测试通过和修改通过,都需要git自己的代码,并且做好良好的描述,你得确保我们随时会回滚,这真的是一个很重要的习惯
  • 不同逻辑段之间要有空行,有注释也要空行,能空行的地方就空行,现在按逻辑段空行,慢慢的,我们就会发现,这些逻辑段可以处理成一个小小的函数
  • 属性放在最上面,然后是构造方法,然是公共方法,逻辑密切的要放在一起,被调用者应该尽量放在下面,至少,我们写的时候,也是先写函数然后写被调用的函数
  • 注释会让你的代码显得比较专业,最好多加一些
  • 我们不想让别人随便修改我们类的变量,所以我们把这些属性设置成了私有,那为什么我们要给这些属性对应的get和set方法呢
    • 其实,并没有人要求给每个属性都有get和set
    • 也没有人要求,我们在get和set的时候,只能获取或者传入一个变量
    • 方法和属性在修改和获取属性的时候,他们之间唯一的区别就是,方法在再获取和修改属性的时候,可以对这些参数或者结果进行一定的处理
    • 你会发现,其实很多类没有什么直接操作get和set方法的函数,所以它们的内部设计可以很好的修改,我们的只不过是一个javaBean,一个数据的承载体而已,所以我们加了这些方法
    • 所以一个框架的set和get不能乱加,尤其是set
  • 一个类只能操作与它直接相关的类,如果必须操作非直接关的类,我们可以把他变成直接相关的
    • 比如你弄一个VO返回前端,与其你调用service获取mapper,然后再调用mapper获取vo的方法
    • 不如你直接把mapper注入进来,然后直接调用,因为修改和添加的时候比较方便
    • 或者你最好在service里面包装一层,这种包装无非就是弄了一个一模一样的函数包装上去,而且你在做调整的时候也比较好修改
      • mapper函数的名称最好起的像是怎么操作一个数据库
      • service函数的名称最好起的像是处理什么业务,意会一下吧,应该我们的service可能会有多个函数调用同一个mapper
    • 什么是直接相关的
      • 一个类的方法,可以操作这个类的数据
      • 可以操作它自己创建的对象(最好不要这样,除非是辅助对象)
      • 可以操作一个通过一个参数传递过来的肚子
      • 操作这个类的其他方法,最好是私有方法
    • 如果我们可能返回的异常情况不止一个,那么就用特殊处理,用catch来分别处理对应的异常这样做比返回一个错误的状态码要优雅的得多
    • 不要在for循环里面执行try-catch,因为异常的开启是有性能消耗的,但是我们可以用try-catch来包裹一个for循环
    • 当我们对第三方类打包的时候,我们其实是在降低对它的依赖,如果我们换了其他功能类似的第三方包,只要我们修改了我们包内的代码,那我们就不需要去处理其他的问题
      • 而且你在封装api的过程中,也对api的调用进行了化简,把形形色色的接口变成了你最熟悉和觉得方便的接口形式,最简单的无非是适配你系统的工具类
      • redis工具类很常用,因为我们发现,我们其实并不会利用原来提供的那么多强大而复杂的方法,甚至redis用一个函数把他们分类之后,操作起来仍然是非常复杂,我们很多时候跟本用不到,所以我们需要自己封装工具类
      • 我很喜欢看别人封装的接口设计,因为这样的设计能让我学到很多,我一直希望有一种非常好用的接口格式,我目前收获最大的就是链式编程
    • java中最常见的异常就是空指针异常,这也是要告诉我们,平时要多在意对null的处理,然后就是比如返回列表,但我们没有返回元素,这个时候,我们返回空列表Collections.emptyList(),比返回一个null要好的多,因为我们处理一个列表,一般是遍历,很少会出现get(0)这种,一般这种情况要自己封装在函数内部
    • 我还发现java的好多工具类是以s结尾,然后与前面的类对应
      • 这种工具类的意义是什么,为什么不直接写在类中
      • 首先,直接写在类中的方法有个致命的缺陷,那就是当对象为null的时候,你是不能执行这个方法的
      • 然后就是,这个方法放在对象里面并不合适,比如把这个list变成一个线程安全的list
  • 单元测试
    • 写单元测试的好处就是,我们能一次运行,就知道我们以前写的代码会不会出现问题,就是说新写的代码影响了之前写的代码
    • 但是,有的时候,测试代码的编写难度还是比较大的,而且一个方法可以对应多个测试代码,工作量确实很大
    • 并发测试最好的办法就是sleep,这样模拟出来的并发,我们才能观测到他的具体情况
    • 我真的发现,好多以前很好解决的问题,看似很好的解决方法,在不断的要求修改,业务增加,代码量上升,分布式系统,并发问题等等,我们依靠很多经验,我们得去理解它,而不是照着他的要求去做,因为历史告诉我们,被淘汰的实在太多,太多了
    • 测试代码编写的流程
      • 构造测试的数据和环境
      • 操作我们的方法
      • 结果进行校验
    • 把公共函数调用的私有函数工具放在后面
      • 别再往上面放了,还得按那么多空格
    • 类中的方法也不应该太多,接口类除外(这个是我加的)
    • 面向对象就是不去操作数据,而是让数据有自己的行为,能理解这一点真的很重要,因为现在的web开发,让很多人失去了面向对象的能力,把类当成了承载数据的结构体
    • 如果我们的部分函数,抽离出小函数后,总是绑定的操作几个变量,我们可以思考一下,是否可以把这个变量弄成一个类,让这个类去操作它
    • 其实不如看设计模式的书
  • 因为有些对象的构造过程相当复杂,而且对象的构造本身就不应该让我们来完成,在真实的世界中,对象是由各种各样的专业工厂来提供的,而有些对象是由神创造的(Ioc),所以我们要把对象的构建和使用解耦合,更何况有的对象强制是单例模式的
  • spring中的拦截器和AOP
    • 拦截器有个around方法,它是before返回false后执行的方法,其实aop也能实现,拦截器比较偏向于网址通配符,而且AOP可以结合注释和方法通配符
  • 并发
    • 并发不一定会比单线程快,并发会在性能和编写额外代码上增加一些开销,比如redis早起使用的是单线程,保证了原子性
    • 并发会产生的问题并非总能重现,不要把这些问题当做偶然,在大数据的情况下,会产生很大的问题
    • 一个程序由单线程变成并发,可以需要对设计和策略做出根本性的修改
    • 并发解决方案
      • 数据复本
        • 思路: 我们修改同一对象会冲突,那我们复制多个,每个线程操作一个
        • 多线程处理(处理数据复本)
        • 单线程整合
        • 提示:我们需要考虑一下,对象的创建和垃圾回收,和锁哪个成本更低
      • 数据作用域
        • synchronized 要细化一些,会很难但是很有必要
      • 最好让线程独立,不要让它们共享数据
    • 并发模型
      • 生产者-消费者模型
        • 生产者和消费者都有一个或多个,他们共同操作一个限定资源
      • 读者-作者模型
        • 更新少,但是读取比较多,在修改的时候不能读取,读取的时候不能修改,因为得保证数据的一致性
        • 做缓存的话,这种情况很常见
      • 宴席哲学家
        • 线程争夺资源,尤其资源它不止一个
        • 死锁
    • 后面理解不太懂,等进一步看多线程再做总结,写的很偏向解决实际问题的方法,非常有用
  • 我们程序开发中有一个很常见的问题,如果我们的某个类的类型变多了,那么我们需要修改好多处代码来实现相对应的结果,而且,最关键的是,我们其实根本不知道怎么修改,修改哪些地方,所以我们得反转这种控制权限,让哪些类自动去实现
  • 提额外的一点,除了要保证我们将要处理的对象不能为null,我们还需要保证一件事情,那就是,我们传递给函数的对象也不能为null,除非它说可以传递null值,因为有的函数是不会处理null值的,因为这个值会让我们的函数看起来和臃肿
  • 这本书有个对某种功能类的逐步修改过程,过程非常的详细
    • 学完设计模式,打算自己做一遍
  • 文章末尾做了好多总结,我基本都总结到了,这里补充一些没有的
    • 一个函数如果是接口级别函数,就是专门给别人用的,那他就应该处理好各种边界条件,这个一个程序改有的严谨
    • 不要搞错分层,不要在controller层面写业务,因为你很容易找不到为什么会这样,反正就是不方便别人找,而且对其他层也会产生不同的影响
    • 类库不要暴露过多的方法,你的接口越少,需要传递的参数越少,使用起来越简单,能自动处理的事情越多,就能越容易受到别人的喜爱
    • 命名规范要前后一致,虽然命名可以不同,但是真很重要
    • 尽量不要用一个类的get和set方法,尤其当出现两个的时候,你真的应该好好考虑,是不是应该把方法放在类里面
    • 用多态和其他设计模式代替if-else或switch-case
    • 宁可通过命名把x.isEmpty改成x.isNotEmpty最好不要弄!(xx)这种,不是很方便理解
    • 17章节全是这些,建议你在以后的编码过程中,慢慢的去渗透这些良好的编程规范,而且不只是新的,你要分析旧的代码,从那里思考怎么去修改,因为好的代码绝对不是一次就能写出来的,而是要经历过不断的修改
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java代码整洁之道是指编写易于理解、易于维护、可扩展性强的高质量代码的一系列准则和实践。以下是一些Java代码整洁之道的要点: 1. 命名规范:使用有意义的变量、方法和类名,遵循驼峰命名法,并避免使用缩写和单个字符作为名称。 2. 函数和方法的简洁性:函数和方法应该尽可能短小,只做一件事,并遵循单一职责原则。避免过长的函数和方法,可以通过提取子函数或方法来减少代码复杂性。 3. 注释和文档:使用清晰的注释来解释代码的意图和逻辑,但不要过度注释。另外,编写良好的文档注释,以便其他开发人员能够理解和使用你的代码。 4. 避免重复代码:重复代码会增加维护成本,应该尽量避免。可以通过提取公共代码块为方法或函数,或者使用继承、接口等方式来实现代码的重用。 5. 异常处理:合理处理异常情况,避免捕获所有异常或忽略异常。根据具体情况选择合适的异常处理方式,例如抛出异常、记录日志或返回默认值。 6. 单元测试:编写单元测试是保证代码质量的重要手段。每个方法都应该有对应的单元测试,覆盖各种情况,确保代码的正确性和稳定性。 7. 代码格式化:统一的代码格式可以提高代码的可读性。使用合适的缩进、空格、换行等格式化规范,并使用代码格式化工具进行自动格式化。 8. 设计模式和面向对象原则:熟悉常用的设计模式和面向对象原则,如单一职责原则、开闭原则、依赖倒置原则等,合理应用于代码设计中。 9. 持续重构:随着需求的变化和代码的演进,及时进行代码重构是保持代码整洁的关键。通过重构,可以改进代码结构、提高可读性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值