改改"坏"代码

简介: 程序猿很多时候费了九牛二虎之力使用各种黑科技实现了某个功能,终于可以交差,但整个过程就像个噩梦,一般人是不太愿意回过头去阅读自己写的代码的,交出去的代码就让它如往事般随风吧。可你不愿读自己的代码,却避免不了去读别人的代码,正如别人不愿读你的代码一样。

程序猿很多时候费了九牛二虎之力使用各种黑科技实现了某个功能,终于可以交差,但整个过程就像个噩梦,一般人是不太愿意回过头去阅读自己写的代码的,交出去的代码就让它如往事般随风吧。

可你不愿读自己的代码,却避免不了去读别人的代码,正如别人不愿读你的代码一样。因果循环,相互纠缠,出来混,迟早要还的。

下面是我从一款开源CMS系统中摘出来的代码,开源出来是很好的事情,在此仅从代码的角度来讨论一下。

<?php

function page($filename, $type = false)
{
    global $_CMS, $_GP;
    $do = '';
    if ($type == true) {
        $do = $_GP['do'] . "/";
    }
    if (SYSTEM_ACT == 'mobile') {


        $source = SYSTEM_ROOT . $_CMS['module'] . "/template/mobile/" . $do . "{$filename}.php";


        if (!is_file($source)) {
            $source = SYSTEM_ROOT . "common/template/mobile/" . $do . "{$filename}.php";
        }
    } else {

        $source = SYSTEM_ROOT . $_CMS['module'] . "/template/web/" . $do . "{$filename}.php";
        if (!is_file($source)) {
            $source = SYSTEM_ROOT . "common/template/web/" . $do . "{$filename}.php";
        }
    }
    return $source;
}

写代码我一般要求格式,这种格式也算是一种套路,按套路来反复练习可以快速积累好的经验。

套路一:三段式;

1.初始化输入;
一般占代码行数20%左右

2.逻辑处理与运算

异常逻辑处理;
一般占代码行数40%~60%左右

正常逻辑处理;
一般占代码行数 20%~40%左右

3.返回

套路二:将逻辑嵌套转换为顺序执行( Guard Clauses);

逻辑一般通过if else或者switch这样的语句来呈现,提炼逻辑时,一般是大逻辑套小逻辑、小逻辑套小小逻辑、层层嵌套进去,这在没有任何封装的环境是正常的。

而一旦我们将代码放到一个函数或方法里面,事情就开始有所不同,因为有了return:每个函数我们会定义好它的返回值类型,return 可以让程序在走到某个逻辑分支时直接终止该函数的执行并返回结果;终止执行意味着就算没有if else嵌套,return 语句之后的代码也不会再执行。

利用这样的特性,我们就可以将嵌套尽量减少,使代码最终看起来是顺序执行的。

要达到顺序执行的目的,还有个先决条件:要学会将该函数和方法的执行过程和目标用一句描述出来,可以用中文,最好先注释在函数或方法体前面,比如:根据用户请求的模块、动作构造相应的视图文件绝对路径。

套路三:将逻辑提炼成数据

示例代码中一眼望去,代码重复度最高的是拼接完整文件路径的那部分,仔细看了以后,就能发现这是一段有规律的字符串:系统所处根目录+模块目录+控制器目录+动作名+后缀名,所不同的仅仅是模块名和控制器名,那么我们转换一下目标,玩个字符串填充的游戏,利用PHP的vsprintf函数就可简单实现。

示例中还有个逻辑,模块内找不到文件就降级去通用模块里找,这可算是框架的一种特性,但在这里不是我们关注的重点,重点是定义一个中间变量,就可以重用代码。

Linus在谈Git时表示:

Git的设计其实很简单,它有一个稳定而合理的数据结构。事实上,我强烈建议围绕着数据来设计代码,而不是反其道而行之,我觉得这可能就是 Git 如此成功的原因。坏程序员总是担心他们的代码,而优秀的程序员则会担心数据结构和它们之间的关系。

还有人说过,可执行程序文件本身就是一种数据。

这里的这个例子是否与Linus的理论匹配,我不太确定,但是想表达这样的一个意思。

调整过的最终代码:

<?php
function page(string $filename, bool $type = false): string
{
    global $_CMS, $_GP;

    $app = (SYSTEM_ACT == 'mobile') ? 'mobile' : 'web';
    $do = ($type == true) ? $_GP['do'] . '/' : '';
    
    $vf = SYSTEM_ROOT . "%s/template/{$app}/{$do}{$filename}.php";
    $source = vsprintf($vf, [$_CMS['module']]);
    if (!is_file($source)) {
        $source = vsprintf($vf, ['common']);
    }
    
    return $source;
}
目录
相关文章
|
11月前
|
存储 人工智能 运维
内附源码|头部基模企业信赖之选——DMS+Lindorm智能搜索方案
本文为数据库「拥抱Data+AI」系列连载第6篇,针对企业构建智能搜索服务的痛点,介绍如何利用阿里云Data+AI解决方案构建一站式AI搜索服务,深入分析了DMS+Lindorm的智能搜索解决方案。
|
存储 弹性计算 固态存储
阿里云服务器系统盘与数据盘ESSD AutoPL、ESSD云盘、SSD云盘区别及选择参考
阿里云系统盘与数据盘如何选择?目前阿里云服务器有ESSD AutoPL、高效云盘、ESSD云盘、SSD云盘可供选择,很多新手用户并不清楚他们之间的区别,也就不知道应该如何选择,因为不同的云盘在最大IOPS、最大吞吐量等性能上是有区别的,下面我们一起来他们之间的区别,这样就有助于我们选择适合自己需求的系统盘与数据盘了。
阿里云服务器系统盘与数据盘ESSD AutoPL、ESSD云盘、SSD云盘区别及选择参考
|
9月前
|
消息中间件 对象存储
轻量消息队列(原 MNS)订阅 OSS 事件实践
使用轻量消息队列订阅OSS事件,实时处理文件变动,赢取ins风U型枕(限量500个)。访问活动页面,完成实操并上传截图即可参与领奖。活动时间:即日起至2025年2月28日16:00。奖品数量有限,先到先得,快来报名吧!
162 2
|
10月前
|
数据可视化 项目管理
项目计划与进度跟踪:甘特图的强大功能解析
甘特图是现代项目管理中不可或缺的工具,通过时间线和任务条直观展示项目进度,支持任务分解、依赖关系管理和进度跟踪。结合板栗看板,可实现任务可视化与实时协作,提升团队效率。定期更新甘特图并灵活应对变化,确保项目顺利推进。
|
安全 Ubuntu Linux
Linux系统无法启动或启动过程中卡住
【10月更文挑战第5天】
1935 3
|
网络协议
BGP路由原理详解
BGP路由原理详解
664 1
BGP路由原理详解
|
分布式计算 Java 数据处理
Apache Spark优缺点大揭秘
【10月更文挑战第12天】
475 11
|
机器学习/深度学习 自然语言处理 语音技术
FunAudioLLM与其他语音模型多维度对比简析
FunAudioLLM与其他语音模型多维度对比简析
499 13
|
传感器 监控 安全
eFuse电子保险丝,需要了解的技术干货来啦
电子保险丝(eFuse)作为热保险丝的升级版,提供更快的反应速度(微秒至纳秒级)、低电流操作、可复位功能、反向电流和过压保护等优势。它们常用于需要快速保护的场景,如热插拔、汽车应用、PLC和电池管理。eFuse可以选择锁定或自动重启模式,根据应用需求调整。虽然可以使用分立组件构建基本的eFuse,但完整的IC解决方案更紧凑、稳定且功能丰富,通常包含多种保护特性,并已通过安全认证,适用于USB终端、笔记本电脑、服务器、可穿戴设备等多种应用。
594 4
|
数据采集 Web App开发 安全
Beautiful Soup和Requests
【5月更文挑战第7天】本文介绍了使用Python中的Requests和Beautiful Soup库创建网络爬虫的方法。Requests库简化了HTTP请求,Beautiful Soup则用于解析HTML和XML文档,便于提取信息。首先,文章解释了两个库的作用和安装步骤。接着,通过实例展示了如何提取网页标题和链接,以及如何下载并保存图片。对于动态加载的内容,文章推荐使用Selenium库模拟浏览器行为。此外,还介绍了如何处理登录认证,包括安全输入密码和从外部文件读取凭据。总结来说,本文提供了Python网络爬虫的基础知识和实用技巧。