我是老温,一名热爱学习的嵌入式工程师
" A% Y1 }; z8 H' N关注我,一起变得更加优秀!写代码这件事,有经验的老司机都比较“烦恼”,直接写吧,能快速写完代码,但会有一堆bug让你加不完的班;慢慢整理业务逻辑、理清思路再写吧,老板天天催进度。。。" ]$ s+ D, D5 L& a8 p, m) c k
今天就来分享一下关于业务逻辑与代码的这些事儿。业务逻辑与代码1.代码是需求逻辑的一种展现形式( u; ?$ z" d( j" W! |. ^9 g
需求文档是业务逻辑的一种展现形式,而代码不过是业务逻辑的另一种表现形式;. u5 ]' r! s+ g$ V% {8 t6 K6 `( p
如果逻辑本身有问题,那么它的各种展示形式自然也是错的,所以写代码前应该先思考清楚业务逻辑。
' h# F! v( c# J) [2.Review代码很多时候是逻辑问题在Review代码经验中发现:混乱的代码并不仅仅是代码编写技艺问题,很多时候是因为逻辑没有梳理清楚。逻辑混乱,自然代码也混乱。梳理清楚业务逻辑,就为代码打下了良好的基础。
, L5 m4 g' a* N. s当然业务逻辑梳理清楚后,业务逻辑到代码的映射依然有可能出问题,这是编程技艺要解决的问题。
: b' F. g L3 a# M下面通过一个简单的例子来演示这个过程。
0 \2 D4 q& @* U业务需求示例% \% A. o0 r# j$ P
我们要做一件事情doSomething:5 ^/ x, h- D: o: X$ Q' k5 R q
第一步先做A,A过程要先执行a1,然后执行a2,然后执行a3这三个子过程。第二步再做B,B过程需要执行b1,然后b2这两个子过程。
/ Y: I% N2 q. _. j这个示例逻辑的图形表述如下:是一个树,包含树的根,枝干,和叶子。9 \/ V! C _3 N* b, n& M+ m; {9 s$ n
ssvzrc0su0o6401242720.jpg
! B* ~+ }, n) t2 ^: C' k' _- L
例子是有通用性的,现实世界的任何事情或业务都可以用类似的树形结构来表述。. {! y6 K y" B% ]
正确的代码实现2 |1 ~/ V0 D4 A( l% C; T9 F
1.和逻辑树映射的代码树正确的代码结构应该是和逻辑映射的,代码结构如下:
+ E5 z( ^5 P' @0 M" e
jcc2aqnrrih6401242820.jpg
6 z& j# g7 H6 u% Z* Y, l x
我们真实写代码的时候,一般并不会直接写出如上结构,而是会先写出「2.代码块+注释」的结构来。
2 H# U9 p8 k8 Q% {2 M( u- G0 J+ a2.代码块+合理注释如下代码通过代码块来映射逻辑,上面图中的子函数对应代码中的注释。void doSomething(){ //A a1逻辑伪代码.....;//a1 a2逻辑伪代码.....;//a2 a3逻辑伪代码.....;//a3+ n( a/ P4 ]$ h7 z5 P5 ?5 u! [
//B b1逻辑伪代码;//b1 b2逻辑伪代码;//b2}
* u! d$ ?8 C$ l$ |3.抽取小函数可以在上面的基础上更优秀些,对代码块进行抽取小函数,更符合业务描述(更符合业务的树形结构)void doSomething(){ doA(); doB();}. u0 Z- o* u! w# _- D( L9 |) d5 {/ T
void doA(){ a1逻辑伪代码.....; a2逻辑伪代码.....; a3逻辑伪代码.....;}$ z6 G" z: l% D; c# s
void doB(){ b1逻辑伪代码; b2逻辑伪代码;}$ |! O$ {7 b' ^
当然你也可以继续对a1,a2,a3,b1,b2等小逻辑映射为小函数,以上提到几种写法都是正确的,关于小函数是否抽取,后续单独在《代码长度与母语的关系》中讨论。下面我们来看看不正确的写法。' n1 V9 Y, s& k6 Q+ a
不正确的代码实现
4 U& t- ~1 ?9 r) x5 g当你看到下面的不正确的写法的时候,你也许会觉得不可思议,真的会写出这样的代码?
0 c5 W; A$ z. v现实是:项目中我见到很多更糟糕的代码,会把下面提到的问题,以及其他编程技艺的问题排列组合出现。
' p, d- e" V( v8 t& }第一种问题:不对等第一种常见的问题不太严重,只对部分逻辑进行了抽取,造成函数中执行不对等;比如只对b()逻辑进行了抽取,但对等的a()逻辑并未抽取;! y: S0 x: K6 u( ?( y8 A' W0 Z5 r
yqrk3jviwek6401242920.jpg
- ^$ s' l: D4 `: d$ k* }5 V* Ivoid doSomething(){ a1逻辑伪代码.....; a2逻辑伪代码.....; a3逻辑伪代码.....; doB();}
. A2 y) H* l4 ~2 R$ jvoid doB(){ b1逻辑伪代码; b2逻辑伪代码;}
7 U8 O* f$ v! B! t, X/ f( M改进办法参考上面第3部分正确的写法,至少可以在doB();之前加空行,并对a1,a2,a3加个注释,也会易读很多(当然这是一种妥协写法)。void doSomething(){ //a逻辑 a1逻辑伪代码.....; a2逻辑伪代码.....; a3逻辑伪代码.....;" D4 u Y0 B" i/ r8 o$ X& Y9 s
//b逻辑 doB();}0 T5 k+ {9 i3 o/ z! i% l8 J
void doB(){ b1逻辑伪代码; b2逻辑伪代码;}
6 M4 R9 D, ~6 F第二种问题:部分抽取- {9 y3 }; r% ?2 `
第二种是对整体的部分逻辑进行了抽取,这种方法很难命名,会给个词不达意的名字,或使用整体的名字,这个就相对严重了,已经影响到了代码阅读和理解。
7 V5 L7 e2 n- |9 S/ H7 ?; o比如电脑是一个整体,可以命名是电脑;如果只给你一部分(CPU,主板,显卡)怎么命名让人能明白?电脑部分零件?但电脑部分零件并不能让人明白,因为它不是一个逻辑主体。
& f1 T' q( l' O% [CPU是一个逻辑主体,封装了运算。如下图,只对a1,a2进行了抽取,然后名字依然称为a,看到代码会很疑惑,a3明显也属于a。% Y3 i4 m) c; n) c
sqixmh21fkv6401243020.jpg
8 s0 i* f1 r8 L3 ]. Yvoid doSomething(){ doA(); a3逻辑伪代码.....; doB();}8 _( _: z% V5 |. a5 ]2 R
void doA(){ a1逻辑伪代码.....; a2逻辑伪代码.....;}. ~; T4 r# f4 G' |; i2 x: _. @
void doB(){ b1逻辑伪代码; b2逻辑伪代码;}
4 |4 r/ e" N$ x/ v% O第三种问题:抽取错误第三种是最严重的问题,抽取错误,和逻辑不匹配。
! g9 c; G, s+ Y* G- u6 U! k* z如下:把A的部分逻辑和B的部分逻辑一起抽取。* _5 Y/ z8 [! K
如果在这个基础上再对抽取的部分起个晦涩的名字(其实这种抽取也起不到好名字),然后应用一些设计模式来把代码更分散(缺点隐藏起来),就成功的完成了只有自己可以看懂的代码(可能表面看起来还很高大上)。
' _) L$ X3 y' P2 [, l' }
afeibijpsz56401243120.jpg
# b' @ z! ]2 M1 l
由此得出结论,先别想着抽取小函数或应用设计模式。先能平铺直叙地写出符合逻辑的代码吧。: J" Z S. K; T& X' f8 q1 \) f2 D
小函数抽取和设计模式不一定能解决问题,也能隐藏问题。
9 v( Y- y$ T- i& H很多难以读懂的代码都是受《重构》和《设计模式》的包装,质量差的代码不可怕,如果再抽取和包装,可以想想是多恐怖。
$ M! _. J3 u* \) t补丁和模式思考
4 K/ Z4 r: R5 |/ Z; U4 A0 j6 s补丁代码思考,代码的腐烂
8 R; P9 T# Q- D: P+ [很多人看到这里,会觉得自己绝对不会写出这么烂的代码;确实一开始也许不会,但伴随新需求,不同人不断打补丁(为了不影响线上,老代码不让动),最后就会演进为这几个问题综合展现的代码。5 r( i# O0 a7 W: z" b( v5 k
阅读这样的代码不看到最底层代码,根本不知道代码在做什么,因为函数名已经不可信。
$ A" y* P) @$ g+ G" c `! c不要急于使用设计模式,写好基础代码写出一个好的基础代码的过程:
4 o! @* s/ y. @/ f; y6 b先梳理清楚逻辑树(树形结构,同层对等),然后做到代码符合逻辑树(代码树自然也符合树形结构,同层的函数对等)。/ i1 I6 L" S! n, t; Y G" p" l
打好基础后,可以再针对基础代码的痛点,应用复杂手段(比如设计模式)来解决,关于函数抽取和函数长度,后续单独文章讨论。
3 S2 L5 \$ D5 N6 t文章来源于网络,版权归原作者所有,如有侵权,请联系删除。
- \& G5 B% J* `4 D9 \% C
; A9 G) K: F6 e3 p$ O-END-
+ G0 L( ?# f' ^往期推荐:点击图片即可跳转阅读
0 ]6 m3 F/ Q8 q! X9 J* Q6 K
tsdxbl2mpv36401243220.jpg
8 Z* y6 N) }9 w. Y1 f% u
嵌入式软件编程,事件标志组被广泛使用!# P2 w) ^3 x3 t6 x
lv1ktykfyoo6401243320.jpg
8 P' n: J) P: Z7 H E
大模型遍地开花,分享一下我对嵌入式端侧 AI 技术的看法。& l8 y* U" ~8 F( a: p/ ~! Y' s9 K
iqqxlya2m5e6401243420.jpg
+ d" w0 G( R; A3 Z& i, b; {
我发现,嵌入式工业处理器,100%国产化已经成为趋势!
# w1 I* F# o5 E0 `我是老温,一名热爱学习的嵌入式工程师" }# q2 e4 f& X; C/ F5 H: }% H5 j
关注我,一起变得更加优秀! |