2018-02-09 可以降低圈复杂度的10种重构技术

Composing Methods(重新组织你的函数)

1.Extract Method(提炼函数)

代码段可被组织在一起并独立出来

void printOwing(double previousAmount)
{
  Enumeration e = _orders.elements();
  double outstanding = previousAmount * 1.2;

  // print banner
  System.out.println ("* * * * * * * * * * * * * * * * * * * * * * *");
  System.out.println ("Customer Owes ");
  System.out.println (" * * * * * * * * * * * * * * * * * * * * * * *");

  // calculate outstanding
  while (e.hasMoreElements())
  {
    Order each = (Order) e.nextElement();
    outstanding += each.getAmount();
  }

  //print details
  System.out.println ("name:" +_name);
  System.out.println ("amount" + outstanding)
}

将这段代码放进一个独立函数中,并让函数名称解释该函数的用途

void printOwing(double previousAmount)
{
  printBanner();
  double  outstanding  =  getOutsta nding(previousAmount  *  1.2);
  printDetads(outstanding);
}

void printBanner0
{
   // print banner
.....
}

double getOutstanding(double initialValue)
{
  double result = initialValue;
  Enumeration e =  orders.elements();
  while (e.hasMoreElements())
  {
    Order each = (Order) e.nextElement();
     result += each.getAmount();
  }
  return result;
}

void printDetails (double outstanding)
 {
  //print details
...
}

2.Substitute Algorithm(替换你的算法)

把某个算法替换为另一个更清晰的算法

String foundPerson(String[] people)
{
  for (int i = 0; i < people.length; i++)
  {
      if (people[i].equals ("Don"))
       return "Don";
      if (people[i].equals ("John"))
       return "John";
      if (people[i].equals ("Kent"))
       return "Kent";
  }
  return "";
}

将函数本体替换为另一个算法

String foundPerson(String[] people)
{
   List candidates = Arrays.asList(new String[]{"Don", "John","Kent"});
   for (int i=0; i<people.length; i++)
      if (candidates.contains(people[i]))
         return people[i];
  return "";
}

Simplifying Conditional Expressions(简化条件表达式)

3. Decompose Conditional(分解条件式)

你有一个复杂的条件语句,从if、else段落中分别提炼出独立函数

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);

4.Consolidate Conditional Expression(合并条件式)

你有一系列条件判断,都得到相同结果,将这些判断合并为一个条件式,并将条件式提炼成为独立函数。

double disabilityAmount()
{
   if (_seniority < 2) return 0;
   if (_monthsDisabled > 12) return 0;
   if (_isPartTime) return 0;
   // compute the disability amount
...
}

修改成

double disabilityAmount()
{
   if (isNotEligableForDisability()) return 0;
   // compute the disability amount
...
}

5.Consolidate Duplicate Conditional Fragments(合并重复的条件片断)

在条件式的每个分支上有着相同的一段代码, 将这段重复代码搬移到条件式之外。

if (isSpeciaIDeal())
  {
     total = price * 0.95
     send();
  }
else
  {
     total = price* 0.98
     send();
  }

修改成

if (isSpeciaIDeal())
   total = price * 0.95
else
   total = price * 0.98
send();

6.Remove Control Flag(移除控制标记)

在一系列布尔表达式种,某个变量带有【控制标记】的作用,以break和return取代控制标记

void checkSecurity(String[] people) {
  boolean found = false;
  for (int i = 0; i < people.length; i++) {
      if (l found) {
         if (people[i].equals ("Don")){
          sendAlert();
           found = true;
       }
         if (people[i].equals ("John")){
           sendAlert();
             found = true;
       }
     }
  }
}

变成

void checkSecurity(String[] people) {
  for (int i = 0; i < people.length; i++) {
      if (people[i].equals ("Don")){
       sendAlert();
       break;
     }
      if (people[i].equals ("John")){
       sendAlert();
       break;
     }
  }
}

Making Method Calls Simpler(简化函数调用)

7.Separate Query from Modifier(将查询函数和修改函数分离)

某个函数既返回对象状态值,又修改对象状态。 建立两个不同的函数, 其中一个负责查询,另一个负责修改

Customer::getTotalOutstandingAndSetReadyForSummaries(...)
{
...
}

分成两个函数

Customer::getTotalOutstanding(...)
{
...
}
Customer::SetReadyForSummaries(...)
{
...
}

8.Parameterize Method(令函数携带参数)

若干函数做了类似的工作,但在函数本体中却包含了不同的值。建立单一函数,以参数表达那些不同的值

Dollars baseCharge0
 {
   double result = Math.min(lastUsage(),l00) * 0.03;
   if (lastUsage() > 100) {
     result += (Math.min (lastUsage(),200) - 100) * 0.05;
  };
   if (lastUsage() > 200) {
     result += (lastUsage() - 200)*0.07;
  };
  return new Dollars (result);
}

修改成

Dollars baseCharge()
{
   double result = usagelnRange(0, 100)* 0.03;
   result += usagelnRange (100,200) * 0.05;
   result += usagelnRange (200, Integer.MAX  VALUE) * 0.07
  return new Dollars (result);
}
int usagelnRange(int start, int end)
{
   if (lastUsage() > start)
     return Math.min(lastUsage(),end) -start
   else
     return 0;
}

9.Replace Parameter with Explicit Methods(以明确函数取代参数)

函数实现完全取决于参数值而采取不同反应,针对该参数的每一个可能值,建立一个独立函数

void setValue (String name, int value)
{
   if (name.equals("height"))
      _height = value;
   if (name.equals("width"))
      _width = value;
  Assert.shouldNeverReachHere();
}

改成

void setHeight(int arg)
{
  _height = arg;
}
void setWidth (int arg)
{
  _width = arg;
}

10.Replace Conditional with Polymorphism(以多态取代条件式)

你手上有个条件式,它根据对象类型的不同而选择不同的行为。那么,将整个条件式的每个分支放进子类的重载方法中, 然后将原始函数声明为抽象方法

double getSpeed()
{
   switch (_type) {
     case EUROPEAN:
       return getBaseSpeed();
     case AFRICAN:
      return getBaseSpeed() - getLoadFactor() *_numberOfCoconuts;
     case NORWEGIAN_BLUE:
       return (isNailed)  ? 0 : getBaseSpeed(_voltage);
    }
  throw new RuntimeException ("Should be unreachable");
}

修改成


image.png

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容

  • 一个软件总是为解决某种特定的需求而产生,时代在发展,客户的业务也在发生变化。有的需求相对稳定一些,有的需求变化的比...
    Rance935阅读 7,845评论 0 9
  • 阅读《重构》的笔记献上。 重构的定义 重构是在不改变软件可观察行为的前提下改善其内部结构。 重构的节奏 以微小的步...
    陈宇明阅读 11,607评论 13 64
  • 一,重构,第一个案例 这一章作者先用一个影片出租程序的案例,来演示重构的过程 每个Customer顾客可以租多部M...
    高稷阅读 10,766评论 1 19
  • 前些天,逛超市看到里脊搞活动,又很鲜嫩,便买了些来。昨日去玉渊潭,看到锦州豆皮,也买了些,今日便给波爸和昊宝做了京...
    懒妈一枚阅读 773评论 2 4
  • 这本书是核聚推荐的,核聚是我在写作群里一个男生—欢喜,文章中经常提及的人物。大概是一个北大博士,没有运动员经验的他...
    春天的约会阅读 353评论 0 3