编写超级可读代码的15个最佳实践

译自:http://net.tutsplus.com/tutorials/html-css-techniques/top-15-best-practices-for-writing-super-readable-code/

译者:蒋宇捷

       一月两次,我们重温Nettuts历史上读者最喜欢的文章。

代码可读性是一个计算机编程世界的普遍主题。它是我们作为开发者第一件学习的事情。这篇文章将阐述编写可读性代码十五个最重要的最佳实践。


1 – 注释和文档

集成开发环境IDE在过去的短短几年里走过了很长的路。它使得注释代码比以前更加有用。依照特定标准书写的注释允许IDE和其他工具通过不同的方式来使用它们。

考虑如下示例:

我在函数定义中添加的注释可以在调用它的地方看到,即便是在其他文件中。

这里是我另外一个从第三方库中调用函数的例子:

在这些特殊的例子中,使用的注释(或者文档)类型基于PHPDoc,IDE是Aptana


2 – 一致的排版

我假定你已经知道了你必须要缩进你的代码。然而,保持排版样式一致仍然是一个好主意。

这里有不止一种方式来进行代码排版。

第一种:
function foo() {
    if ($maybe) {
        do_it_now();
        again();
    } else {
        abort_mission();
    }
    finalize();
}
第二种:
function foo()
{
    if ($maybe)
    {
        do_it_now();
        again();
    }
    else
    {
        abort_mission();
    }
    finalize();
}
第三种:
function foo()
{    if ($maybe)
    {    do_it_now();
        again();
    }
    else
    {    abort_mission();
    }
    finalize();
}

我曾经使用第二种样式但是最近换为第一种。但是这仅仅只代表了一种偏爱。这里并没有每个人必须要遵守的“最好的”样式。事实上,最佳的样式,就是一致的样式。如果你是一个小组的一部分或者你在为一个项目贡献代码,你必须依照这个项目之前使用的样式。

排版的样式总不是完全和另外一个不同。有时,它们混合了多种不同的规则。例如,按照PEAR编码标准,前括弧“{”和控制结构在同一行上,但是在功能定义后放在第二行上。

PEAR样式:

function foo()
{                     // placed on the next line
    if ($maybe) {     // placed on the same line
        do_it_now();
        again();
    } else {
        abort_mission();
    }
    finalize();
}

同时注意它们使用4个空格而不是Tab来缩进。

这里有一个维基百科的文章,里面有许多不同排版样式的例子。


3 – 避免显而易见的注释

为代码添加注释是效果显著的;但是,它可能太过或者只是多余的文本。像如下例子:

// get the country code
$country_code = get_country_code($_SERVER[‘REMOTE_ADDR‘]);
// if country code is US
if ($country_code == ‘US‘) {
    // display the form input for state
    echo form_input_state();
}

如果注释内容都是显而易见的,它们并没有提高工作效率。如果你必须要注释这些代码,你可以简单的把它们合并在一行:

// display state selection for US users
$country_code = get_country_code($_SERVER[‘REMOTE_ADDR‘]);
if ($country_code == ‘US‘) {
    echo form_input_state();
}

4 – 代码分组

确定的任务多半需要多行代码。使用一些空白将这些任务的代码分隔为几段是一个好主意。

这是一个简单的示例:

// get list of forums
$forums = array();
$r = mysql_query("SELECT id, name, description FROM forums");
while ($d = mysql_fetch_assoc($r)) {
    $forums []= $d;
}
// load the templates
load_template(‘header‘);
load_template(‘forum_list‘,$forums);
load_template(‘footer‘);

在每一段之前添加注释也增强了视觉上的分隔。


5 – 命名的一致性

PHP有些时候在遵守命名一致性方面有很大问题:

  • strops()和str_split()
  • imagetypes()和image_type_to_extension()

首先,这些命名必须有单词的分界线。有两种流行的选择:

  • 骆驼命名法:除了第一个单词外,每个单词的第一个字符大写。
  • 下划线命名法: 单词间采用下划线,例如mysql_real_escape_string()。

像我之前提到的一样,采用不同的命名选择会创建和排版样式类似的情形。如果一个已有的项目遵照一个确定的习惯,你必须遵守它。同时,某些语言平台倾向于使用特定的命名规则。例如Java里,大多数代码使用骆驼命名法;在PHP里大多采用下划线命名法。

它们也可以混用。一些开发者喜欢在程序函数和类名上使用下划线命名,但是在类方法名上使用骆驼命名。

class Foo_Bar {
    public function someDummyMethod() {
    }
}
function procedural_function_name() {
}

所以,没有明显的“最好的”样式,只需要保持一致。


6 – DRY原则

DRY即不要重复你自己。也被称为DIE:重复是恶魔。

这个原则规定:

      “在一个系统里每一个知识的片段必须有一个单一、明确、权威的表现。”

大多数应用程序(或者通常的计算机)的目的是让重复的任务自动化。这个原则在所有的代码,即使Web程序中也应该保持。代码的相同片段不应该多次重复。

例如,大多数Web程序由许多页面组成。这些页面很可能包含相同的元素。页头和页脚经常符合这个条件。复制和粘贴这些页头和页尾到每一个页面中不是一个好主意。这是Jeffrey Way解释如何在CodeIgniter里创建模版的链接

$this->load->view(‘includes/header‘);
$this->load->view($main_content);
$this->load->view(‘includes/footer‘);

7 – 避免过深的嵌套

太多层的嵌套会造成代码阅读和跟踪困难。

function do_stuff() {
// ...
    if (is_writable($folder)) {
        if ($fp = fopen($file_path,‘w‘)) {
            if ($stuff = get_some_stuff()) {
                if (fwrite($fp,$stuff)) {
                    // ...
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        return false;
    }
}

为了可读性,通常需要修改代码来减少嵌套的层数。

function do_stuff() {
// ...
    if (!is_writable($folder)) {
        return false;
    }
    if (!$fp = fopen($file_path,‘w‘)) {
        return false;
    }
    if (!$stuff = get_some_stuff()) {
        return false;
    }
    if (fwrite($fp,$stuff)) {
        // ...
    } else {
        return false;
    }
}

8 – 减少行的长度

我们的眼睛对于阅读高和窄的文本列更感觉舒适。这就是为什么报纸文章看起来像如下样子的原因:

避免在一行上编写过长的代码是一个最佳实践。

// bad
$my_email->set_from(‘[email protected]‘)->add_to(‘[email protected]‘)->set_subject(‘Methods Chained‘)->set_body(‘Some long message‘)->send();
// good
$my_email
    ->set_from(‘[email protected]‘)
    ->add_to(‘[email protected]‘)
    ->set_subject(‘Methods Chained‘)
    ->set_body(‘Some long message‘)
    ->send();
// bad
$query = "SELECT id, username, first_name, last_name, status FROM users LEFT JOIN user_posts USING(users.id, user_posts.user_id) WHERE post_id = ‘123‘";
// good
$query = "SELECT id, username, first_name, last_name, status
    FROM users
    LEFT JOIN user_posts USING(users.id, user_posts.user_id)
    WHERE post_id = ‘123‘";

同时,如果任何人想要在例如Vim这样的终端窗口中阅读代码,限制每一行的长度在80个字符以内是一个好主意。


9 – 代码结构

理论上,你可以将整个应用代码写在一个文件里。但是对于阅读和维护来说是一个噩梦。

在我的第一个编程项目中,我知道创建“包含文件”的含义。但是,我并没有好好进行组织。我创建了一个“inc”文件夹,放置了两个文件:db.php、functions.php。当程序变大时,functions文件也变得越来越大并难以维护。

最好的方法之一是采用框架或者模仿它们的文件夹结构。下面是CodeIgniter的文件结构:


10 – 统一的临时变量名

通常,变量名应该是描述性的并且包含一个或者更多的单词。但是,这对临时变量来说并不是必须的。它们可以短到只有一个单独字符。

最佳实践是:对于有同样职责临时变量采用统一的命名。这里有一些我倾向于在代码里使用的例子:

// $i for loop counters
for ($i = 0; $i < 100; $i++) {
    // $j for the nested loop counters
    for ($j = 0; $j < 100; $j++) {
    }
}
// $ret for return variables
function foo() {
    $ret[‘bar‘] = get_bar();
    $ret[‘stuff‘] = get_stuff();
    return $ret;
}
// $k and $v in foreach
foreach ($some_array as $k => $v) {
}
// $q, $r and $d for mysql
$q = "SELECT * FROM table";
$r = mysql_query($q);
while ($d = mysql_fetch_assocr($r)) {
}
// $fp for file pointers
$fp = fopen(‘file.txt‘,‘w‘);


11 – SQL关键词大写

数据库交互对于大多数Web应用来说是很大一个组成部分。如果你正在编写SQL查询,尽量保持它们可读。

即使SQL关键词和函数名是大小写无关的,大写来将它们从表名和列名中区分出来是一个通用的实践。

SELECT id, username FROM user;
UPDATE user SET last_login = NOW()
WHERE id = ‘123‘
SELECT id, username FROM user u
LEFT JOIN user_address ua ON(u.id = ua.user_id)
WHERE ua.state = ‘NY‘
GROUP BY u.id
ORDER BY u.username
LIMIT 0,20


12 – 代码和数据分离

这是另外一个对于所有环境下的绝大多数编程语言都适用的原则。在Web开发中,数据通常意味着HTML输出。

当PHP许多年前第一次发布时,它最开始被看作是一个模版引擎。在巨大的HTML文件里插入一些PHP代码行是非常普通的。但是,这些年来,事情发生了改变:网站变得越来越动态化和功能化。代码已经是Web程序的一个很大的部分,将它们和HTML合并在一起并不是一个好的实践。

你可以在你的程序中应用这个原则,或者你可以使用一个第三方工具(模版引擎、框架或者CMS系统)或者依照它们的习惯。

流行的PHP框架:

流行的模版引擎:

流行的CMS系统:

  • Joomla
  • Drupal


13 – 模版内的交替格式

你可以选择不使用一个奇特的模版引擎,取而代之的是在模版文件里使用纯内联的PHP代码。这不是必须要违反“数据和代码分离“,只是内联代码是直接和输出相关的,并且可读。在这种情况下你可以考虑使用交替格式来控制结构。

这是一个示例:

<div class="user_controls">
    <?php if ($user = Current_User::user()): ?>
        Hello, <em><?php echo $user->username; ?></em> <br/>
        <?php echo anchor(‘logout‘, ‘Logout‘); ?>
    <?php else: ?>
        <?php echo anchor(‘login‘,‘Login‘); ?> |
        <?php echo anchor(‘signup‘, ‘Register‘); ?>
    <?php endif; ?>
</div>
<h1>My Message Board</h1>
<?php foreach($categories as $category): ?>
    <div class="category">
        <h2><?php echo $category->title; ?></h2>
        <?php foreach($category->Forums as $forum): ?>
            <div class="forum">
                <h3>
                    <?php echo anchor(‘forums/‘.$forum->id, $forum->title) ?>
                    (<?php echo $forum->Threads->count(); ?> threads)
                </h3>
                <div class="description">
                    <?php echo $forum->description; ?>
                </div>
            </div>
        <?php endforeach; ?>
    </div>
<?php endforeach; ?>

这让你避免了许多大括号。同时代码看起来和HTML的结构和排版相似。


14 – 面向对象 vs 面向程序

面向对象编程可以帮助你创建结构化代码。但是这不代表你完全排除程序化编程。事实上创建两者混合的风格是非常棒的。

描述数据,通常是数据库里的数据,必须使用对象。

class User {
    public $username;
    public $first_name;
    public $last_name;
    public $email;
    public function __construct() {
        // ...
    }
    public function create() {
        // ...
    }
    public function save() {
        // ...
    }
    public function delete() {
        // ...
    }
}

程序化方法常用于可以独立执行的特定任务。

function capitalize($string) {
    $ret = strtoupper($string[0]);
    $ret .= strtolower(substr($string,1));
    return $ret;
}


15 – 阅读开源代码

开源项目是许多开发者一起构建的。这些项目必须保持高度的代码可读性,以便他们可以尽可能高效的协同工作。

因此,通读这些项目的源代码来观察这些开发者是如何工作的是非常棒的方法。


16 – 代码重构

当你“重构“,你在不改变功能的情况下调整代码。你可以把它看作是“清理”,为了改进代码质量和可读性。

这并不包括bug的修复或者添加新功能。你可以重构你之前编写的代码,当它们在你头脑你还保持新鲜的时候,以便于你两个月以后有可能回顾代码时更加可读和可重用。就像那句格言所说的一样:“尽早重构,经常重构“。

时间: 2024-10-17 22:58:24

编写超级可读代码的15个最佳实践的相关文章

编写 Node.js Rest API 的 10 个最佳实践

Node.js 除了用来编写 WEB 应用之外,还可以用来编写 API 服务,我们在本文中会介绍编写 Node.js Rest API 的最佳实践,包括如何命名路由.进行认证和测试等话题,内容摘要如下: 正确使用 HTTP Method 和路由 正确的使用 HTTP 状态码 使用 HTTP Header 来发送元数据 为 REST API 挑选合适的框架 要对 API 进行黑盒测试 使用基于 JWT 的无状态的认证机制 学会使用条件请求机制 拥抱接口调用频率限制(Rate-Limiting) 编

前端代码9种标准最佳实践:CSS

前端工程师对写标准的前端代码的重视程度很高.这些最佳标准实践并不是那个权威组织发布的,而是由大量的前端工程师们在实践过程中的经验总结,目的在于提高代码的可读性,可维护性和性能.那么接着上一篇,我们再来谈谈CSS代码的一些标准实践. 1,命名 和其他语言规范一样,css的命名也讲究命名要有意义,命名要尽可能短但是要足够表达含义:命名的词用连字符连接. 不规范的命名: 1 #navigation{ 2 } 3 .demoimage{ 4 } 5 .error_status{ 6 } 规范的命名: 1

《编写可读代码的艺术》读书笔记

表面内容 1.代码的写法应当是别人理解他所需的时间最小化.一条注释可以让你更快理解代码.尽管减少代码行数是一个好目标,但是八里街代码所需的时间最小化是一个更好的目标. 2.选择专业的词,比如函数名使用getxxx(),这个get没有表达出很多信息,是从缓存中得到?从数据库中得到?或者从网络得到?如果是网络,可以用更专业的fetchxxx()或者downloadxxx() 3.tmp,retval这样泛泛的名字,可以根据情况命名,比如tmpFile,让人知道变量是一个临时的文件.(tmp这个名字只

《编写可读代码的艺术》——简单总结

上个月好像冥冥中自有安排一样,我在图书馆看到这本 <编写可读代码的艺术> ( The Art of Readable Code) 期间因为工作的原因,停停看看,这几天终于看完了,可以大概总结如下: 1. 把信息装进名字里,给变量起个好名字 2. 审美,把代码分成段落,对齐 3. 应当取个好名字,而不是用注释去粉饰它 4. 用注释记录你的思想,比如当时为什么要这样写,记录开发过程中有哪些思考 5. 将自己代码中的不足和瑕疵记录下来,方便今后别人的维护,不要顾忌别人的看法! 6. 注释应该言简意赅

《编写可读代码的艺术》---变量和可读性

对变量的草率使用,会导致程序的难以理解,原因是以下几点 变量越多,就越难以全部跟踪他们的动向 变量的作用域越大,就需要跟踪它的动向越久 变量改变的越频繁,就越难以跟踪它的当前值. 下面来讨论如何改善这些问题. 1 减少变量 仅当我们需要的时候,才使用变量,下面将列举出一些没必要存在的变量的. 1.1 没有价值的临时变量 一般有经验的程序员是不会刻意写个没有价值的临时变量.造成临时变量没有使用价值的原因,可能是多次修修改改之后遗留的结果. 来个日期赋值的例子 DateTime now = Date

编写可读代码的艺术笔记

编写可读代码的艺术 表面层次上的改进 命名.注释以及审美--可以用于代码库每一行的小提示. 简化循环和逻辑 在程序中定义循环.逻辑和变量,从而使得代码更容易理解. 重新组织你的代码 在更高层次上组织大的代码块以及在功能层次上解决问题的方法. 精选话题 把"易于理解"的思想应用于测试以及大数据结构代码的例子. 第1章:代码应当易于理解 1.代码应当易于理解. 2.代码的写法应当使别人理解它所需的时间最小化. 第一部分:表面层次的改进 第2章:把信息装到名字里 1.使用专业的单词. 2.避

第一次编写简单的中间件测试工具(2) - 读代码的方法

加入新员工训练营的有开发也有测试,大家的coding水平参差不齐. 我发现一个问题,就是当面对一个新学的语言时,我们这期训练营里除了我以外所有的测试人员甚至一些开发人员都不会读代码,不知道怎么去读,或者虽然读了,却一知半解,毫无效率. 首先分享一下我读代码的方法供从手工测试转自动化测试的同学们参考(可能各人思维模式不同,仅供参考): 我读代码时的思维方式属于一级一级严密的逻辑思维,所以一旦我的逻辑链中间断掉,我就不能理解这些代码. 一句话总结:先跑起来,再调试,理解原理,掌握细节. 第一步,看有

HDU 4930 Fighting the Landlords (超级暴力+读懂题意)

题目链接:HDU 4930 Fighting the Landlords 斗地主!!.不会玩这游戏,真是苦逼.题意其他都还好,就是要注意只要第一个回合1号玩家能压制2号玩家就算赢了(突破点). 其他就分类暴力了,思路还是比较清晰的. 注意点: 1.对方炸弹,必输 2.一回合就出完牌,必胜 AC代码: #include<stdio.h> #include<string.h> int vis1[30],vis2[30]; int find(char s) { if(s=='T') re

Effective Python之编写高质量Python代码的59个有效方法

                                                     这个周末断断续续的阅读完了<Effective Python之编写高质量Python代码的59个有效方法>,感觉还不错,具有很大的指导价值.下面将以最简单的方式记录这59条建议,并在大部分建议后面加上了说明和示例,文章篇幅大,请您提前备好瓜子和啤酒! 1. 用Pythonic方式思考 第一条:确认自己使用的Python版本 (1)有两个版本的python处于活跃状态,python2和pyt