为什么面试的大公司都注重代码规范?

为什么大公司都注重代码规范, 今天就跟大家唠唠代码规范的好处和重要性。

有助于逐层深入的阅读代码。

你有没有想过,究竟是什么驱使你打开那些源代码去阅读的呢?或者说你在什么情况下会打开一段源代码阅读呢?

  • 第一,你可能想了解一段代码的逻辑,比如,你在调用别人的代码时,感觉输出结果怪怪的,想进去一探究竟。

  • 第二,你可能想要学习一下大神写的代码的的核心点。

  • 第三,你运行这段代码时遇到了Bug,你要进去找到并修改它。或者想更改一下这段代码的某个地方。

可以看出,我们在阅读源代码的目的,都不是要把全部的代码阅读一遍,而是快速的找到我们需要的那个点,或者找出一条脉络。

如果说“代码是给人看的,顺便给机器运行以下”,那么写代码的人要怎样写,才能让阅读的人最快的找到自己需要的关键点呢?在查找算法中,最慢的就是,顺序查找,最快的是构建查找树进行查找。

如果有一个函数1000行,寻找某一行逻辑代码,平均需要500次,看的人头晕眼花。

如果他把函数切分成10个短函数,每个函数100行,找到一行代码平均需要5+50=55次。

如果他把每个短函数再分割成10个小函数,每个函数10行,查找平均需要 5+5+5=15次。

对于一个要查找500次才能找到的代码,大部分人直接就放弃了,不看了。你这代码不待见我。

但是对于一个平均看15次就能找到的代码,我们嗖嗖嗖就找到了。

这就是代码规范里最重要的一条: 不允许写长函数

而且把一千行的代码分割成10个函数写,我们只要看看这10个函数的名字,就能清晰的知道这段长代码的逻辑。一眼就把住了脉络。

当然这还需要我们的函数起得名字要能够说明这个代码时作什么的。很多人喜欢随便起个短小的名字然后写上注释,但是调用的时候大多数是不会看注释的,《代码整洁之道》中介绍说,最好的函数名,就是把你写的注释简化一下。比如

// sort the list and return the biggest one
int s(List arr){...}

阅读代码或者调用时,看到一个s函数,估计你和我一样会懵。

改成:

int sortAndGetBiggestElement(List arr){...}

这样就清晰明了了,这个函数名,在哪里调用都显得清晰明了。

这就是代码规范里最重要的第二条: 变量名函数名要能够表达变量和函数的作用

能够加快练习出代码逻辑的肌肉记忆

作为码农的你,应该对快速排序不陌生吧。让你在没准备的情况下手撕一段快排,应该有点难度吧。

为啥呢,因为首先快速排序这个名字就得让我们想好一阵子,起得名字不具有解释性,别的排序法不快吗,还不如叫,左右分开再分治。

那Ok, 让你只看一遍快排的代码,看你能不能完全记得住。

    public void fastSort(int[] arr){
        int l=0,r=arr.length-1;
        partition(arr,l,r);
    }
    void partition(int[] arr,int l,int r ){
        if(l>=r) return;
        int start=l,end=r;
        int flag=arr[l];
        int seat=l;
        l++;

        while (true){
            while (l<=r && arr[r]>flag) r--;
            if(l>r) break;
            arr[seat] = arr[r];
            seat = r;
            r--;

            while (l<=r && arr[l]<=flag)l++;
            if(l>r) break;
            arr[seat] = arr[l];
            seat = l;
            l++;
        }
        arr[seat]=flag;

        partition(arr,start,seat-1);
        partition(arr,seat+1,end);
    }

这段代码中递归调用Partition 函数 ,先把[l,r]之间的元素,以第一个元素为标杆,分为两段,左边比标杆小,右边比标杆大,分完了以后再分别排序左右两段数据。

看一遍很难记住,主要原因是我的代码写的有问题,问题主要包括:

  • 函数太长了
  • 逻辑不清晰,变量名字看不懂是什么含义。

重构一下看看:

虽然重构了以后,代码主要逻辑在partition, 就四句话,先判断退出条件,然后分割成两段splitTwoPart,在依次递归调用左右两段。

这样我们就能快速记住,快速排序法的核心就是三句话,先分成两段,再递归分左一段和右一段

    public void fastSort(int[] arr){
        if(arr==null) return;
        partition(arr,0,arr.length-1);
    }
    void partition(int[] arr,int start,int end ){
        if(start>=end) return;
        int splitPoint= splitTwoPart(arr,start,end);
        partition(arr,start,splitPoint-1);
        partition(arr,splitPoint+1,end);
    }
    private int splitTwoPart(int[] arr, int left, int right) {
        if(left>=right) return left;
        int start=left,end=right;
        int flag=arr[left];
        int seat=left;
        left++;

        while (true){
            while (left<=right && arr[right]>flag) right--;
            if(left>right) break;
            arr[seat] = arr[right];
            seat = right;
            right--;

            while (left<=right && arr[left]<=flag)left++;
            if(left>right) break;
            arr[seat] = arr[left];
            seat = left;
            left++;
        }
        arr[seat]=flag;
        return seat;
    }

当然这里呢,我们对分割成两段还是不太直观的认识,把splitTwoPart继续分割,在切分成两段的函数中,首先把所有参数放在了一个参数类中,然后循环内部做两件事,先从右向左找比标杆大的数。再从左向右找比标杆小的数。最后把标杆放在空位上。

    private int splitTwoPart(int[] arr, int left, int right) {
        IndexParam param=new IndexParam(left+1,right,left,arr[left]);
        while (true){
            if(!findBigOneFromRight(arr,param)) break;
            if(!findSmallOneFromLeft(arr,param))break;
        }
        arr[param.seat]=param.flag;
        return param.seat;
    }

    private boolean findSmallOneFromLeft(int[] arr, IndexParam p) {
        while (p.left<=p.right && arr[p.left]<=p.flag) p.left++;
        if(p.left>p.right) return false;
        arr[p.seat] = arr[p.left];
        p.seat = p.left;
        p.left++;
        return true;
    }

    private boolean findBigOneFromRight(int[] arr, IndexParam p) {
        while (p.left<=p.right && arr[p.right]>p.flag) p.right--;
        if(p.left>p.right) return false;
        arr[p.seat] = arr[p.right];
        p.seat = p.right;
        p.right--;
        return true;
    }
    class IndexParam {
        public int left;
        public int right;
        public int seat;
        public int flag;

        public IndexParam(int left, int right, int seat, int flag) {
            this.left = left;
            this.right = right;
            this.seat = seat;
            this.flag = flag;
        }
    }

如果所有的算法都能把主干部分提炼出来,然我们一眼看穿,然后根据我们的记忆漏洞做针对性的补充,岂不美哉。

按照规范设计的代码能够减少思维阅读的负担。

你看看以下几行代码,你估计以下他们可能是起什么作用的

int a=set(12);
c C;
fs(ar);

首先,第一行set(12)应该是为什么设置值,但是返回的a是什么鬼呢? 看到这个,谁都得停下来挠挠头。

第二行c C;是写反了吗,还是乱码了。看到这个是不是会停下来卡一下。

第三行,‘fs’是什么函数,看不懂,还得找到这个函数里面读读代码,或者注释。

这就是不规范的代码给我们的阅读带来的负担,就是要多花几秒钟才能理解,这几秒很可能就是你的忍耐力极线了。

第一行应该是设置某个变量后得到一个什么值,比如得到最小值。那就直接写成

int smallest=setAndGetSmall(12);

第二行,类要大写变量小写

class C{}
C c;

岂不是更符合正常人思维,还有类名字要把类的作用表达出来。

第三行,本来是快速排序函数,不用做简写,直接写成fastSort(arr);

可见,规范是最符合大多数人思维习惯的编程格式,所以,还是按套路出牌吧,不然你的下家头都要秃光了。

降低团队合作过程中的阻力,

你最喜欢看到谁的代码呢?

当然是自己的代码,“常用的变量名、格式、工程结构”都是按你的习惯写的,肯定比较容易接受。

那怎么才能让你乐意去阅读别人的代码呢,可以让所有的程序员都按照你的“常用的变量名、格式、工程结构”得方式写代码是不是就不错呢?

这个当然不太容易实现,因为你的编程格式和习惯很多地方都不科学,也不合理。别人不愿意接受。

那还有一种方法,如果所有人都按照某一套编程规范写代码,你的规范风格和别人的规范风格都一样。这样你阅读别人的代码和阅读自己的代码就感觉一模一样了。

在团队合作中,自己的代码经常被队友吐槽,自己也常常吐槽队友的代码,那就让大家使用同一种代码规范写代码吧。做个和谐的码农小组。

大脑的习惯按套路出牌

我们的大脑就喜欢规规矩矩,符合常理的东西,符合规范的代码就像骑自行车,手把脚蹬,腰身保持平衡,都是我们的肌肉记忆。我们基本上就不用去思考,但是不符合规范的代码就像,突然让骑自行车的你,去学驾照,你恨不得把所有的注意力都用上,却还是筋疲力尽,难以控制,因为这不符合你的规范。

当然了,这个比喻不然恰当,学开车更像是新接触代码规范的你,虽然开始比较吃力,但是,等过几年,你的车龄足够了,就像路上所有的老司机,聊着天听着歌,还刷着微信(强烈不建议),依然游刃有余。符合规范的东西,我们的大脑会走捷径,不用过多思考,手到擒来。而不符合规范,我们就得调用全部精力才能对付。

当老司机看到刚学车的新手笨手笨脚的,不敢加速,还熄火,只想喷一句,“会不会写代码“
说了这么多代码规范的问题,那么哪里去找代码规范呢?

有两个资料比较好《阿里巴巴Java开发手册》,还有一本书《代码整洁之道》。

好代码,神清气爽,爱不释手,越写越好。

守规范,简洁直观,队友不喷,合作愉快。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值