# edev-refactor-helloworld **Repository Path**: mooodo/edev-refactor-helloworld ## Basic Information - **Project Name**: edev-refactor-helloworld - **Description**: 用C++演示软件重构的过程 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-09-01 - **Last Updated**: 2024-05-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: Refactor ## README # 用C++进行重构的过程 这是一个示例代码,演示了如何用C++进行软件重构的过程。当年Martin Fowler提出了重构的概念,让我们可以更加安全地修改代码,而不用担心会引入新的bug。通过这个重构的方法,我们可以让代码更加清晰、简洁、易于维护。然而,这样的方法不能仅仅停留在理论上。同时,重构的过程也不仅仅是某一次,而是无数次。因此,我们通过以下实际的代码来演示它逐步递进的应用过程。 ## 函数的重构 重构方法实际上是在不同层次上对代码的改进和优化,而在函数层面上的重构方法就是“抽取方法”(Extract Method)。这个方法的目的是将一个代码庞大、业务复杂的大函数,分解成多个短小而清晰的小型函数,从而提高代码的可读性和可维护性。在第一次重构中就演示了这样的重构过程。 ## 对象的重构 在对象层面上的重构方法就是“抽取类”(Extract Class)。这个方法的目的是将一个庞大、杂乱而无所不包的类,按照“单一职责原则”拆分成多个更加专注、职责更加单一的小类,从而提高代码的可复用性和可维护性。这对于改善复杂系统的可维护性和可扩展性尤为重要。 所有的软件系统都有这样的发展规律,就是随着业务的变更而变得越来越复杂,代码越来越多。这时候就需要对代码进行重构,在原有的代码中抽取出更多的类,让每个类都不会太大,也不会太小,达到一种动态平衡,从而让代码更加清晰、简洁、易于维护。拆分类的原则就是“单一职责原则”,而方法就是“抽取类”。在第二次重构中就演示了这样的重构过程。 然而,C++不是一个真正面向对象的编程语言,真正面向对象的语言(如Java、C#),一个类就是一个文件。而C++中一个cpp文件中可以有多个类,使得即使按照“单一职责原则”拆分出多个类,依然在一个文件中,依然难于维护。因此,在“抽取类”的同时,可以将每个类放到不同的文件中,用头文件来进行串联,从而更加清晰地组织代码。在第三次重构中就演示了这样的重构过程。 ## 接口的重构 对接口的软件重构就是“抽取接口”(Extract Interface)。这个方法的目的是将类和类的调用,通过抽取接口,变成类和接口的调用。这样,就可以在接口的基础上,编写各种不同的实现类,从而满足不同客户的需求。这对于软件的可扩展性和可维护性尤为重要。 然而,抽取接口理论上可行,实际上差强人意。一方面,接口的实现会影响系统的性能,这对于很多C++编写的系统来说,是无法接受的。另一方面,即使抽取出了一个接口与多个类,在C++中依然可以写在一个文件中,这样就无法真正实现接口的隔离。因此,在C++的重构中,可以将头文件和实现文件分离,从而实现与接口相同的效果。 在本案例中,当greetToUser和greetAboutTime通过头文件抽取出来以后,我们的客户可能会有2种不同甚至相互矛盾的需求,一个是用中文问候,一个是用英文问候。那么如何在同一版本中,同时满足这2类用户的需求呢?通过抽取头文件,然后为其写2个不同的实现,就可以在设计期用一个版本满足不同用户需求。 这里特别要注意重构的过程。按照“两顶帽子”的方法,在添加新功能时,应当在不添加新功能的前提下先进行重构,以适应新功能,然后再添加新功能。这样,才可以保证重构的安全性。 因此,我们首先通过重构抽取出一个头文件,以及它原有的实现,保证程序的正常运行(如第三次重构的过程)。然后,在头文件中定义一个宏,用来控制不同的实现。这样,我们可以在不同的cpp文件中,通过修改这个宏的值,来实现不同的实现。这样,在编译期通过修改宏程序的值,就可以为不同的用户编译出不同版本的程序,满足不同客户的需求。通过这种方式,就实现了与接口类似的功能,并且让程序变得易于维护和变更。第四次重构就演示了这样的重构过程。 ## 更高层次的重构 除了以上的重构过程以外,还可以在模块、组件、系统等更高层面上进行重构。这些更高层面上的重构,实际上是由无数个类似“抽取方法”、“抽取类”和“抽取接口”等代码级的重构积累而成的。因此,掌握代码级的重构,是更高层次重构的基础。但与代码级的重构不同的是,更高层次的重构需要站在更高的层面上先进行规划,形成重构的路线图,然后再一步步地进行代码级重构,逐步实施。这需要一个较长的过程,做好打持久战的准备。