前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

简化

作者头像
超级大猪
发布2019-11-22 14:53:08
6610
发布2019-11-22 14:53:08
举报
文章被收录于专栏:大猪的笔记大猪的笔记

写简单的代码,是每个程序猴最为重要的事情之一。 本章提出了几点建议:

组合方法

同一个方法中,它们的细节应该保持一致。这样将更容易理解。 把方法分解成命名良好的、处在细节的同一层面上的行为模块,以此来简化方法。 上层调用将不再关心细微的处理。而是业务逻辑。 例如:

def calc(type):
    if type==0:
        # 一大段非常多细节的代码
        pass
    dosth()  # 对细节的封装

# 重构后
def calc(type):
    if type==0:
        dosth1()
    else:
        dosth2()

使用strategy替换条件逻辑

把算法的每个变体搬移到新类或子类通常是更好的选择。这实际上就是对象组合和继承之间的选择。

讲白了。就是抽象出算法的部分,建立新的类。然后将它组合进原来的类中。

值得注意的是。switch case通常不能被简单的消除,而只是换了一种形式。比如以下示例:

def capital(type):
    if type==1:
        pass
    if type==2:
        pass
    ...
    return result
# 重构后
loan = new loan()
loan.inner_capital = new Type1Capital()
loan.capital()  # 这里消除了type。因为依赖type的选择分支被拆分到了不同的Capital类中

但是,如何根据实际选择组合Type1Capital,还是Type2Capital 呢?恐怕,除了反射也没有很好的办法消除这一层逻辑了。

将装饰功能搬移到Decorator

如果只是需要对原有的类进行边角功能的扩充,则可以考虑使用装饰器。 但是:

如果需要搬移装饰功能的类包含许多的公共方法,那么Decorator模式不应该是重构的选择。

因为装饰器应该是透明的。即,被包装的对象不应该感知到它被包装。 在理想情况下,装饰器也不应该互相影响。否则,它们之间就会有顺序的依赖问题。 示例: 对一个Html的node在tostring的时候是否应该解码

class StringNode():
    def __init__(self):
        self.should_decode=False

    def get_str(self):
        ...
        if self.should_decode:
            return decode(result)
        return result

重构为:
# 将decode(result)的逻辑抽离出StringNode类
string_node = new StringNode()
decode_node = new DecodeNode(string_node)
decode_node.get_str()

用state替换状态改变条件语句

把状态改变条件逻辑从类中去除,并搬移到表示不同状态的一系列类中,可以产生更简单的设计。

如果把所有状态的迁移都放在一个地方处理(不使用状态模式)则很可能该方法的责任过大。方法体也会很长。 状态模式实质上,是把在一个类中不断的state变换,分解成一个个子状态。子状态类中,只关心状态的迁移。也就是上下文。

示例:

class Task(object):
    def __init__(self):
        self.state = 'nostart'

    def run(self):
        if self.state=='nostart':
            self.state = 'doing'
        elif self.state == 'doing':
            if self.check():
                self.state = 'done'
            else:
                self.state = 'undone'
        self.update()

    def check(self):
        # ...
        return True

    def update(self):
        # ...
        pass

task = Task()
print(task.state)
task.run()
print(task.state)
task.run()
print(task.state)

在这个例子中,所有状态的转化都依赖于主类的run。且,check操作只有在state==doing的时候才用的上。此时,可以进行重构。 重构后:

class Task(object):
    def __init__(self):
        self.state = NoStart()

    def run(self):
        self.state.run(self)
        self.update()

    def set_state(self, state):
        self.state = state

    def update(self):
        pass


class State(object):
    def run(self, task):
        pass

    def get_str(self):
        pass


class NoStart(State):
    def run(self, task):
        new_state = Doing()
        task.set_state(new_state)

    def get_str(self):
        return 'nostart'


class Doing(State):
    def run(self, task):
        if self.check():
            task.set_state(Done())
        else:
            task.set_state(UnDone())

    def get_str(self):
        return 'doing'

    def check(self):
        # ...
        return True


class Done(State):
    def run(self, task):
        pass

    def get_str(self):
        return 'done'


class UnDone(State):
    def run(self, task):
        pass

    def get_str(self):
        return 'undone'


task = Task()
print(task.state.get_str())
task.run()
print(task.state.get_str())
task.run()
print(task.state.get_str())

此时,在主task中,run被抽象为执行当前的state的run。这样做的好处在于: 1. 流程的控制下移到了state。此时在state中,只需要关系当前状态下的转移。而不需要再次对当前状态进行判断。if self.state=='nostart':这样的句子被移除。 2. 不通用的check函数从主类移除。

用Composite替换隐含树

这个重构其实很常见,即,将隐含的树形结构用组合模式来表示。 实际上,系统提供的xml包就是一个很不错的例子。

用Command替换条件调度程序

command模式,实质上是将执行的一行行命令原子化和抽象化。 比如:

if xxx:
    # dosth1
elif xxx:
    # dosth2
重构为
if xxx:
    task = Dosth1()
    task.exec(args)
elif xxx:
    task = Dosth2()
    task.exec(args)

将子任务抽象为相同的exec接口,会使得系统更为明晰。虽然上面的重构没有包含command_list。但是仍然是一种不错的思路。 当走出这一步,就会有意想不到的收获。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-03-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 组合方法
  • 使用strategy替换条件逻辑
  • 将装饰功能搬移到Decorator
  • 用state替换状态改变条件语句
  • 用Composite替换隐含树
  • 用Command替换条件调度程序
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档