电子产业一站式赋能平台

PCB联盟网

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

嵌入式软件,如何更好地编写业务逻辑代码?

[复制链接]

561

主题

561

帖子

3987

积分

四级会员

Rank: 4

积分
3987
发表于 2025-3-5 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师* M" F6 A8 u* h/ P
关注我,一起变得更加优秀!写代码这件事,有经验的老司机都比较“烦恼”,直接写吧,能快速写完代码,但会有一堆bug让你加不完的班;慢慢整理业务逻辑、理清思路再写吧,老板天天催进度。。。
! m- Z7 Q/ D$ x; d, j今天就来分享一下关于业务逻辑与代码的这些事儿。业务逻辑与代码1.代码是需求逻辑的一种展现形式2 P2 n1 l3 U' ]' v
需求文档是业务逻辑的一种展现形式,而代码不过是业务逻辑的另一种表现形式;$ @: k( I8 b9 x! ]
如果逻辑本身有问题,那么它的各种展示形式自然也是错的,所以写代码前应该先思考清楚业务逻辑。
$ @/ ?% z0 j8 n* y) b7 y2.Review代码很多时候是逻辑问题在Review代码经验中发现:混乱的代码并不仅仅是代码编写技艺问题,很多时候是因为逻辑没有梳理清楚。逻辑混乱,自然代码也混乱。梳理清楚业务逻辑,就为代码打下了良好的基础。) v7 V& @+ X* O
当然业务逻辑梳理清楚后,业务逻辑到代码的映射依然有可能出问题,这是编程技艺要解决的问题。
  M6 \1 F3 m6 U下面通过一个简单的例子来演示这个过程。
) ]6 L; E1 u8 _; Z7 i0 @2 i: Q3 O业务需求示例/ Q6 J# H; q: x0 I" W+ V, Y' p
我们要做一件事情doSomething:
# T+ j* }$ y+ F; H第一步先做A,A过程要先执行a1,然后执行a2,然后执行a3这三个子过程。第二步再做B,B过程需要执行b1,然后b2这两个子过程。* ^8 V+ T/ f7 c+ r- B
这个示例逻辑的图形表述如下:是一个树,包含树的根,枝干,和叶子。
, B) ^5 l" Q" }' S5 e! w

ssvzrc0su0o6401242720.jpg

ssvzrc0su0o6401242720.jpg
8 U5 J2 h4 {. L& Z
例子是有通用性的,现实世界的任何事情或业务都可以用类似的树形结构来表述。. `" P& V+ T+ m+ U
正确的代码实现. P5 V$ }3 C" G) ?
1.和逻辑树映射的代码树正确的代码结构应该是和逻辑映射的,代码结构如下:
" _% J0 v1 j9 C, i: r( J

jcc2aqnrrih6401242820.jpg

jcc2aqnrrih6401242820.jpg

7 @+ v8 V; f( d1 n2 F我们真实写代码的时候,一般并不会直接写出如上结构,而是会先写出「2.代码块+注释」的结构来。1 u* R) A8 K) o; Y$ i9 p+ ?7 g! D
2.代码块+合理注释如下代码通过代码块来映射逻辑,上面图中的子函数对应代码中的注释。
  • void doSomething(){    //A    a1逻辑伪代码.....;//a1    a2逻辑伪代码.....;//a2    a3逻辑伪代码.....;//a3
    . Z5 U$ Q5 v. b1 [4 j) Z    //B    b1逻辑伪代码;//b1    b2逻辑伪代码;//b2}
    $ m0 y; s8 O# }2 T* Q/ k1 a3.抽取小函数可以在上面的基础上更优秀些,对代码块进行抽取小函数,更符合业务描述(更符合业务的树形结构)
  • void doSomething(){    doA();    doB();}+ J; a% q( w9 Z/ Z4 K. P7 i
    void doA(){    a1逻辑伪代码.....;    a2逻辑伪代码.....;    a3逻辑伪代码.....;}
    % z, t  d* h& y. c( |1 Rvoid doB(){    b1逻辑伪代码;    b2逻辑伪代码;}
    1 x1 f0 p* Z" t! s' I, [. H当然你也可以继续对a1,a2,a3,b1,b2等小逻辑映射为小函数,以上提到几种写法都是正确的,关于小函数是否抽取,后续单独在《代码长度与母语的关系》中讨论。下面我们来看看不正确的写法。
    1 c) f7 A" b! [2 X" f% X8 \: \, S* A不正确的代码实现
    ) ~1 A* W  `. i+ H8 W+ d当你看到下面的不正确的写法的时候,你也许会觉得不可思议,真的会写出这样的代码?
    * Y. M. P! }" ^! P2 \# L现实是:项目中我见到很多更糟糕的代码,会把下面提到的问题,以及其他编程技艺的问题排列组合出现。) Y, H; t4 \" M$ W; ?( l
    第一种问题:不对等第一种常见的问题不太严重,只对部分逻辑进行了抽取,造成函数中执行不对等;比如只对b()逻辑进行了抽取,但对等的a()逻辑并未抽取;- @2 Y' x. S6 K! {

    yqrk3jviwek6401242920.jpg

    yqrk3jviwek6401242920.jpg

    8 G* P, J* W- Y$ R
  • void doSomething(){    a1逻辑伪代码.....;    a2逻辑伪代码.....;    a3逻辑伪代码.....;    doB();}. i# U; k6 b3 S: W
    void doB(){    b1逻辑伪代码;    b2逻辑伪代码;}' ^, C/ m5 p2 b& n6 \" y
    改进办法参考上面第3部分正确的写法,至少可以在doB();之前加空行,并对a1,a2,a3加个注释,也会易读很多(当然这是一种妥协写法)。
  • void doSomething(){        //a逻辑    a1逻辑伪代码.....;    a2逻辑伪代码.....;    a3逻辑伪代码.....;6 |" F: ?9 \! q9 e( V
        //b逻辑    doB();}
    0 P# N& H* b0 ?0 n& K# H7 T1 Kvoid doB(){    b1逻辑伪代码;    b2逻辑伪代码;}
      K; }* s. i3 d: b4 V
    第二种问题:部分抽取
    9 T* R( D9 Q$ u5 c, Q8 ~$ N" A2 o第二种是对整体的部分逻辑进行了抽取,这种方法很难命名,会给个词不达意的名字,或使用整体的名字,这个就相对严重了,已经影响到了代码阅读和理解。( S2 L5 c) J' a$ q5 N" Y( B
    比如电脑是一个整体,可以命名是电脑;如果只给你一部分(CPU,主板,显卡)怎么命名让人能明白?电脑部分零件?但电脑部分零件并不能让人明白,因为它不是一个逻辑主体。: \# c; S/ g& t
    CPU是一个逻辑主体,封装了运算。如下图,只对a1,a2进行了抽取,然后名字依然称为a,看到代码会很疑惑,a3明显也属于a。; L9 S# b& ^; ~- O5 h2 y

    sqixmh21fkv6401243020.jpg

    sqixmh21fkv6401243020.jpg

    7 n3 s# v$ W1 p! C2 u
  • void doSomething(){    doA();    a3逻辑伪代码.....;    doB();}& M. q$ X* z5 q% v$ J9 d1 ~
    void doA(){    a1逻辑伪代码.....;    a2逻辑伪代码.....;}
    4 V' ^. v0 N9 L: b0 x* @void doB(){    b1逻辑伪代码;    b2逻辑伪代码;}& j6 Y, E2 {4 K' g. J2 T5 W
    第三种问题:抽取错误第三种是最严重的问题,抽取错误,和逻辑不匹配。5 l# q9 K; U1 k$ n: B. E
    如下:把A的部分逻辑和B的部分逻辑一起抽取。9 |! `+ n- K2 r, q- G  Q
    如果在这个基础上再对抽取的部分起个晦涩的名字(其实这种抽取也起不到好名字),然后应用一些设计模式来把代码更分散(缺点隐藏起来),就成功的完成了只有自己可以看懂的代码(可能表面看起来还很高大上)。: U, r. n  H5 X& T+ \  y

    afeibijpsz56401243120.jpg

    afeibijpsz56401243120.jpg
      n5 X$ n/ f5 G, L3 j
    由此得出结论,先别想着抽取小函数或应用设计模式。先能平铺直叙地写出符合逻辑的代码吧。
    ) s1 a2 D) N- m0 ]. ~6 p小函数抽取和设计模式不一定能解决问题,也能隐藏问题。2 m1 n* Q" ^0 N5 O0 o
    很多难以读懂的代码都是受《重构》和《设计模式》的包装,质量差的代码不可怕,如果再抽取和包装,可以想想是多恐怖。
    ) i! T' l; g7 T- e, D# Y/ u; Z补丁和模式思考7 w% r5 {5 j% o/ z- @& Y- v
    补丁代码思考,代码的腐烂
    ' d7 `; {/ o2 n# m+ u很多人看到这里,会觉得自己绝对不会写出这么烂的代码;确实一开始也许不会,但伴随新需求,不同人不断打补丁(为了不影响线上,老代码不让动),最后就会演进为这几个问题综合展现的代码。
    ) Q  b8 c# u; |$ |' ~  E& j阅读这样的代码不看到最底层代码,根本不知道代码在做什么,因为函数名已经不可信。
    8 i8 y% m$ X6 F) ?' P不要急于使用设计模式,写好基础代码写出一个好的基础代码的过程:
    - I9 J6 q2 l2 f9 x; B$ v3 x先梳理清楚逻辑树(树形结构,同层对等),然后做到代码符合逻辑树(代码树自然也符合树形结构,同层的函数对等)。
    3 p* W% X' t  G打好基础后,可以再针对基础代码的痛点,应用复杂手段(比如设计模式)来解决,关于函数抽取和函数长度,后续单独文章讨论。7 G2 F' ~4 G5 |7 g  _
    文章来源于网络,版权归原作者所有,如有侵权,请联系删除。3 c* E1 J- @* t" n# ^, n% `9 Q

    " r0 C1 h4 [* u% i$ A, v: G-END-3 `" K; R% R2 _1 _3 f7 O$ w
    往期推荐:点击图片即可跳转阅读5 u& z$ M3 S. H. p' {5 N, l+ I( Q

    tsdxbl2mpv36401243220.jpg

    tsdxbl2mpv36401243220.jpg
      Z; t* E# d1 U( ]; w
    嵌入式软件编程,事件标志组被广泛使用!; R: f! p; H* @, G+ O

    lv1ktykfyoo6401243320.jpg

    lv1ktykfyoo6401243320.jpg
    ; j, e% \# k6 K% ^4 M/ j3 k; O
    大模型遍地开花,分享一下我对嵌入式端侧 AI 技术的看法。8 G; S/ ?) |" d0 T. j

    iqqxlya2m5e6401243420.jpg

    iqqxlya2m5e6401243420.jpg

    7 ]* R& t8 r. k. r9 M) V2 q我发现,嵌入式工业处理器,100%国产化已经成为趋势!
    & \6 ~( A) [% }$ ~6 M我是老温,一名热爱学习的嵌入式工程师
    * F1 j- D% |/ S4 Y  H$ r" Q关注我,一起变得更加优秀!
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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