电子产业一站式赋能平台

PCB联盟网

搜索
查看: 13|回复: 0
收起左侧

业务逻辑代码怎样写才规范

[复制链接]

280

主题

280

帖子

1849

积分

三级会员

Rank: 3Rank: 3

积分
1849
发表于 昨天 12:06 | 显示全部楼层 |阅读模式
关注+星标公众,不错过精彩内容来源 | qryc
写代码这件事,有经验的老司机都比较“烦恼”,直接写吧,能快速写完代码,但会有一堆bug让你加不完的班;慢慢整理业务逻辑、理清思路再写吧,老板天天催进度。。。
今天就来分享一下关于业务逻辑与代码的这些事儿。业务逻辑与代码
1.代码是需求逻辑的一种展现形式需求文档是业务逻辑的一种展现形式,而代码不过是业务逻辑的另一种表现形式;
如果逻辑本身有问题,那么它的各种展示形式自然也是错的,所以写代码前应该先思考清楚业务逻辑。
2.Review代码很多时候是逻辑问题在Review代码经验中发现:混乱的代码并不仅仅是代码编写技艺问题,很多时候是因为逻辑没有梳理清楚。逻辑混乱,自然代码也混乱。梳理清楚业务逻辑,就为代码打下了良好的基础。
当然业务逻辑梳理清楚后,业务逻辑到代码的映射依然有可能出问题,这是编程技艺要解决的问题。
下面通过一个简单的例子来演示这个过程。
业务需求示例
我们要做一件事情doSomething:第一步先做A,A过程要先执行a1,然后执行a2,然后执行a3这三个子过程。第二步再做B,B过程需要执行b1,然后b2这两个子过程。
这个示例逻辑的图形表述如下:是一个树,包含树的根,枝干,和叶子。

5iobmbknyg164079703719.jpg

5iobmbknyg164079703719.jpg

例子是有通用性的,现实世界的任何事情或业务都可以用类似的树形结构来表述。

正确的代码实现
1.和逻辑树映射的代码树正确的代码结构应该是和逻辑映射的,代码结构如下:

540oiulbcc264079703819.jpg

540oiulbcc264079703819.jpg

我们真实写代码的时候,一般并不会直接写出如上结构,而是会先写出「2.代码块+注释」的结构来。
2.代码块+合理注释如下代码通过代码块来映射逻辑,上面图中的子函数对应代码中的注释。
  • void doSomething(){    //A    a1逻辑伪代码.....;//a1    a2逻辑伪代码.....;//a2    a3逻辑伪代码.....;//a3
        //B    b1逻辑伪代码;//b1    b2逻辑伪代码;//b2}
    3.抽取小函数可以再上面的基础上更优秀些,对代码块进行抽取小函数,更符合业务描述(更符合业务的树形结构)
  • void doSomething(){    doA();    doB();}
    void doA(){    a1逻辑伪代码.....;    a2逻辑伪代码.....;    a3逻辑伪代码.....;}
    void doB(){    b1逻辑伪代码;    b2逻辑伪代码;}
    当然你也可以继续对a1,a2,a3,b1,b2等小逻辑映射为小函数,以上提到几种写法都是正确的,关于小函数是否抽取,后续单独在《代码长度与母语的关系》中讨论。下面我们来看看不正确的写法。
    不正确的代码实现
    当你看到下面的不正确的写法的时候,你也许会觉得不可思议,真的会写出这样的代码?
    现实是:项目中我见到很多更糟糕的代码,会把下面提到的问题,以及其他编程技艺的问题排列组合出现。
    第一种问题:不对等第一种常见的问题不太严重,只对部分逻辑进行了抽取,造成函数中执行不对等;比如只对b()逻辑进行了抽取,但对等的a()逻辑并未抽取;

    rmzrv0npwlh64079703919.jpg

    rmzrv0npwlh64079703919.jpg


  • void doSomething(){    a1逻辑伪代码.....;    a2逻辑伪代码.....;    a3逻辑伪代码.....;    doB();}
    void doB(){    b1逻辑伪代码;    b2逻辑伪代码;}
    改进办法参考上面第3部分正确的写法,至少可以在doB();之前加空行,并对a1,a2,a3加个注释,也会易读很多(当然这是一种妥协写法)。
  • void doSomething(){        //a逻辑    a1逻辑伪代码.....;    a2逻辑伪代码.....;    a3逻辑伪代码.....;
        //b逻辑    doB();}
    void doB(){    b1逻辑伪代码;    b2逻辑伪代码;}
    第二种问题:部分抽取第二种是对整体的部分逻辑进行了抽取,这种方法很难命名,会给个词不达意的名字,或使用整体的名字,这个就相对严重了,已经影响到了代码阅读和理解。
    比如电脑是一个整体,可以命名是电脑;如果只给你一部分(CPU,主板,显卡)怎么命名让人能明白?电脑部分零件?但电脑部分零件并不能让人明白,因为它不是一个逻辑主体。CPU是一个逻辑主体,封装了运算。
    如下图,只对a1,a2进行了抽取,然后名字依然称为a,看到代码会很疑惑,a3明显也属于a。

    oidvge5pxgj64079704019.jpg

    oidvge5pxgj64079704019.jpg

  • void doSomething(){    doA();    a3逻辑伪代码.....;    doB();}
    void doA(){    a1逻辑伪代码.....;    a2逻辑伪代码.....;}
    void doB(){    b1逻辑伪代码;    b2逻辑伪代码;}
    第三种问题:抽取错误第三种是最严重的问题,抽取错误,和逻辑不匹配。
    如下:把A的部分逻辑和B的部分逻辑一起抽取。
    如果在这个基础上再对抽取的部分起个晦涩的名字(其实这种抽取也起不到好名字),然后应用一些设计模式来把代码更分散(缺点隐藏起来),就成功的完成了只有自己可以看懂的代码(可能表面看起来还很高大上)。

    xxwnt3s0aai64079704120.jpg

    xxwnt3s0aai64079704120.jpg

    由此得出结论,先别想着抽取小函数或应用设计模式。先能平铺直叙的写出符合逻辑的代码吧。
    小函数抽取和设计模式不一定能解决问题,也能隐藏问题。

    很多难以读懂的代码都是受《重构》和《设计模式》的包装,质量差的代码不可怕,如果再抽取和包装,可以想想是多恐怖。
    补丁和模式思考
    补丁代码思考,代码的腐烂很多人看到这里,会觉得自己绝对不会写出这么烂的代码;确实一开始也许不会,但伴随新需求,不同人不断打补丁(为了不影响线上,老代码不让动),最后就会演进未这几个问题综合展现的代码。阅读这样的代码不看到最底层代码,根本不知道代码在做什么,因为函数名已经不可信。
    不要急于使用设计模式,写好基础代码写出一个好的基础代码的过程:先梳理清楚逻辑树(树形结构,同层对等),然后做到代码符合逻辑树(代码树自然也符合树形结构,同层的函数对等)。
    打好基础后,可以再针对基础代码的痛点,应用复杂手段(比如设计模式)来解决,关于函数抽取和函数长度,后续单独文章讨论。参考来源:https://zhuanlan.zhihu.com/p/435871448声明:本文素材来源网络,版权归原作者所有。如涉及作品版权问题,请与我联系删除。
    ------------ END ------------

    kgqwnw4rfrs64079704220.gif

    kgqwnw4rfrs64079704220.gif


    ●专栏《嵌入式工具
    ●专栏《嵌入式开发》
    ●专栏《Keil教程》
    ●嵌入式专栏精选教程

    关注公众号回复“加群”按规则加入技术交流群,回复“1024”查看更多内容。
    点击“阅读原文”查看更多分享。
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表