注册一亩三分地论坛,查看更多干货!
您需要 登录 才可以下载或查看附件。没有帐号?注册账号 
x
TL;DR 定义多个功能单一的函数,并命名以readable function name
相信大家都认同一点:越复杂的代码,出现bug的几率越高
楼主建议大家做的,就是用尽量简单的代码实现solution
以LC 388 为例,楼主为每个子逻辑都定义了函数。(文章末尾有代码
比如判断一个字符串是否是文件名:如果里面有 ".",就是文件名,如果没有,就不是
很多同学(包括以前的楼主)喜欢直接写- if strings.Index(s, ".") != -1 {
- // do something
- }
复制代码 单独看这一段代码,没什么问题。但是把放到整体代码里面我们就需要做一次思维转换,查找一个字符串中是否有 "." 是在判断这是否是一个文件名
楼主非常喜欢一句话:“程序写出来是为了让人看懂它的算法,附带告诉计算机如何执行” ---- 《黑客与画家》
我们为每个子逻辑定义函数,就是为了让主函数看起来更像自然语言。这样,写代码和阅读代码需要的思维复杂度也就更低,即我们写出bug的概率更小。
我相信,再聪明的人,写的代码多了(需要考虑的事情多了),一定会出现bug。
我想做的,是在实现功能的前提下,思考尽量少的逻辑。
主函数只是一些子函数的拼接,看起来像是自然语言。我们阅读自然语言,肯定更容易发现bug
而子函数内部只专注于一个功能,我们看看自己写的代码,再看看函数名,也更容易写出bugfree的代码
反之,所有逻辑都堆积于主函数内,我们写一个代码片段的时候,需要结合上下文才能看出来写得对不对,无疑增加了我们写出bug的频率
最后,楼主还有一个习惯,写把自己的思路写在函数开头的注释里。思路理清再开始编码- func lengthLongestPath(input string) int {
- paths := strings.Split(input, "\n")
- /* iterate paths, find its depth by the number ot \t
- if it's a dir, push of depth[i], set len(dirname) to dep[i]
- if it's a file(contains dot), caculate the absolute path len, update the max len
- */
- maxLen := 0
- dep := make(map[int]int, 0)
- max := func(x, y int) int {
- if x > y {
- return x
- }
- return y
- }
- isFile := func(s string) bool {
- return
- }
- depth := func(s string) (int, string) {
- d := 0
- for strings.HasPrefix(s, "\t") {
- d++
- s = strings.TrimPrefix(s, "\t")
- }
- return d, s
- }
- pathLen := func(path string) int {
- d, name := depth(path)
- pLen := len(name)
- for i := 0; i < d; i++ {
- pLen += dep[i] + 1
- }
- return pLen
- }
- for _, path := range paths {
- if isFile(path) {
- maxLen = max(maxLen, pathLen(path))
- } else {
- d, dirname := depth(path)
- dep[d] = len(dirname)
- }
- }
- return maxLen
- }
复制代码 |