`

如何提高代码质量一 可读性

    博客分类:
  • Java
阅读更多

高质量代码的三要素
  我们评价高质量代码有三要素:可读性、可维护性、可变更性。我们的代码要一个都不能少地达到了这三要素的要求才能算高质量的代码。
  1. 可读性强
  一提到可读性似乎有一些老生常谈的味道,但令人沮丧的是,虽然大家一而再,再而三地强调可读性,但我们的代码在可读性方面依然做得非常糟糕。由于工作的需要,我常常需要去阅读他人的代码,维护他人设计的模块。每当我看到大段大段、密密麻麻的代码,而且还没有任何的注释时常常感慨不已,深深体会到了这项工作的重要。由于分工的需要,我们写的代码难免需要别人去阅读和维护的。而对于许多程序员来说,他们很少去阅读和维护别人的代码。正因为如此,他们很少关注代码的可读性,也对如何提高代码的可读性缺乏切身体会。有时即使为代码编写了注释,也常常是注释语言晦涩难懂形同天书,令阅读者反复斟酌依然不明其意。针对以上问题,我给大家以下建议:一堂如何提高代码质量的培训课

1)不要编写大段的代码
  如果你有阅读他人代码的经验,当你看到别人写的大段大段的代码,而且还不怎么带注释,你是怎样的感觉,是不是“嗡”地一声头大。各种各样的功能纠缠在一个方法中,各种变量来回调用,相信任何人多不会认为它是高质量的代码,但却频繁地出现在我们编写的程序了。如果现在你再回顾自己写过的代码,你会发现,稍微编写一个复杂的功能,几百行的代码就出去了。一些比较好的办法就是分段。将大段的代码经过整理,分为功能相对独立的一段又一段,并且在每段的前端编写一段注释。这样的编写,比前面那些杂乱无章的大段代码确实进步了不少,但它们在功能独立性、可复用性、可维护性方面依然不尽人意。从另一个比较专业的评价标准来说,它没有实现低耦合、高内聚。我给大家的建议是,将这些相对独立的段落另外封装成一个又一个的函数。
  许多大师在自己的经典书籍中,都鼓励我们在编写代码的过程中应当养成不断重构的习惯。我们在编写代码的过程中常常要编写一些复杂的功能,起初是写在一个类的一个函数中。随着功能的逐渐展开,我们开始对复杂功能进行归纳整理,整理出了一个又一个的独立功能。这些独立功能有它与其它功能相互交流的输入输出数据。当我们分析到此处时,我们会非常自然地要将这些功能从原函数中分离出来,形成一个又一个独立的函数,供原函数调用。在编写这些函数时,我们应当仔细思考一下,为它们取一个释义名称,并为它们编写注释(后面还将详细讨论这个问题)。另一个需要思考的问题是,这些函数应当放到什么地方。这些函数可能放在原类中,也可能放到其它相应职责的类中,其遵循的原则应当是“职责驱动设计”(后面也将详细描述)。

下面是我编写的一个从XML文件中读取数据,将其生成工厂的一个类。这个类最主要的一段程序就是初始化工厂,该功能归纳起来就是三部分功能:用各种方式尝试读取文件、以DOM的方式解析XML数据流、生成工厂。而这些功能被我归纳整理后封装在一个不同的函数中,并且为其取了释义名称和编写了注释:

/**
  * 初始化工厂。根据路径读取XML文件,将XML文件中的数据装载到工厂中
  * @param path XML的路径
  */
public void initFactory(String path){
    if(findOnlyOneFileByClassPath(path)){return;}
    if(findResourcesByUrl(path)){return;}
    if(findResourcesByFile(path)){return;}
    this.paths = new String[]{path};
}
/**
* 初始化工厂。根据路径列表依次读取XML文件,将XML文件中的数据装载到工厂中
* @param paths 路径列表
*/
public void initFactory(String[] paths){
    for(int i=0; i<paths.length; i++){
        initFactory(paths[i]);
    }
    this.paths = paths;
}
/**
* 重新初始化工厂,初始化所需的参数,为上一次初始化工厂所用的参数。
*/
public void reloadFactory(){
initFactory(this.paths);
}
/**
* 采用ClassLoader的方式试图查找一个文件,并调用<code>readXmlStream()</code>进行解析
* @param path XML文件的路径
* @return 是否成功
*/
protected boolean findOnlyOneFileByClassPath(String path){
    boolean success = false;
    try {
        Resource resource = new ClassPathResource(path, this.getClass());
        resource.setFilter(this.getFilter());
        InputStream is = resource.getInputStream();
        if(is==null){return false;}
        readXmlStream(is);
        success = true;
    } catch (SAXException e) {
        log.debug("Error when findOnlyOneFileByClassPath:"+path,e);
   } catch (IOException e) {
        log.debug("Error when findOnlyOneFileByClassPath:"+path,e);
    } catch (ParserConfigurationException e) {
        log.debug("Error when findOnlyOneFileByClassPath:"+path,e);
    }
    return success;
}
/**
* 采用URL的方式试图查找一个目录中的所有XML文件,并调用<code>readXmlStream()</code>进行解析
* @param path XML文件的路径
* @return 是否成功
*/
protected boolean findResourcesByUrl(String path){
    boolean success = false;
    try {
        ResourcePath resourcePath = new PathMatchResource(path, this.getClass());
        resourcePath.setFilter(this.getFilter());
        Resource[] loaders = resourcePath.getResources();
        for(int i=0; i<loaders.length; i++){
            InputStream is = loaders[i].getInputStream();
            if(is!=null){
                readXmlStream(is);
                success = true;
            }
        }
    } catch (SAXException e) {
        log.debug("Error when findResourcesByUrl:"+path,e);
    } catch (IOException e) {
       log.debug("Error when findResourcesByUrl:"+path,e);
    } catch (ParserConfigurationException e) {
        log.debug("Error when findResourcesByUrl:"+path,e);
    }
    return success;
}
/**
* 用File的方式试图查找文件,并调用<code>readXmlStream()</code>解析
* @param path XML文件的路径
* @return 是否成功
*/
protected boolean findResourcesByFile(String path){
    boolean success = false;
    FileResource loader = new FileResource(new File(path));
    loader.setFilter(this.getFilter());
    try {
        Resource[] loaders = loader.getResources();
        if(loaders==null){return false;}
    for(int i=0; i<loaders.length; i++){
        InputStream is = loaders[i].getInputStream();
        if(is!=null){
            readXmlStream(is);
            success = true;
        }
    }
} catch (IOException e) {
    log.debug("Error when findResourcesByFile:"+path,e);
} catch (SAXException e) {
    log.debug("Error when findResourcesByFile:"+path,e);
} catch (ParserConfigurationException e) {
    log.debug("Error when findResourcesByFile:"+path,e);
}
  return success;
}
/**
* 读取并解析一个XML的文件输入流,以Element的形式获取XML的根,
* 然后调用<code>buildFactory(Element)</code>构建工厂
* @param inputStream 文件输入流
* @throws SAXException
* @throws IOException
* @throws ParserConfigurationException
*/
protected void readXmlStream(InputStream inputStream) throws SAXException, IOException, ParserConfigurationException{
    if(inputStream==null){
        throw new ParserConfigurationException("Cann't parse source because of InputStream is null!");
    }
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(this.isValidating());
    factory.setNamespaceAware(this.isNamespaceAware());
    DocumentBuilder build = factory.newDocumentBuilder();
    Document doc = build.parse(new InputSource(inputStream));
    Element root = doc.getDocumentElement();
    buildFactory(root);
}
/**
* 用从一个XML的文件中读取的数据构建工厂
* @param root 从一个XML的文件中读取的数据的根
*/
protected abstract void buildFactory(Element root);  


在编写代码的过程中,通常有两种不同的方式。一种是从下往上编写,也就是按照顺序,每分出去一个函数,都要将这个函数编写完,才回到主程序,继续往下编写。而一些更有经验的程序员会采用另外一种从上往下的编写方式。当他们在编写程序的时候,每个被分出去的程序,可以暂时只写一个空程序而不去具体实现功能。当主程序完成以后,再一个个实现它的所有子程序。采用这样的编写方式,可以使复杂程序有更好的规划,避免只见树木不见森林的弊病。
  有多少代码就算大段代码,每个人有自己的理解。我编写代码,每当达到15~20行的时候,我就开始考虑是否需要重构代码。同理,一个类也不应当有太多的函数,当函数达到一定程度的时候就应该考虑分为多个类了;一个包也不应当有太多的类······

2)释义名称与注释
  我们在命名变量、函数、属性、类以及包的时候,应当仔细想想,使名称更加符合相应的功能。我们常常在说,设计一个系统时应当有一个或多个系统分析师对整个系统的包、类以及相关的函数和属性进行规划,但在通常的项目中这都非常难于做到。对它们的命名更多的还是程序员来完成。但是,在一个项目开始的时候,应当对项目的命名出台一个规范。譬如,在我的项目中规定,新增记录用new或add开头,更新记录用edit或mod开头,删除用del开头,查询用find或query开头。使用最乱的就是get,因此我规定,get开头的函数仅仅用于获取类属性。

注释是每个项目组都在不断强调的,可是依然有许多的代码没有任何的注释。为什么呢?因为每个项目在开发过程中往往时间都是非常紧的。在紧张的代码开发过程中,注释往往就渐渐地被忽略了。利用开发工具的代码编写模板也许可以解决这个问题。
  用我们常用的MyEclipse为例,在菜单“window>>Preferences>>Java>>Code Style>>Code Templates>>Comments”中,可以简单的修改一下。


 “Files”代表的是我们每新建一个文件(可能是类也可能是接口)时编写的注释,我通常设定为:

/*
* created on ${date}
*/  

Types”代表的是我们新建的接口或类前的注释,我通常设定为:
/**
*
* @author ${user}
*/  

第一行为一个空行,是用于你写该类的注释。如果你采用“职责驱动设计”,这里首先应当描述的是该类的职责。如果需要,你可以写该类一些重要的方法及其用法、该类的属性及其中文含义等。
  ${user}代表的是你在windows中登陆的用户名。如果这个用户名不是你的名称,你可以直接写死为你自己的名称。
  其它我通常都保持为默认值。通过以上设定,你在创建类或接口的时候,系统将自动为你编写好注释,然后你可以在这个基础上进行修改,大大提高注释编写的效率。
  同时,如果你在代码中新增了一个函数时,通过Alt+Shift+J快捷键,可以按照模板快速添加注释。
  在编写代码时如果你编写的是一个接口或抽象类,我还建议你在@author后面增加@see注释,将该接口或抽象类的所有实现类列出来,因为阅读者在阅读的时候,寻找接口或抽象类的实现类比较困难。

/**
* 抽象的单表数组查询实现类,仅用于单表查询
* @author 范钢
* @see com.htxx.support.query.DefaultArrayQuery
* @see com.htxx.support.query.DwrQuery
*/
public abstract class ArrayQuery implements ISingleQuery {
...  

  • 大小: 52.9 KB
  • 大小: 13.1 KB
分享到:
评论

相关推荐

    统一文件编码和代码风格,提高代码可读性(eclipse设置)

    本文将深入探讨如何通过Eclipse IDE来统一文件编码和代码风格,从而提高代码的可读性。 首先,我们需要理解文件编码的重要性。编码方式决定了文本文件中字符的表示方法,常见的有GBK、UTF-8等。不一致的编码可能...

    统一文件编码和代码风格,提高代码可读性

    标题“统一文件编码和代码风格,提高代码可读性”直指两个核心概念:文件编码和代码风格。这两个方面是软件开发过程中的基础要素,对团队协作和长期项目维护有着深远的影响。 **文件编码**指的是在计算机中存储和...

    一堂如何提高代码质量的培训课(2)

    这堂“如何提高代码质量的培训课(2)”旨在深入探讨如何通过有效的方法和技术来提升代码质量,从而构建更加可靠、可维护和高效的软件系统。我们将从源码管理和工具应用两个核心方面进行详细阐述。 首先,源码管理...

    如何提高c_c++代码质量

    一个良好的文件结构能够帮助开发者快速定位代码,提高代码的可读性和可维护性。包括: * 版权和版本的声明:在文件的开头声明版权和版本信息,能够帮助开发者了解代码的来源和版本信息。 * 头文件的结构:头文件是...

    提升代码质量:编写可读性强的代码的艺术

    代码的可读性是衡量代码质量的重要标准之一。可读性强的代码不仅易于理解,方便维护,还能有效减少错误和提高开发效率。本文将探讨如何编写可读性强的代码,包括代码风格、命名约定、代码结构、注释和文档等方面。 ...

    如何提高代码质量

    本文将深入探讨提高代码质量的三大要素:可读性、可维护性和可变更性。 **可读性**是代码质量的基石。代码应清晰易懂,让其他开发者能迅速理解其功能和逻辑。这包括但不限于: 1. **避免大段代码**:过长的函数或...

    提高代码可读性: 命名技术

    总之,良好的命名习惯是编写高质量代码的基础,它能够提高代码的可读性和可维护性,降低开发过程中出错和理解成本。因此,开发者应该养成良好的命名习惯,遵循一致的命名规则,从而提升整个团队的开发效率。

    如何提高代码质量(管理篇):代码复查

    在软件开发过程中,提高代码质量是一项至关重要的任务。代码复查是确保代码质量的重要手段,它是一种同行评审过程,旨在发现并修复潜在的错误、不一致性和设计问题。本篇文章将探讨如何通过有效的代码复查来提升代码...

    一堂如何提高代码质量的培训课

    【提高代码质量】是软件开发领域中至关重要的议题。...总的来说,提高代码质量是一个持续的过程,需要开发者在编码时时刻关注可读性、可维护性和可变更性,通过不断的重构和优化,使得代码更加健壮、易于理解和维护。

    代码质量管理资料 包

    在IT行业中,代码质量管理是确保软件开发过程中的关键环节,旨在提高代码的可读性、可维护性和稳定性。本资料包包含了一系列与代码质量管理相关的文章和文档,涵盖了多个重要方面,如代码评审、单元测试、程序复杂度...

    提高代码质量的157个建议

    针对C#编程语言,以下是从“提高代码质量的157个建议”这一主题中提炼出的一些关键知识点: 1. **遵循编码规范**:统一的命名规则、注释风格和代码格式能让团队协作更顺畅,提高代码可读性。 2. **使用强类型**:...

    提高代码可读性的10个注释技巧

    ### 提高代码可读性的10个注释技巧 ...通过以上这些注释技巧的应用,可以显著提高代码的可读性和可维护性,进而提升软件项目的整体质量。无论是对于团队协作还是个人开发,良好的注释习惯都是非常宝贵的。

    如何全面的提高代码质量

    提高代码质量是一项长期而持续的任务,它不仅仅是程序员个人的责任,也是整个团队乃至组织文化的体现。通过不断地学习和实践,遵循最佳实践和原则,我们可以在提高软件质量和生产力方面取得显著的进步。

    代码行统计工具(统计代码质量)

    为了提高代码质量,开发者应该结合代码审查、静态代码分析和自动化测试等其他方法。而代码行统计工具则提供了一种量化的方式,帮助我们更好地理解和改进我们的代码库。通过定期使用这些工具,可以持续优化代码质量,...

    关于c语言编译预处理与代码质量的提高的三篇论文

    这三篇论文结合了理论与实践,旨在提升程序员对C语言编译预处理的理解,并通过编码技巧提高代码质量。对于中低水平的学习者来说,这些内容提供了深入学习和提高的基础,有助于他们在编程实践中做出更优的选择。

    编写可读性代码的艺术.docx

    《编写可读性代码的艺术》是一本专注于提升代码质量,特别是强调代码可读性的书籍。在IT行业中,尤其是在软件开发领域,代码的可读性至关重要,因为它直接影响到代码的维护和扩展。良好的代码可读性不仅是对其他...

    10种让代码更具可读性的方法

    在软件开发中,代码可读性是衡量代码质量的重要指标之一。当代码易于理解时,团队成员可以更快速地熟悉项目,减少错误和维护成本。以下是10种提高代码可读性的方法,这些方法也将有助于为单元测试打下基础,促进代码...

    java代码质量控制

    Java代码质量控制是软件开发过程中不可或缺的一环,它...利用各种工具,结合人工审查,可以有效地提高代码质量,为软件项目的成功打下坚实基础。开发团队应重视并实践这些工具和方法,以不断提升开发效率和软件质量。

    养成C++编程好习惯提高程序可读性_之注释篇

    良好的排版有助于提高代码的可读性。在添加注释时,需要注意以下几点: - **独立性**:注释和代码不应出现在同一行,除非注释是针对特定行的简短说明。 - **缩进**:注释的缩进应该与对应的代码块保持一致。 - **...

    追求代码质量.rar

    TDD(测试驱动开发)提倡先写测试,再写实现,有助于发现设计问题并提高代码质量。 3. **静态代码分析**:通过静态代码分析工具(如SonarQube、Pylint、ESLint等)可以在编码阶段发现潜在的错误和问题,如未使用的...

Global site tag (gtag.js) - Google Analytics