什么是高质量的代码?
学习并整理一下个人的理解:什么样的代码是高质量的代码? 代码的评价指标这部分内容主要参考知乎上的回答:什么样的代码是高质量的代码? - 王争的回答 - 知乎。 简洁性 KISS原则:“Keep It Simple,Stupid” 我们需要通过尽可能简单的代码来完成目标,避免炫技地引入复杂的结构和设计模式。 典型的反例就是Java,完全的面向对象导致了代码架构的过度复杂化。例如程序员需要点一杯咖啡,Java 风格的代码如下 12345CoffeeFactoryBuilderSingletonManagerProvider.getCoffeeFactoryBuilderSingleton() .getCoffeeBuilder() .addMilk() .addSugar() ...
MATLAB 绘图笔记
这里主要关注 MATLAB 绘图的技术性内容,不讨论非技术性内容,例如论文中的绘图要求或偏好。 MATLAB 的语法学习曲线很特别:入门时用起来特别简单舒服,但是深入学下去就会感觉到语法非常混乱,无所适从。尤其在绘图部分,MATLAB 杂揉了命令式语句和面向对象的语句,存在太多的语法糖,毫无逻辑性可言。因此在这里记录一些关于绘图的代码,便于查找。 MATLAB 同时提供面向过程和面向对象(指定操作的 figure 或 ax)的绘图语法,面向过程的语法通过会直接获取当前 figure 或 axes 进行操作,面向对象的语法通常是在面向过程对应函数的第一个参数中传递 figure 或 axes。 需要说明的是,下文中的一些代码写法和常见的教程不太一样,包括: 将常见的命令语法都换成了可读性更高的函数语法,例如 hold on 换成 hold('on'),参考官方文档中的 选择命令语法或函数语法; 将早期的键值对语法换成了更简洁的形式,例如 plot(ax, x, 'DisplayName', 'energy'); 改成 plot(...
Git 使用规范
分支规范分支的命名习惯上使用小写字母、数字、连字符 - 以及斜杠 / 组成。这里建议使用斜杠 / 因为它会被Git自动识别,并且在 .git/ 中为其创建目录结构,例如 .git/refs/heads/feature/xxx。 复杂项目对于使用多个平行分支进行版本管理的复杂项目,分支的命名和使用通常遵循如下规范: 两个长期分支: 主分支:包括项目的所有正式版本,名称为 main 或 master; 开发分支:包括项目的最新版本,名称为 develop、dev 或 next; 几种短期分支:(向长期分支合并完成后即可删除) 功能分支:拆分为多个独立功能进行同步开发,名称例如 feature/login-page,feature/user_module; 预发布分支:在正式版本发布之前的准备,名称例如 release/xxx,xxx 代表日期;(改为 pre-release 可能更合适) 快速修复分支:名称例如 hotfix/xxx,xxx 代表修复的问题编号或描述。 关于长期分支的使用: 主分支和开发分支作为一组平行线长期存在; 主分支上的结点主要是发布的稳定版本,在...
Python 命令行参数解析 argparse
Python经常被用来写一下简化操作的脚本,并且要求脚本支持一定的选项,有必要整理一下Python命令行参数解析的用法。 Python自带的argparse模块功能已经非常强大,使用非常便捷。Python其实还有另外两个模块可以完成同样的任务:getopt和optparse,但是前者过于简单,后者已经被弃用,目前只推荐使用argparse。 与之形成鲜明对比的是,C/C++对这种基础的需求通常都是直接手写的,或者去下载一些第三方提供的纯头文件库,为这种简单的任务引入外部依赖其实也并不合算,不如直接自己写了。 极简例子从最简单的例子开始 test.py123import argparseparser = argparse.ArgumentParser()parser.parse_args() 这两行的含义为:设置一个参数解析器,解析参数。 直接运行脚本,无事发生 1python test.py 空的参数解析器为我们提供了--help(-h)参数,可以打印使用帮助,例如 1python test.py -h 输出形如 1234usage: test.py [-h]...
MATLAB 工程化编程笔记
MATLAB 被吐槽的一个重要原因就是大量 MATLAB 代码的质量一言难尽:完全脚本式编程、命名随意、结构松散、缺乏代码格式化、缺乏注释和单元测试。这类代码虽然能完成一次性的计算,却难以复现、扩展或维护,注定变成屎山代码。 本文关注如何让 MATLAB 代码变得工程化,使得 MATLAB 项目开发更有条理、更容易维护,具体包括输入参数检查、代码注释,单元测试等主题。 其实还应该加上日志系统,但是 MATLAB 并没有官方提供的,或者第三方广泛使用的日志系统。 函数参数检查为了得到健壮的代码,非常有必要对函数的参数进行检查,除了最基础的参数个数,还需要关注参数的类型和数据范围等,下面介绍几个MATLAB提供的用于参数检查的内置函数。 assert + isXXX最简单的做法就是基于 assert 和 isXXX 检查函数的形参是否满足要求,例如 1234567891011function func(u, t, f, n, b, flag, params) assert(isnumeric(u) && (isvector(u) || ismatrix(u)...
MATLAB 面向对象学习笔记
随着代码越来越复杂,我实在是无法忍受修改完全面向过程的混乱程序了,急需引入面向对象的语法进行重构。 笔记主要参考的是《MATLAB 面向对象编程——从入门到设计模式》(徐潇,李远),书中使用的估计是 2015 左右的版本。 MATLAB 的面向对象语法从整体上看,既不像 C++ 和 java 那样严格,也不像 Python 那样过于灵活,而是具有自身的特点。 虽然面向对象机制不可避免地会带来一些运算效率的损失,但是我认为这是值得的,只是需要避免在涉及大量计算的性能瓶颈中使用面向对象,对于程序中的辅助部分,使用面向对象所带来的代码简化还是非常舒服的。 简单示例从最简单的一个自定义类型开始 point2d.m1234567891011121314151617181920212223242526classdef point2d properties x y end methods function obj = point2d(x0,y0) if nargin == 0 obj...
MATLAB 学习笔记——4. 脚本与函数
.M 文件MATLAB 的 .m 文件主要分成两类: 脚本文件,不接受输入参数,它们处理工作区中的变量和数据。 函数文件,可接受输入参数,并且可以有返回值,内部变量是函数的局部变量。 除此之外,还有面向对象编程所涉及的类文件,这里暂时不做讨论。 MATLAB 对于 .m 文件的文件名有一些特殊要求: 文件名允许由字母、数字、下划线(_)和点(.)组成,注意不包括 - 和空格; 文件名必须以字母开头; 文件名区分大小写。 实际就是要求文件名也是一个合法的标识符,因为在 MATLAB 中运行一个脚本就是通过在终端输入脚本文件名来完成的。 较新版本的 MATLAB 提供了后缀为 .mlx 的实时脚本/函数文件,大致就是对 Jupyter Notebook 的模仿,但是用起来并没有后者那么好用,各种操作不够自然。由于 .mlx 文件不是纯文本文件,如果我们需要在 .m 文件和 .mlx 文件之间转换,必须通过 MATLAB 专门提供的工具进行转换,vscode 等编辑器也并不支持 .mlx 文件的显示。 脚本文件载入脚本文件会依次执行所有命令,在重复执行大量命令...
MATLAB 学习笔记——3. 流程控制与输入输出
流程控制在划分控制结构所对应的代码块时,编程语言通常采用如下三种做法: 基于大括号 {}:例如 C/C++,Java 基于 end 标记:例如 FORTRAN,MATLAB 基于缩进:Python MATLAB 受到 FORTRAN 的影响很大,也采用基于 end 的代码块标记,并不使用大括号 {} 来划分代码结构。 if 条件语句提供例子即可 123if x>1 x=1;end 12345if x>1 y=x;else y=1;end 1234567if x>10 y=x;elseif x>0 y=1;else y=0end 在 if 语句中通常需要使用与或非运算(不建议用 & 和 |) 123if cond1 && cond2 % ...end 123if cond1 || cond2 % ...end 123if ~cond % ...end switch 条件语句MATLAB 支持基本的 switch 语句,我们可以判断表达式的值以进入不同的分支,不需...
MATLAB 学习笔记——2. 矩阵
概述MATLAB 对于矩阵的支持非常好,以矩阵运算为代表的基本运算功能一直是 MATLAB 引以为自豪的核心与基础。我们可以把向量和矩阵都视作矩阵进行统一的操作。在下文中我们默认讨论二维矩阵,但 MATLAB 支持多维矩阵。行向量即行数为 1 的矩阵,列向量即列数为 1 的矩阵。 在内存中,MATLAB 使用列主序进行连续存储,与 Fortran 相同,与 C 语言是反的。在下标的使用中,MATLAB 默认下标从 1 开始,与 Fortran 相同,与 C 语言等绝大部分编程语言都不同。 矩阵的尺寸信息可以通过下面的语句获取: size(A) 行数和列数,返回一个1x2的行向量; size(A,1) 行数; size(A,2) 列数。 还有如下函数: numel(A) 可以获取(任意维度数组)所有元素个数; length(A) 可以获取向量的长度(也就是元素个数),但是扩展到高维数组的行为是非常反直觉的——返回最大维数长度,相当于max(size(A))。 注意: MATLAB 对于矩阵的支持是非常彻底的,甚至标量都是被视作 1 行 1 列的矩阵。 MATLAB 的很多...
MATLAB 学习笔记——1. 基础
基本语法注释:MATLAB 使用百分号%进行单行注释,使用%{...%}进行多行注释(不常见),使用%%开头的内容不仅是注释,而且会被视作节标题。(在字符数组中%仍然被用于占位符) 分号:; MATLAB 并不需要强制使用分号作为语句的结尾,以空格或回车结尾即可。不使用分号结尾时会把计算结果显示出来,使用分号结尾则会抑制计算结果的显示。 续行符:在第一行的结尾使用...可以把命令接续到第二行。(如果直接把...接在数字后面会报错,可以加空格) 命令补全:Tab 键。 对命令行窗口清屏:clc MATLAB 几乎所有数据都是矩阵:行向量是行数为 1 的矩阵,数是行数列数均为 1 的矩阵,甚至一个无效命令,它的返回值[]都是一个 0 行 0 列的空矩阵。 和其他现代编程语言类似: MATLAB 对大小写敏感,这与它所参考的 FORTRAN 不同。 MATLAB 对表达式中的空格不敏感,表达式中的空格通常被忽略。(只有bash这些异类才会对空格敏感) 和大部分现代编程语言不同: MATLAB 的索引都从 1 开始,而不是更常见的从 0 开始; 在 MATLAB 中,不等号是~=,...
