读书心得1 如何避免脏代码

先摆结论

1.消除重复
2.起更具表达力的名字
3.为对象和方法减负,各司其职只做一件事
4.尽可能把类中的字段和方法保护好不被外界访问,来逼迫自己改进质量

我的经历和思考

    1、当一段代码在你的工程中出现了两次或者以上时,我们也许就该引起警惕了,最直接的做法就是把它抽出来写出一个方法,在以前我常常不放在心上,我认为写成方法会带来额外的开销,因为程序在调用某个方法时,需要把程序的当前状态保存起来,也就是常说的保存现场,这里主要是当前函数的局部变量值,底层是保存在寄存器内部;在保存完现场后,需要准备函数所需要的参数,并执行跳转指令,这比从上之下依次执行也费得多。当执行完毕后,程序内部取到之前指令的地址回来,并恢复现场继续后面的语句。但是随着项目的规模扩大,我发现这样的小省会带来更大的麻烦:当你和团队一起合作时,别人找不到实现这个功能所需要的方法,最后没办法,只能自己写一个,这又会带来代码的重复。更恐怖的是,如果策划修改需求了,你们写的这一段代码需要修改,那你不得不在几千行的代码里去搜索你写的重复代码并一个个修改过来。一旦你漏了一个地方忘记改过来了,可能会给你后面的工作带来几十分钟甚至几小时的Debug时间。这就是我遇到的写重复代码遇到的问题。

经验:把功能模块化,尽量不要在不同的地方写相同的功能,让方法调用统一起来,减少后续的修改代价

    2、很多书本为了排版或者是减少初学者对英文的恐惧或者是一些其它我想不到的原因,通常是随意起名字,a,b,c,d等等,当然的确他们编者可能有他们自己的思考。这种习惯我也有,我自己写代码的时候也有起名抓狂症,总是想不出什么合适的名字,然后想着,反正没人看,就无所谓了。但是在最近我整理电脑里的项目时,忽然发现以前写的代码不知道啥意思,那大概是我大二写的了,费了3分钟反复看才明白那是在干啥。写时一时爽,写后火葬场,的确就是这样的。当你在和团队合作时,这种危害也会被放大很多,就想象一下你拿到一个几千行毫无格式的代码然后被要求重构的场景吧。我在公司中其实一直有注意这一点,因为我担心后面别人来重构代码或者是阅读代码加新需求时,会一脸懵逼。

经验:尽量见量知其意,然后适当注释,减少别人和自己的阅读代价(不要以为自己几个月后就一定能看懂现在写的代码!!!

    3、相信很多学C语言学的比较深的人都会有这样的一个问题,我之前是数学专业的,然后自学了C语言,且在当时对C有较深入的认识。C的确很棒,但是C面向过程这一特性也特别容易让我们这种对计算机的其他学科不太了解的跨专业生陷入低质量代码深渊。我在很长一段时间甚至到现在,写的代码都有股浓浓的面向过程味。习惯从前往后把功能一个个加进来,很多东西习惯都写在一个类里,没有面向对象的思想。这个习惯也给我带来了很多麻烦。在我之前独游开发过程中,我把我们的那个项目大部分的功能都实现在一个类里,后来我去公司上班了,我把项目交接给我们团队另一位朋友,他阅读我的代码就非常吃力,因为虽然功能都有了,但是不太符合逻辑。一个类里,有摄像机的移动和旋转,有交互方法,有创建有保存…他完全理不清楚实现那些功能,最后我们视频一个个方法来解释,然后重构了代码。这也是目前我最惨痛的一次教训,自那以后我就提醒自己,一个类就放相关的东西,一个方法就实现一种功能。这不仅仅是一种规范,更是能让项目的逻辑更清晰,还能增强代码的复用性。

经验:一个类只做自己该做的事情,一个方法只负责单一的职能。

    4、第四个是我前不久看到的,感觉的确是有道理。我以前在开发的时候,常常会把几乎所有的方法设置为public,以便于我在其他地方去使用。这意味着:我把大部分的功能都开放出去了,别人都能轻易得从我这个类里拿到数据,来得太容易总是不会去珍惜。举个简单的例子吧,假如我们在开发一个枪战类的游戏,我们开枪打中敌人时要扣血,要是我们对个体类开放了修改血量的方法,可能我们就不假思索得写下了:

enemyHp = enemyHp - mySelf.weaponDemage;

    这样的代码好吗?学过一点点代码的可能都知道,这不是不好,而是糟透了。这是太轻松,写代码思维容易被带偏的例子。再来举个例子,还是这个枪战类游戏,我们需要判断此时周围有多少敌人并分别知道他们与自己的距离。如果我们个体可以拿到所有的个体列表,可能就会这么去写:

float minDistance = mySelf.ViewDistance;
float tempDistance = 0.0f;
Agent target = null;
List<Agent> agentList = GetAllAgent();
foreach(Agent agent in agentList)
{
    
    
	tempDistance = Vector3.Distance(transform.position,agent.transform.position);//得到自己和对方的距离
	if(tempDistance < minDistance)
	{
    
    
		minDistance = tempDistance;
		target = agent;
	}
}
if(target != null && minDistance <= mySelf.attackDistance)
{
    
    
	mySelf.Attack(target);
}

    这里看起来应该没啥大问题,咱不针对逻辑是否合理(我乱想的一个例子),看性能。假设有n个存活个体,每个个体在他的刷新周期内要遍历所有的个体去计算距离判断是否在自己视野范围内,A计算了自己和B、和C、和D的,B计算了自己和A、和C、和D的…而我们把这个拿到个体的权限对个体封闭掉,你会怎么去写呢?让我写,我应该会用一个单例管理者去做,让它去计算距离,这样在一个刷新周期内,计算距离的次数就可以降低一半了,可以看作我们只用算距离矩阵的一半即可。

经验:当然,不同的人对于这点可能有不同的看法,我是认可这段话再回过头来看来写的。而我去实践的时候也发现,的确应该把自己的内部方法封闭起来不要轻易让别人访问,把自己的数据藏起来不要轻易让别人修改,不然某天你这边的数值出问题了,你一查引用,妈咪呀,怎么有几百个引用,一个个去看或者打印、Debug找出问题吧!

如果大家感兴趣,欢迎关注我的微信公众号,我们一起探讨!

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/l1606468155/article/details/104890174