zoukankan      html  css  js  c++  java
  • 大话重构 之 你的参数列表像蚯蚓一样让人厌恶吗

    checkout("zhangsan", "chengdu",
    			"236891001Y", 1, 1.59,
    			"279645311R", 2, 2.50,
    			"357498670R", 1, 19.90,
    			"139776685")
    

    不知道小伙伴们看到上面的函数有何感想?一码是真的有股骂人的冲动。这一二一,一二一的,是在走正步吗?天知道是什么意思。如果你在一个大型商业项目中编写代码,则一定碰到过比这还凌乱的参数列表。。。想骂就骂吧,别憋出内伤。&#*``...

    长参数列表的由来

    为啥会写出这么长的参数列表呢?

    还真是有说法的。在面向过程的语言中,全局变量会使人陷入问题和调试的深渊。为了避免使用全局变量,大伙都谨遵一条法则:需要啥就向函数传啥。

    到了面向对象语言中,有人依然没有适应过来,在没人提醒的情况下,然后。。。就没有然后了。

    一码今天就来提醒依然有这个问题的小伙伴们。

    合理构建对象,隐藏部分数据

    在面向对象的语言中,对象即为数据和行为的结合体。对象有了数据,再调用对象方法的时候,需要传的数据就少多了。

    前提是构建合理的对象,让它封装一部分数据。

    拿篇首的例子来说,checkOut是选好商品后,去买单的意思。买单得有个人吧,消费者出来了。

    case class Customer(name: String, address: String)
    
    val customer = Customer("zhangsan", "chengdu")
    customer.checkout("236891001Y", 1, 1.59,
    			"279645311R", 2, 2.50,
    			"357498670R", 1, 19.90,
    			"139776685")
    

    消费者一出,参数减少了两个。

    该重构手法叫 提取类 ,在 消除过长类 中也有使用。

    引入参数对象

    继续识别对象。购物嘛,薯片1盒,苹果两斤,打包成对象,多个同类产品构成订单项,多个订单项构成订单。

    case class Product(id: String, price: Float)
    case class OrderItem(amount: Int, product: Product)
    case class Order(id: String, items: List[OrderItem])
    
    val orderItems = List(
    	OrderItem(1, Product("236891001Y", 1.59)),
    	OrderItem(2, Product("279645311R", 2.50)),
    	OrderItem(1, Product("357498670R", 19.90))
    )
    val order = Order("139776685", orderItems)
    
    customer.checkout(order)
    

    主谓宾,和造句一样,整个代码终于又有画面感了。道法自然,面向对象的代码也讲究自然。一个商业项目的代码会维护较长时间,人要读很多次,所以写代码一定要讲人话。面向对象对可读性的贡献不可谓不大。

    这种重构的手法,叫 引入对象参数 。顾名思义,把参数列表中相关度较高的参数打包形成对象,进而减少参数数量。该重构手法在 消除过长方法 一文中也有使用。

    除了上面的重构手法,还可以通过下面两种手法减少参数数量。

    保持对象完整

    如果发现方法的参数里面有多个来自于一个对象,那么就直接传入这个对象。

    val begin = dateRange.begin
    val end = dateRange.end
    
    withinPlan = plan.withinRange(begin, end)
    

    重载个withinRange方法,支持直接传入完整的DateRange对象。

    withinPlan = plan.withinRange(dateRange)
    

    保持对象完整消除过长方法 也有使用。

    用方法替代参数

    用方法替代参数 有以下两个两个场景:

    1. 方法中某个参数可以通过当前类内部的某个方法直接获得
    2. 方法中某个参数可以通过另外一个对象参数的方法直接获得
    val basePrice = quantity * itemPrice
    val discountLevel = getDiscountLevel()
    val finalPrice = discountPrice(basePrice, discountLevel)
    

    把discountLevel参数去掉,在discountPrice方法内部直接调用getDiscountLevel方法。

    val basePrice = quantity * itemPrice
    val finalPrice = discountPrice(basePrice)
    

    之前有人反馈说内容有难度,今天的主题应该还好,不长而且比较轻松,希望小伙伴们能有所收获,下一篇见。

    推荐

    解决万恶之首“重复代码”

    消除过长方法

    消除巨无霸类

    答读者问

    你的参数列表像蚯蚓一样让人厌恶吗

    职责单一原则真的简单吗

    查看《大话重构》系列文章,请进入YoyaProgrammer公众号,点击 核心技术,点击 大话重构。

    分类 大话重构

    优雅程序员 原创 转载请注明出处

    图片二维码

  • 相关阅读:
    Date类型转换成LocalDateTime 类型
    连接mysql数据库执行写入语句
    排序的的值为非数字时的处理方法
    git所遇到的问题
    visual studio快捷键
    Win10编译chromium
    下载chromium CIPD client失败的解决办法
    Linux内核源代码情景分析
    【赵强老师】史上最详细的PostgreSQL体系架构介绍
    3.Consul 安装配置(Proxysql+mgr)
  • 原文地址:https://www.cnblogs.com/yoyaprogrammer/p/long_method_parameters.html
Copyright © 2011-2022 走看看