重构-改善既有代码设计
In part 2 of this series I shared questions that dealt with code refactoring for Readability. In this part we’ll spend some time with another aspect, Extensibility. We’ll take the same practical question/discussion approach as in the last part so you’ll be able to get into the new world of refactoring as fast as possible.
在本系列的第2部分中 ,我分享了有关可读性代码重构的问题。 在这一部分中,我们将花一些时间讨论另一个方面,即可扩展性。 我们将采用与上一部分相同的实用问题/讨论方法,因此您将能够尽快进入重构的新世界。
Extensible code is a piece of code which follows re-usable, logical, well-known patterns, be it standard design patterns, or normal logical flow. Modular code tends to be highly extensible and monolithic code tends to be non-extensible, but monolithic code might be more efficient, so to solve this conundrum some practices allow developing in a modular way and deploying in a monolithic way so we can get the best of both worlds.
可扩展代码是遵循可重复使用的,逻辑的,众所周知的模式(无论是标准设计模式还是常规逻辑流程)的一段代码。 模块化代码趋向于高度可扩展,而整体代码趋向于不可扩展,但是整体代码可能更高效,因此,为了解决这一难题,一些实践允许以模块化方式进行开发并以整体方式进行部署,从而使我们能够获得最佳效果两个世界。
The major aspects which we are to discuss with regard to extensible code are: logical extensibility (normal logical flow and design patterns), modular design, and decoupling and encapsulation.
关于可扩展代码,我们要讨论的主要方面是:逻辑可扩展性(正常的逻辑流程和设计模式),模块化设计以及去耦和封装。
1. Do most code blocks follow normal logical flow?
1.大多数代码块是否遵循正常的逻辑流程?
When you are dealing with small logical problems, make sure you are using the right constructs (if, for, foreach, while, etc.). What I mean by the “right constructs” is you should be using the most logical and common language feature for the job. For example, looping through simple arrays should be done with foreach; this is common normal flow, whereas using a for loop for such simple iteration is not normal flow in a language like PHP. Using while is even more alien for such a simple task. You may have your reasons, in which case recall from the previous part about documenting any custom practice and you are okay.
当您处理小的逻辑问题时,请确保使用正确的构造(if,for,foreach,while等)。 我所说的“正确的构想”是您应该在工作中使用最合逻辑且通用的语言功能。 例如,循环简单数组应该使用foreach来完成; 这是普通的正常流程,而对于像PHP这样的语言,使用for循环进行这种简单的迭代并不是正常的流程。 对于这样一个简单的任务,使用while更为陌生。 您可能有自己的理由,在这种情况下,请回想一下上一部分中有关记录任何自定义惯例的内容,您还可以。
2. Do complex problem solutions follow standard design patterns?
2.复杂的问题解决方案是否遵循标准设计模式?
When I first started working with PHP, I wasn’t much aware of design patterns. Now I find using design patterns is a must for large scale projects because they are commonly understood and account for future development.
刚开始使用PHP时,我对设计模式并不了解。 现在,我发现对于大型项目,必须使用设计模式,因为它们通常被理解并考虑到未来的发展。
A common complex problem for which you should use a well defined standard pattern to solve is creating various instances of some class. But why and when to use the factory design pattern? It’s probably debatable, but a general guideline, if you have different implementations of the same interface and you require implementing objects to be created dynamically, then the pattern may be suitable. Another case may be when generating a number of dynamic objects of the same class but when the number is only known at runtime. For instance, a modern GUI-intensive web application might necessitate creating rows of form inputs dynamically for database records. Examples are endless of when design patterns can be useful.
您应该使用定义明确的标准模式来解决的一个常见的复杂问题是创建某个类的各种实例。 但是,为什么以及何时使用工厂设计模式? 这可能是值得商de的,但是是一般准则,如果您对同一接口有不同的实现,并且需要动态创建实现对象,那么该模式可能是合适的。 另一种情况可能是在生成多个相同类的动态对象时,但仅在运行时才知道该数量。 例如,现代的GUI密集型Web应用程序可能需要动态创建数据库记录的表单输入行。 设计模式何时有用的例子无穷无尽。
1. Do code structures follow modular design?
1.代码结构是否遵循模块化设计?
Modular design means that you divide your application into modules. A large app made up of smaller apps are easier to develop and are easier to extend and maintain. Each module should collect a bunch of related features and functionalities and group them together in a single entity.
模块化设计意味着您可以将应用程序分为模块。 由较小的应用程序组成的大型应用程序更易于开发,更易于扩展和维护。 每个模块应收集一堆相关的特性和功能,并将它们组合在一个实体中。
Core functionality and application entry points may be treated as modules as well. You may then add functionality in the future by adding new modules. Some people call modules used in this manner plugins. Whatever design and structure you choose for your application though, you need to make sure how modules/plugins are loaded and unloaded, what their basic structure is, etc. and account for it before developing the core module.
核心功能和应用程序入口点也可以视为模块。 然后,您将来可以通过添加新模块来添加功能。 有人将以这种方式使用的模块称为插件。 但是,无论为应用程序选择哪种设计和结构,在开发核心模块之前,都需要确保如何加载和卸载模块/插件,其基本结构是什么,等等。
Whenever you see groups of code in some module acting as a single sub-entity of it and being consumed by that top module with minimum parameters, why not split it off into a new module? Generally, when I have a sub-entity that splits more than a single class doing some side tasks, I will move it without hesitation to a new module.
每当您看到某个模块中的代码组充当其单个子实体并被带有最少参数的顶级模块占用时,为什么不将其拆分为一个新模块? 通常,当我有一个子实体拆分多个类来执行一些副任务时,我会毫不犹豫地将其移动到新模块中。
Utility modules are a neat solution for orphaned code in a well designed modular application. Whenever I have some orphaned code, I move it to a utility module that handles snippets and mini tasks. The module is made up generally of orphaned functions and small classes. Whenever these tasks are big enough, I start moving them to it’s own separate module in a continuous process of refactoring.
实用程序模块是精心设计的模块化应用程序中孤立代码的简洁解决方案。 每当我有一些孤立的代码时,我都会将其移至处理代码片段和小型任务的实用程序模块。 该模块通常由孤立的函数和小类组成。 只要这些任务足够大,我就会在连续的重构过程中开始将它们移到它自己的单独模块中。
2. Are modules dependency minimum?
2.模块依赖性最小吗?
Modules should be self-contained as much as possible. Soft module dependencies are natural and good, such as “Inventory” module being dependent on an “Accounting” module for getting a homogeneous e-commerce system, but many hard dependencies are bad. They make debugging and deployment much more difficult.
模块应尽可能独立。 软模块依赖关系是自然而良好的,例如“库存”模块依赖于“会计”模块来获取同类的电子商务系统,但是许多硬依赖关系则很糟糕。 它们使调试和部署变得更加困难。
To ensure less inter-module dependencies, you have to iterate over your code base every now and then to see if there are any hard dependencies between modules. Clear them if you can, and if you can’t then you should make both modules into a single module with a more generic name. For example, in the e-commerce app you might have an “Items” module and an “Inventory” management module, and classes from the inventory are intensively using classes from items and vice-versa. I would merge both and rename the module “Inventory” which has a sub-module for dealing with items.
为了确保减少模块间的依赖性,您必须不时地遍历代码库,然后查看模块之间是否存在任何硬性依赖性。 如果可以,请清除它们,如果不能,则应将两个模块合并为一个具有更通用名称的模块。 例如,在电子商务应用程序中,您可能具有“项目”模块和“库存”管理模块,并且库存中的类正大量使用项目中的类,反之亦然。 我将两者合并并重命名模块“库存”,该模块具有一个用于处理物料的子模块。
1. Are functions, methods, and classes fairly decoupled?
1.函数,方法和类是否完全解耦?
Adding a paging feature to display results coming from a database is a very common task. In fact, early in my PHP development career I was writing some code to do paging for results; the code at first was procedural, constituting very specific functions for dealing with the database and results. I decided then to decouple the paging algorithm from each of the components where I used it with a variation of the Strategy pattern. Whenever you find your self duplicating logic or code, you probably need to do some decoupling of your own to enhance code re-usability and extensibility.
添加分页功能以显示来自数据库的结果是一项非常常见的任务。 实际上,在我PHP开发生涯的早期,我正在编写一些代码来进行分页以获得结果。 最初的代码是过程性的,构成了用于处理数据库和结果的非常特定的功能。 然后,我决定将分页算法与我使用过的每个组件分离开来,并使用不同的策略模式。 每当发现自己的自我复制逻辑或代码时,您可能都需要对自己进行解耦,以增强代码的可重用性和可扩展性。
2. Are modules and components fairly decoupled?
2.模块和组件是否完全分离?
When keeping dependencies to a minimum, you are decoupling the right way. There’s no 100% decoupling between any two related things; coupling is natural, so you should always decouple but not much so as not to end up making your code more complicated. As a guideline, decouple until your modules and components of your code base can talk together without having a lot in commonalities duplicated.
当保持最小依赖性时,您将以正确的方式解耦。 任何两个相关的事物之间都不存在100%的去耦关系。 耦合是很自然的,因此您应该始终解耦,但不要过多,以免最终使您的代码更复杂。 原则上,要脱钩,直到代码库的模块和组件可以一起交谈,而不必重复很多共同点。
Keep in mind that lowering dependencies is directly proportional to usability and extensibility whenever complexity is not increasing. When complexity starts to increase, the relationship starts to be in-directly proportional.
请记住,只要不增加复杂性,降低依赖关系就与可用性和可扩展性成正比。 当复杂性开始增加时,该关系开始间接成比例。
In this part we discussed refactoring your code for extensibility, concentrating the discussion on three main aspects: logical extensibility, modular design, and decoupling and encapsulation. Hopefully now you are starting to gain better insight of how to develop and maintain better applications. In the final part we’ll discuss how to refactor for better efficiency without compromising readability and extensibility.
在这一部分中,我们讨论了重构代码以实现可扩展性,并将讨论集中在三个主要方面:逻辑可扩展性,模块化设计以及去耦和封装。 希望现在您开始对如何开发和维护更好的应用程序有更好的了解。 在最后一部分中,我们将讨论如何在不影响可读性和可扩展性的情况下重构以获得更好的效率。
Image via Fotolia
图片来自Fotolia
翻译自: https://www.sitepoint.com/practical-code-refactoring-3/
重构-改善既有代码设计
相关资源:重构:改善既有代码的设计.[美]Martin Fowler(带详细书签).pdf