开发组织都会有代码规范。当我拿到一份代码规范,首先会去查看有没有对于单个函数最大行数做限制。如果没有这个最基本的约定,这份代码规范,在我看来几乎没有意义。
以Java为例,一个函数不应超过多少行呢?
大多数人都会说,函数不能太长,但也不能定死,要具体问题具体分析。再追问一下,有人会说,不超过200行,100行,50行,30行都有。另有人说,面向对象风格的可以短些,面向过程风格的可以长些。也有人说,一个方法不超过一屏幕就行(姑且不论显示器大小,字体大小和分辨率问题)。
先摘录一段Martin Fowler《重构》P110-P111 中的一段话:
引用
人们有时会问我,一个函数多长才合适?在我看来,长度不是问题,关键在于函数名称和函数本体之间的语义距离(semantic distance)。如果提炼动作(extracting)可以强化代码的清晰度,那就去做,就算函数名称比提炼出来的代码还长也无所谓。
说了直白点,函数名是干什么,函数体是怎么干。当2者不是那么能容易分辨出来时,就需要提炼出函数来,让代码更好懂。
既然马大师都说了,长度不是问题了吗,那干吗还要追究函数长度规范呢?
其实马大师讲的是对于懂得编程之道的人而言,不用关心长度,因为小函数是必然的结果。但在开发实践中,适当的函数长度限制值,可以给予我们警示,为什么这个方法写长了?哪里不对劲了?
对于这个问题我的回答是:Java函数不应超过15行。
为什么定这个数呢?
一方面,这个是基于多年开发实践的总结。15行其实已经是一个比较宽松的标准,开发人员稍加培训就可以实际贯彻,而符合这个标准的函数也能达到良好的可读性。
另一方面,这是基于对函数复杂度和代码行数之间关联关系的认识。
我采用一个简单的数学公式(注1):
引用
函数复杂度 >= 代码行数^2
以下为了简化,只以最低增长方式,平方数进行计算。
以一个函数的行数,从1行到20行为例,见下图:
当函数行数到达10行以上,函数复杂度就开始大幅度攀升。
当代码行数达到20行时(复杂度400),其复杂度已经是14行时(复杂度 196)的2倍。
因此我将代码规范定在15行。
下面我们运行此公式,来分析一下提炼小函数的好处。
例如,有1个100行的函数,分解为11(含自身)个10行的函数。
原复杂度= 100^2=10000。
分解后复杂度= 11×(10^2)= 1100。
分解后的复杂几乎是分解前的 1/9,几乎降低了1个数量级。这就解释了为什么长方法分解之后,可维护性大幅度提高。
再运用此公式,来观察那些现实中的长函数。
函数长度(Line) | 函数复杂度(Unit) | 10 | 100 | 15 | 225 | 20 | 400 | 30 | 900 | 50 | 2500 | 100 | 10000 | 500 | 250000 | 1000 | 1000000 |
也就无怪乎有同学表示维护1000行以上的函数,有种生不如死的感受。
注1:
该公式参考于 gerald m. weinberg 《质量·软件·管理(第1卷)——系统思维》
- 大小: 14 KB
分享到:
相关推荐
“本书向你展示了提升Scala技能的方法和理念,它已超过‘更好的Java’。” ——Fernando Dobladez, Code54 “里面的练习有些挑战,很有趣,对你在真实世界中使用它很有益。” ——Chris Nauroth, ...
Java 把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的 一些基本类型...为这个变量分配内存空间,当超过变量的作用域后,java 会自动释放 掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。
在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存...
试题 算法训练 二元函数 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 令二元函数f(x,y)=ax+by,a和b为整数,求一个表达式S的值。... S的长度不超过50,运算过程中所有变量不会超出int的范围。 pack
试用java.util.Stack泛型栈作为父类,用另一个泛型栈对象作为成员变量,模拟实现一个泛型子类Queue,当存储元素的第1个栈的元素超过dump时,再有元素入队列就倒入第2栈。除提供无参构造函数Queue( )外,其它所有队列...
1. 定义一个学生类Student,包括:属性学号,姓名,性别,年龄,方法包括构造方法初始化变量;显示学号方法、显示姓名方法、显示性别方法、显示年龄方法、修改年龄方法。 2. 定义一个测试类StudentTest创建两个学生...
栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动 释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。 堆内存用来存放由 new ...
《LLH-Graphics C++图形函数库》使用说明 1 前言 博大纾深而又高度灵活的C++语言的对于程序...而同样流行的Java或者C#,只用不超过10行代码帱可以生成一个漂亮的GUI窗口。在窗口区画条线或者画个圆更是易如反掌。
GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收...
坑1:Java的字节从-128到127,因此给其赋值超过127会报错;DotNET的字节从0-256,无此问题。 坑2:Java没有PKCS7Padding,只有PKCS5Padding。因此DotNET的BlockSize只有为8,才可与Java兼容。 坑3:Java的字符串转...
看不到源码Muster - 集中您的 Java AWS Lambda 函数 概述 Muster 是一个概念验证框架,旨在简化 Java 中的 AWS Lambda 开发和部署。 它旨在克服使用 AWS Lambda 而不是传统应用程序服务器的一些问题。 Muster 尚未...
1.可以连续输入运算,对于输入的表达式能够按算符优先级进行处理。如输入2+3*2时输出为8,而不是10。...5.错误提示,除数为0,应算超过范围等在下方将有文字提示,并将当前结果置零。 6.支持小数点,支持正负运算。
String中==与equals区别验证!...当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
Java面试 Java超级经典100问题 Java高级开发工程师必备 Java面试宝典 1.赋值运算函数.2.单例设计模式.3.二维数组中查找目标值、4.替换字符串中的空格。5.从尾到头打印链表.6.由前序和中序遍历重建二叉树.7.用两个栈...
里面包含以下题目的答案: 本次上机考试时长 90分钟 上机操作试题随机选自以下题目,请按照分配的题目完成上机操作,多做,不做或是自行选择题目均不得分。...编写一个函数MyRandom( int n )随机生成5个不超过n且
Java把内存划分成两种:一种是栈内存,一种...当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
设计一个学生类Student,其中的属性有:学号stunum、姓名name、性别Gender、年龄age。方法包括:设置学号、姓名,取得性别、年龄。利用学生类,创建一个对象,描述自己的所有属性。
主要介绍了java中超过long范围的超大整数相加算法(面试高频),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
文件上传工具类,上传文件,上传导入文件到path文件夹下,判断图片大小是否超过要求,上传多张图片到服务器,上传图片到服务器,上传文件(在指定目录下创建年月日目录),上传导入文件到temp文件夹下,删除指定...
HashMap是Java中非常常用的一种数据结构,它实现了Map接口,用于存储键值对。HashMap内部使用哈希表来实现,通过将键映射到哈希表中的一个位置来快速查找和插入元素。 HashMap的主要特点是: 非线程安全:如果多个...