iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >怎么让代码不再臃肿,写的像诗一样优雅
  • 697
分享到

怎么让代码不再臃肿,写的像诗一样优雅

2023-06-02 18:06:20 697人浏览 八月长安
摘要

基本类型偏执基本类型偏执(Primitive Obsession)使用基本类型而不是小对象来实现简单任务(例如货币、范围、电话号码字符串等)。使用常量编码信息(例如一个用于引用管理员权限的常量USER_ADMIN_ROLE = 1 

基本类型偏执

基本类型偏执(Primitive Obsession)

  • 使用基本类型而不是小对象来实现简单任务(例如货币、范围、电话号码字符串等)。
  • 使用常量编码信息(例如一个用于引用管理员权限的常量USER_ADMIN_ROLE = 1 )。
  • 使用字符串常量作为字段名在数组中使用。

怎么让代码不再臃肿,写的像诗一样优雅

问题原因

类似其他大部分坏味道,基本类型偏执诞生于类初建的时候。一开始,可能只是不多的字段,随着表示的特性越来越多,基本数据类型字段也越来越多。

基本类型常常被用于表示模型的类型。你有一组数字或字符串用来表示某个实体。

还有一个场景:在模拟场景,大量的字符串常量被用于数组的索引

解决方法

怎么让代码不再臃肿,写的像诗一样优雅

大多数编程语言都支持基本数据类型和结构类型(类、结构体等)。结构类型允许程序员将基本数据类型组织起来,以代表某一事物的模型。

基本数据类型可以看成是机构类型的积木块。当基本数据类型数量成规模后,将它们有组织地结合起来,可以更方便的管理这些数据。

  • 如果你有大量的基本数据类型字段,就有可能将其中部分存在逻辑联系的字段组织起来,形成一个类。更进一步的是,将与这些数据有关联的方法也一并移入类中。为了实现这个目标,可以尝试 以类取代类型码(Replace Type Code with Class) 。
  • 如果基本数据类型字段的值是用于方法的参数,可以使用 引入参数对象(Introduce Parameter Object) 或 保持对象完整(Preserve Whole Object) 。
  • 如果想要替换的数据值是类型码,而它并不影响行为,则可以运用 以类取代类型码(Replace Type Code with Class) 将它替换掉。如果你有与类型码相关的条件表达式,可运用 以子类取代类型码(Replace Type Code with Subclass) 或 以状态/策略模式取代类型码(Replace Type Code with State/Strategy) 加以处理。
  • 如果你发现自己正从数组中挑选数据,可运用 以对象取代数组(Replace Array with Object) 。

收益

  • 多亏了使用对象替代基本数据类型,使得代码变得更加灵活。
  • 代码变得更加易读和更加有组织。特殊数据可以集中进行操作,而不像之前那样分散。不用再猜测这些陌生的常量的意义以及它们为什么在数组中。
  • 更容易发现重复代码。

怎么让代码不再臃肿,写的像诗一样优雅

重构方法说明

以类取代类型码(Replace Type Code with Class)

问题

类之中有一个数值类型码,但它并不影响类的行为。

怎么让代码不再臃肿,写的像诗一样优雅

解决

以一个新的类替换该数值类型码。

怎么让代码不再臃肿,写的像诗一样优雅

引入参数对象(Introduce Parameter Object)

问题

某些参数总是很自然地同时出现。

怎么让代码不再臃肿,写的像诗一样优雅

解决

以一个对象来取代这些参数。 

怎么让代码不再臃肿,写的像诗一样优雅

保持对象完整(Preserve Whole Object)

问题

你从某个对象中取出若干值,将它们作为某一次函数调用时的参数。

int low = daysTempRange.getLow();int high = daysTempRange.getHigh();boolean withinPlan = plan.withinRange(low, high);

解决

改为传递整个对象。

boolean withinPlan = plan.withinRange(daysTempRange);
以子类取代类型码(Replace Type Code with Subclass)

问题

你有一个不可变的类型码,它会影响类的行为。

怎么让代码不再臃肿,写的像诗一样优雅

解决

以子类取代这个类型码。

怎么让代码不再臃肿,写的像诗一样优雅

以状态/策略模式取代类型码(Replace Type Code with State/Strategy)

问题

你有一个类型码,它会影响类的行为,但你无法通过继承消除它。

怎么让代码不再臃肿,写的像诗一样优雅

解决

以状态对象取代类型码。

怎么让代码不再臃肿,写的像诗一样优雅

以对象取代数组(Replace Array with Object)

问题

你有一个数组,其中的元素各自代表不同的东西。

String[] row = new String[3];row[0] = "Liverpool";row[1] = "15";

解决

以对象替换数组。对于数组中的每个元素,以一个字段来表示。

PerfORMance row = new Performance();row.setName("Liverpool");row.setWins("15");

数据泥团

数据泥团(Data Clumps)

有时,代码的不同部分包含相同的变量组(例如用于连接到数据库的参数)。这些绑在一起出现的数据应该拥有自己的对象。

怎么让代码不再臃肿,写的像诗一样优雅

问题原因

通常,数据泥团的出现时因为糟糕的编程结构或“复制-粘贴式编程”。

有一个判断是否是数据泥团的好办法:删掉众多数据中的一项。这么做,其他数据有没有因而失去意义?如果它们不再有意义,这就是个明确的信号:你应该为它们产生一个新的对象。

解决方法

  • 首先找出这些数据以字段形式出现的地方,运用 提炼类(Extract Class) 将它们提炼到一个独立对象中。
  • 如果数据泥团在函数的参数列中出现,运用 引入参数对象(Introduce Parameter Object) 将它们组织成一个类。
  • 如果数据泥团的部分数据出现在其他函数中,考虑运用 保持对象完整(Preserve Whole Object) 将整个数据对象传入到函数中。
  • 检视一下使用这些字段的代码,也许,将它们移入一个数据类是个不错的主意。

收益

  • 提高代码易读性和组织性。对于特殊数据的操作,可以集中进行处理,而不像以前那样分散。
  • 减少代码量。

怎么让代码不再臃肿,写的像诗一样优雅

何时忽略

  • 有时为了对象中的部分数据而将整个对象作为参数传递给函数,可能会产生让两个类之间不收欢迎的依赖关系,这中情况下可以不传递整个对象。

重构方法说明

提炼类(Extract Class)

问题

某个类做了不止一件事。

怎么让代码不再臃肿,写的像诗一样优雅

解决

建立一个新类,将相关的字段和函数从旧类搬移到新类。

怎么让代码不再臃肿,写的像诗一样优雅

引入参数对象(Introduce Parameter Object)

问题

某些参数总是很自然地同时出现。

怎么让代码不再臃肿,写的像诗一样优雅

解决

以一个对象来取代这些参数。

怎么让代码不再臃肿,写的像诗一样优雅

保持对象完整(Preserve Whole Object)

问题

你从某个对象中取出若干值,将它们作为某一次函数调用时的参数。

int low = daysTempRange.getLow();int high = daysTempRange.getHigh();boolean withinPlan = plan.withinRange(low, high);

解决

改为传递整个对象。

boolean withinPlan = plan.withinRange(daysTempRange);

过大的类

过大的类(Large Class)

一个类含有过多字段、函数、代码行。

怎么让代码不再臃肿,写的像诗一样优雅

问题原因

类通常一开始很小,但是随着程序的增长而逐渐膨胀。

类似于过长函数,程序员通常觉得在一个现存类中添加新特性比创建一个新的类要容易。

解决方法

设计模式中有一条重要原则:职责单一原则。一个类应该只赋予它一个职责。如果它所承担的职责太多,就该考虑为它减减负。

怎么让代码不再臃肿,写的像诗一样优雅

  • 如果过大类中的部分行为可以提炼到一个独立的组件中,可以使用 提炼类(Extract Class)
  • 如果过大类中的部分行为可以用不同方式实现或使用于特殊场景,可以使用 提炼子类(Extract Subclass)
  • 如果有必要为客户端提供一组操作和行为,可以使用 提炼接口(Extract Interface)
  • 如果你的过大类是个 GUI 类,可能需要把数据和行为移到一个独立的领域对象去。你可能需要两边各保留一些重复数据,并保持两边同步。 复制被监视数据(Duplicate Observed Data) 可以告诉你怎么做。

收益

  • 重构过大的类可以使程序员不必记住一个类中大量的属性。
  • 在大多数情况下,分割过大的类可以避免代码和功能的重复。

怎么让代码不再臃肿,写的像诗一样优雅

重构方法说明

提炼类(Extract Class)

问题

某个类做了不止一件事。

怎么让代码不再臃肿,写的像诗一样优雅

解决

建立一个新类,将相关的字段和函数从旧类搬移到新类。

怎么让代码不再臃肿,写的像诗一样优雅

提炼子类(Extract Subclass)

问题

一个类中有些特性仅用于特定场景。

怎么让代码不再臃肿,写的像诗一样优雅

解决

创建一个子类,并将用于特殊场景的特性置入其中。

怎么让代码不再臃肿,写的像诗一样优雅

提炼接口(Extract Interface)

问题

多个客户端使用一个类部分相同的函数。另一个场景是两个类中的部分函数相同。

怎么让代码不再臃肿,写的像诗一样优雅

解决

移动相同的部分函数到接口中。

怎么让代码不再臃肿,写的像诗一样优雅

复制被监视数据(Duplicate Observed Data)

问题

如果存储在类中的数据是负责 GUI 的。

怎么让代码不再臃肿,写的像诗一样优雅

解决

一个比较好的方法是将负责 GUI 的数据放入一个独立的类,以确保 GUI 数据与域类之间的连接和同步。

怎么让代码不再臃肿,写的像诗一样优雅

过长函数

过长函数(Long Method)

一个函数含有太多行代码。一般来说,任何函数超过 10 行时,你就可以考虑是不是过长了。 函数中的代码行数原则上不要超过 100 行。

怎么让代码不再臃肿,写的像诗一样优雅

问题的原因

通常情况下,创建一个新函数的难度要大于添加功能到一个已存在的函数。大部分人都觉得:“我就添加这么两行代码,为此新建一个函数实在是小题大做了。”于是,张三加两行,李四加两行,王五加两行。。。函数日益庞大,最终烂的像一锅浆糊,再也没人能完全看懂了。于是大家就更不敢轻易动这个函数了,只能恶性循环的往其中添加代码。所以,如果你看到一个超过 200 行的函数,通常都是多个程序员东拼西凑出来的。

解决函数

一个很好的技巧是:寻找注释。添加注释,一般有这么几个原因:代码逻辑较为晦涩或复杂;这段代码功能相对独立;特殊处理。 如果代码前方有一行注释,就是在提醒你:可以将这段代码替换成一个函数,而且可以在注释的基础上给这个函数命名。如果函数有一个描述恰当的名字,就不需要去看内部代码究竟是如何实现的。就算只有一行代码,如果它需要以注释来说明,那也值得将它提炼到独立函数中。

怎么让代码不再臃肿,写的像诗一样优雅

 

  • 为了给一个函数瘦身,可以使用 提炼函数(Extract Method)
  • 如果局部变量和参数干扰提炼函数,可以使用 以查询取代临时变量(Replace Temp with Query)引入参数对象(Introduce Parameter Object) 或 保持对象完整(Preserve Whole Object) 。
  • 如果前面两条没有帮助,可以通过 以函数对象取代函数(Replace Method with Method Object) 尝试移动整个函数到一个独立的对象中。
  • 条件表达式和循环常常也是提炼的信号。对于条件表达式,可以使用 分解条件表达式(Decompose Conditional) 。至于循环,应该使用 提炼函数(Extract Method) 将循环和其内的代码提炼到独立函数中。

收益

  • 在所有类型的面向对象代码中,函数比较短小精悍的类往往生命周期较长。一个函数越长,就越不容易理解和维护。
  • 此外,过长函数中往往含有难以发现的重复代码。

怎么让代码不再臃肿,写的像诗一样优雅

性能

是否像许多人说的那样,增加函数的数量会影响性能?在几乎绝大多数情况下,这种影响是可以忽略不计,所以不用担心。 此外,现在有了清晰和易读的代码,在需要的时候,你将更容易找到真正有效的函数来重组代码和提高性能。

重构方法说明

提炼函数(Extract Method)

问题

你有一段代码可以组织在一起。

void printOwing() {  printBanner();  //print details  System.out.println("name: " + name);  System.out.println("amount: " + getOutstanding());}

解决

移动这段代码到一个新的函数中,使用函数的调用来替代老代码。

void printOwing() {  printBanner();  printDetails(getOutstanding());}void printDetails(double outstanding) {  System.out.println("name: " + name);  System.out.println("amount: " + outstanding);}
以查询取代临时变量(Replace Temp with Query)

问题

将表达式的结果放在局部变量中,然后在代码中使用。

double calculateTotal() {  double basePrice = quantity * itemPrice;  if (basePrice > 1000) {    return basePrice * 0.95;  }  else {    return basePrice * 0.98;  }}

解决

将整个表达式移动到一个独立的函数中并返回结果。使用查询函数来替代使用变量。如果需要,可以在其他函数中合并新函数。

double calculateTotal() {  double basePrice = quantity * itemPrice;  if (basePrice > 1000) {    return basePrice * 0.95;  }  else {    return basePrice * 0.98;  }}
引入参数对象(Introduce Parameter Object)

问题

某些参数总是很自然地同时出现。

怎么让代码不再臃肿,写的像诗一样优雅

解决

以一个对象来取代这些参数。

怎么让代码不再臃肿,写的像诗一样优雅

保持对象完整(Preserve Whole Object)

问题

你从某个对象中取出若干值,将它们作为某一次函数调用时的参数。

int low = daysTempRange.getLow();int high = daysTempRange.getHigh();boolean withinPlan = plan.withinRange(low, high);

解决

改为传递整个对象。

boolean withinPlan = plan.withinRange(daysTempRange);
以函数对象取代函数(Replace Method with Method Object)

问题

你有一个过长函数,它的局部变量交织在一起,以致于你无法应用提炼函数(Extract Method) 。

class Order {  //...  public double price() {    double primaryBasePrice;    double secondaryBasePrice;    double tertiaryBasePrice;    // long computation.    //...  }}

解决

将函数移到一个独立的类中,使得局部变量成了这个类的字段。然后,你可以将函数分割成这个类中的多个函数。

class Order {  //...  public double price() {    return new PriceCalculator(this).compute();  }}class PriceCalculator {  private double primaryBasePrice;  private double secondaryBasePrice;  private double tertiaryBasePrice;  public PriceCalculator(Order order) {    // copy relevant information from order object.    //...  }  public double compute() {    // long computation.    //...  }}
分解条件表达式(Decompose Conditional)

问题

你有复杂的条件表达式。

if (date.before(SUMMER_START) || date.after(SUMMER_END)) {  charge = quantity * winterRate + winterServiceCharge;}else {  charge = quantity * summerRate;}

解决

根据条件分支将整个条件表达式分解成几个函数。

if (notSummer(date)) {  charge = winterCharge(quantity);}else {  charge = summerCharge(quantity);}

过长参数列

过长参数列(Long Parameter List)

一个函数有超过 3、4 个入参。

怎么让代码不再臃肿,写的像诗一样优雅

问题原因

过长参数列可能是将多个算法并到一个函数中时发生的。函数中的入参可以用来控制最终选用哪个算法去执行。

过长参数列也可能是解耦类之间依赖关系时的副产品。例如,用于创建函数中所需的特定对象的代码已从函数移动到调用函数的代码处,但创建的对象是作为参数传递到函数中。因此,原始类不再知道对象之间的关系,并且依赖性也已经减少。但是如果创建的这些对象,每一个都将需要它自己的参数,这意味着过长参数列。

太长的参数列难以理解,太多参数会造成前后不一致、不易使用,而且一旦需要更多数据,就不得不修改它。

解决方案

怎么让代码不再臃肿,写的像诗一样优雅

 

  • 如果向已有的对象发出一条请求就可以取代一个参数,那么你应该使用 以函数取代参数(Replace Parameter with Methods) 。在这里,,“已有的对象”可能是函数所属类里的一个字段,也可能是另一个参数。
  • 你还可以运用 保持对象完整(Preserve Whole Object) 将来自同一对象的一堆数据收集起来,并以该对象替换它们。
  • 如果某些数据缺乏合理的对象归属,可使用 引入参数对象(Introduce Parameter Object) 为它们制造出一个“参数对象”。

收益

  • 更易读,更简短的代码。
  • 重构可能会暴露出之前未注意到的重复代码。

何时忽略

  • 这里有一个重要的例外:有时候你明显不想造成"被调用对象"与"较大对象"间的某种依赖关系。这时候将数据从对象中拆解出来单独作为参数,也很合情理。但是请注意其所引发的代价。如果参数列太长或变化太频繁,就需要重新考虑自己的依赖结构了。

重构方法说明

以函数取代参数(Replace Parameter with Methods)

问题

对象调用某个函数,并将所得结果作为参数,传递给另一个函数。而接受该参数的函数本身也能够调用前一个函数。

int basePrice = quantity * itemPrice;double seasonDiscount = this.getSeasonalDiscount();double fees = this.getFees();double finalPrice = discountedPrice(basePrice, seasonDiscount, fees);

解决

让参数接受者去除该项参数,并直接调用前一个函数。

int basePrice = quantity * itemPrice;double finalPrice = discountedPrice(basePrice);
保持对象完整(Preserve Whole Object)

问题

你从某个对象中取出若干值,将它们作为某一次函数调用时的参数。

int low = daysTempRange.getLow();int high = daysTempRange.getHigh();boolean withinPlan = plan.withinRange(low, high);

解决

改为传递整个对象。

boolean withinPlan = plan.withinRange(daysTempRange);
引入参数对象(Introduce Parameter Object)

问题

某些参数总是很自然地同时出现。

怎么让代码不再臃肿,写的像诗一样优雅

解决

以一个对象来取代这些参数。

怎么让代码不再臃肿,写的像诗一样优雅

--结束END--

本文标题: 怎么让代码不再臃肿,写的像诗一样优雅

本文链接: https://www.lsjlt.com/news/230838.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么让代码不再臃肿,写的像诗一样优雅
    基本类型偏执基本类型偏执(Primitive Obsession)使用基本类型而不是小对象来实现简单任务(例如货币、范围、电话号码字符串等)。使用常量编码信息(例如一个用于引用管理员权限的常量USER_ADMIN_ROLE = 1 ...
    99+
    2023-06-02
  • 这样写python注释让代码更加的优雅
    python这样注释,让你的代码看起来更加的优雅,是不是常常感觉自己的python代码写出来,看起来特别的乱,虽然可以正常运行,但是在优雅性上似乎欠缺的很多,这篇文章主要教你,如何让...
    99+
    2024-04-02
  • 怎么写出优雅的C++代码
    本篇内容主要讲解“怎么写出优雅的C++代码”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么写出优雅的C++代码”吧!工欲善其事必先利其器,优雅的代码离不开静态代码检查工具,大家可能平时使用较多...
    99+
    2023-06-15
  • 怎么写出优雅的Java代码
    这篇文章主要讲解了“怎么写出优雅的Java代码”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么写出优雅的Java代码”吧!1.使用 IntelliJ IDEA 作为您的集成开发环境 (ID...
    99+
    2023-06-16
  • 怎么写出让人看起来很优雅舒服的python代码
    这篇文章将为大家详细讲解有关怎么写出让人看起来很优雅舒服的python代码,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。很多新手在开始学一门新的语言的时候,往往会忽视一些不应该忽视的细节,比...
    99+
    2023-06-02
  • 怎么写出优雅耐看的JavaScript代码
    这篇文章主要介绍“怎么写出优雅耐看的JavaScript代码”,在日常操作中,相信很多人在怎么写出优雅耐看的JavaScript代码问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解...
    99+
    2024-04-02
  • 怎么写出优雅耐看的css代码
    这篇“怎么写出优雅耐看的css代码”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面...
    99+
    2024-04-02
  • 怎么写出清晰又优雅的Python代码
    本篇文章为大家展示了怎么写出清晰又优雅的Python代码,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。个人认为,下面这几条规则是绝对应该遵循的。01 与空白有关的建议在Python中,空白(whit...
    99+
    2023-06-15
  • web开发中让DIV一直固定在屏幕的某个位置示例代码该怎么写
    web开发中让DIV一直固定在屏幕的某个位置示例代码该怎么写,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 代...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作