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

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

下面是我从一款开源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;
}

改改"坏"代码的更多相关文章

  1. OO之美4(好代码与坏代码)

    前言:写代码不仅仅要做到能与机器交流,更要做到能和人交流 编码规范:编码规范就是最佳实践,是前辈在编码这件事上的积累和总结,是智慧的延续和工业的实践,如下: ⑴命名规范 ⑵避免行数过多的方法 ⑶代码缩 ...

  2. 改改Python代码,运行速度还能提升6万倍

    这份最新研究指出,在后摩尔定律时代,人类所获得的的算力提升将更大程度上来源于计算堆栈的「顶层」,即软件.算法和硬件架构,这将成为一个新的历史趋势. 很多人学习python,不知道从何学起.很多人学习p ...

  3. eslint prettier editrorconfig - 写出干净的前端代码

    FConfidence 关注 2018.12.30 02:38* 字数 2912 阅读 195评论 0喜欢 0 VSCode 插件安装 Prettier - Code Formatter ESLint ...

  4. Go代码重构:23倍的性能爆增

    几周前,我读了一篇名为“ Good Code vs Go Code中的错误代码 ”的文章,作者指导我们逐步完成实际业务用例的重构. 本文的重点是将“坏代码”转变为“良好代码”:更具惯用性,更易读,利用 ...

  5. 代码整洁之道Clean Code 读后感After Reading

    1.有意义的命名 名副其实,避免误导 做有意义的区分,简单明了2.函数 短小,职责单一 别重复自己3.注释 用代码来阐述 可怕的废话4.格式 垂直格式,垂直距离,空范围 横向格式,水平对齐,缩进5.错 ...

  6. CODING 代码多仓库实践

    关于代码的管理问题已经讨论多年,随着企业业务的复杂度提高.软件行业技术栈的选择度变宽泛,现代软件的代码仓库也变得越来越庞大和复杂.一个中型项目,将测试代码.核心业务代码.编译构建.部署打包等基础设施的 ...

  7. Laravel 代码开发最佳实践

    我们这里要讨论的并不是 Laravel 版的 SOLID 原则(想要了解更多 SOLID 原则细节查看这篇文章)亦或是设计模式,而是 Laravel 实际开发中容易被忽略的最佳实践. 内容概览 单一职 ...

  8. Python3 与 C# 扩展之~模块专栏

      代码裤子:https://github.com/lotapp/BaseCode/tree/maste 在线编程:https://mybinder.org/v2/gh/lotapp/BaseCode ...

  9. 安装seafile记录文档

    安装yum-cron.iptables .关闭selinux yum -y install cronie yum -y install yum-cron systemctl start yu,-cro ...

随机推荐

  1. explicit_defaults_for_timestamp参数

    Introduced 5.6.6 Deprecated 5.6.6 Command-Line Format --explicit_defaults_for_timestamp=# System Var ...

  2. 公网用户接入NAT后面的freeswitch配置

    大致网络示意和终端号码: 客户端侧: 终端号码(1019)终端IP(192.168.1.15)+ 网关(192.168.1.1) + 路由器公网IP(动态地址) 服务器侧: 防火墙(181.92.2. ...

  3. [转]OkHttp3 最有营养的初级教程

    一.前言 自从Android4.4开始,google已经开始将源码中的HttpURLConnection替换为OkHttp,而在Android6.0之后的SDK中google更是移除了对于HttpCl ...

  4. C#基础第八天-作业-设计类-面向对象方式实现两个帐户之间转账

    要求1:完成以下两种账户类型的编码.银行的客户分为两大类:储蓄账户(SavingAccount)和信用账户(CreditAccount),两种的账户类型的区别在于:储蓄账户不允许透支,而信用账户可以透 ...

  5. PHP规范PSR0和PSR4的理解

    一.PSR0简介 下文描述了若要使用一个通用的自动加载器(autoloader),你所需要遵守的规范: 一个完全标准的命名空间(namespace)和类(class)的结构是这样的:\<Vend ...

  6. Datagrid分页、排序、删除代码

    <%@ Page language="c#" Codebehind="default.aspx.cs" AutoEventWireup="fal ...

  7. The superclass "javax.servlet.http.HttpServlet" was not found 问题解决

    项目中报" The superclass "javax.servlet.http.HttpServlet" was not found "这个错误,是因为缺少t ...

  8. 菜鸟调错(六)——Hibernate 4.3.x 注解常见错误及解决方案

    编程的过程免不了遇到各种错误,各种问题,而遇到问题,解决问题的这个过程我认为是最让人兴奋的事情.越棘手的问题,解决以后带来的快感也越大.当一个问题你搞了一下午或者一天,甚至几天,当你解决的那一刻你会觉 ...

  9. linux命令(45):去掉 所有文件中的空行

    方法一:利用grep grep -v '^\s*$' test.txt 注:-v表示将匹配的结果进行反转,正则表达式匹配空行.(空行可包括空格符制表符等空白字符) 方法二:利用sed sed '/^\ ...

  10. lua的模块加载require

    加载指定的模块.首先函数会在 package.loaded 这个表中查看是否已经加载 了 modname 这个模块.如果是,那么 require 会返回保存在 package.loaded[modna ...