2023年阅读笔记2

发布时间 2024-01-09 16:06:07作者: wardream
  • 四、注解
    • 注解的缺点
      • 若编程语言足够有表达力,就不需要注释
      • 注释的恰当用法是弥补我们在用代码表达意图时遭遇的失败。注释总是一种失败
      • 程序员应当负责将注释保持在可维护、有关联、精确的高度,更应该把力气用在写清楚代码上,直接保证无须编写注释
      • 不准确的注释要比没注释坏得多
    • 注释不能美化糟糕的代码
      • 带有少量注释的整洁而有表达力的代码,要比带有大量注释的零碎而复杂的代码像样得多
      • 与其花时间编写解释你搞出的糟糕的代码的注释,不如花时间清洁那堆糟糕的代码
    • 用代码来阐释
      • 用代码解释你大部分的意图,很多时候,简单到只需要创建一个描述与注释所言同一事物的函数即可
    • 好注释
      • 法律信息
      • 提供信息的注解
      • 对意图的解释:提供某个决定背后的意图
      • 阐释:注释把某些晦涩难懂的参数或返回值的意义翻译为某种可读形式
      • 警示:有时,用于警告其他程序员会出现某种后果的注释也是有用的
      • TODO注释:注意要清理
      • 放大:放大某种看来不合理之物的重要性
      • 共API中的Javadoc
    • 坏注释
      • 喃喃自语
      • 多余的注释
      • 误导性注释
      • 循规式注释
      • 日志式注释
      • 废话注释
      • 可怕的废话
      • 能用函数和变量时就别用注释
      • 位置标记
      • 括号后面的注释
      • 归属与署名
      • 注释掉的代码
      • HTML注解
      • 非本地信息
      • 信息过多
      • 不明显的联系
      • 函数头
      • 非公共代码的javadoc
      • 范例
    • 五、格式
      • 格式的目的
        • 格式关乎沟通,而沟通是专业开发者的头等大事
      • 垂直格式
        • 短文件比长文件易于理解
        • 源文件也要像报纸文章那样。名称应当简单且一目了然。名称本身应该足够告诉我们否在正确的模块中。源文件自顶部应该给出高层次概念和算法。细节应该往下渐次展开,直至找到源文件中最底层的函数和细节。
        • 几乎所有的代码都是从上往下读,从左往右读。每行展现一个表达式或一个子句,每组代码行展示一条完整的思路。
        • 紧密相关的代码应该互相靠近
        • 除非有很好的理由,否则就不要把关系密切的概念放到不同的文件中,实际上,这也是避免使用protected变量的理由之一,应避免迫使读者在源文件和类中跳来跳去
        • 变量声明应尽可能靠近其使用位置,在函数顶部出现,循环的控制变量总是在循环语句中声明
        • 实体变量在类的顶部声明
        • 相关函数。若某个函数调用了另一个,就应该把他们放在一起,而且调用者应该尽可能放在被调用者上面
        • 概念相关。概念相关的代码应该放在一起。相关性越强,彼此之间的距离就应该越短
        • 我们想自上向下展示函数调用依赖顺序,被调用的函数应该放在执行调用的函数下面,这就建立了一种自顶向下贯穿源代码模块的良好信息流(能一开始就读懂整个程序的大脉络,不用沉溺于细节中)
      • 横向格式
        • 尽力保持代码行短小,遵守无需拖动滚动条到右边的原则,最好不要超过120个字符
        • 使用空格字符将彼此紧密相关的事物连接到一起,也用空格字符把相关性较弱的事物分开
        • 对齐,像是在强调不重要的东西,把目光从真正的意义上拉开
        • 如果有较长的列表需要做对齐处理,那问题就是在列表的长度上而不是对齐上
        • 程序员相当依赖缩进模式
        • 有时,while或for语句的语句体为空,如果无法避免,就确保空范围体的缩进,用括号包围起来
      • 团队原则
        • 每个程序员都有自己喜欢的格式规则,但如果在一个团队中工作,就是团队说了算。
        • 好的软件系统是由一系列读起来不错的代码文件组成的。他们需要拥有一致和顺畅的风格。
      • 六、对象和数据结构
        • 数据抽象
        • 隐藏实现关乎抽象,类并不简单地用取值器和赋值器将其变量推向外部,而是曝露抽象接口,以便用户无需了解数据的实现就能操作数据本体
        • 数据对象的反对称性
        • 对象吧数据隐藏于抽象之后,暴露操作数据的函数。数据结构暴露其数据,没有提供有意义的函数。
        • 对象与数据结构之间的二分原理:
        • 过程式代码(使用数据结构的代码)便于在不改动既有数据结构的前提下添加新函数。面向对象代码便于在不改动既有函数的前提下添加新类
        • 过程式代码难以添加新数据结构,因为必须修改所有函数。面向对象代码难以添加新函数,因为必须修改所有类
        • 得墨忒耳律(The Law of Demeter 也称迪米特法则)
        • 模块不应了解它所操作对象的内部情形
        • 方法不应调用任何函数返回的对象的方法
        • link:
        • 混合结构,一半是对象,一半是数据结构,应避免这种结构
        • 数据传送对象
        • 最精炼的数据结构,是只有一个公共变量,没有函数的类。这种数据结构有时候被称为数据传送对象,或DTO(Data Transfer Objects)。在与数据库通信、或解析套接字传递的消息之类场景中充当翻译角色
        • Active Record:一种特殊的DTO形式。他们是拥有公共(或可豆式访问的)变量的数据结构,但是通常也会拥有类似save和find这样的可浏览方法。
      • 七、错误的处理
        • 原则
        • 错误处理很重要,但如果它搞乱了代码逻辑,就是错误的做法
        • 使用异常而非返回码
        • 遇到错误时,最好抛出一个异常。调用代码很整洁,其逻辑不会被错误处理搞乱
        • 先写Try-Catch-Finally
        • 异常的妙处之一是,它们在程序中定义了一个范围。执行try-catch-finally语句中try部分的代码时,你是在表明可随时取消执行,并在catch语句中接续
        • 在某种意义上,try代码块就像是事务,catch代码块将程序维持在一种持续状态
        • 在编写可能抛出异常的代码时,最好先写try-catch-finally语句,能帮你定义代码的用户应该期待什么,无论try代码块中执行的代码出什么错都一样
        • 使用不可控异常
        • 可控异常的代价就是违反开放、闭合原则,得在catch语句和抛出异常处之间的每个方法签名中声明该异常
        • 可控异常意味着对软件中较低层级的修改,都将波及较高层级的签名
        • 给出异常发生的环境说明
        • 抛出的每个异常,都应当提供足够的环境说明,以便判断错误的来源和处所
        • 应创建信息充分的错误消息,并和异常一起传递出去
        • 依调用者需要定义异常类
        • 最重要的考虑是它们如何被捕获
        • 将第三方API打包是个良好的实践手段,降低了对每个第三方的依赖,也有助于模拟第三方调用
        • 定义常规流程
        • 特例模式(SPECIAL CASE PATTERN,[Fowler]),创建一个类或配置一个对象,用来处理特例,异常行为被封装到特例对象中
        • 别返回null值
        • 返回null值,基本是在给自己增加工作量,也是在给调用者添乱,只要有一处没检查null值,应用程序就会失控
        • 别传递null值
        • 将null值传递给其他方法更糟糕,除非API要求你向它传递null值,否则就要尽可能避免传递null值