重构代码中的分支(if-else)

子曾曰过:“没有代码洁癖的程序员不是好码工”。

if-else

在熟悉新部门的c++代码时,看到了类似下面的一些实现:

void test(const char *str) {
  if (0 == strncmp(str, "app1", sizeof("app1"))) {
    printf("%s\n", "app1");
  } else if (0 == strncmp(str, "app2", sizeof("app2"))) {
    printf("%s\n", "app2");
  } else {
    printf("%s\n", "default");
  }
}

先按下字符串硬编码的事情不表,其中使用 if-else 分支处理不同业务逻辑的方式触发了强烈的重构冲动,隐隐约约中感觉这里是 设计模式 的用武之地。

工厂模式

工厂模式使用编程语言的多态性来封装变化。

struct Base {
  virtual void print() const {
    printf("%s\n", "default");
  }
};

struct App1 : public Base {
  virtual void print() const {
    printf("%s\n", "app1");
  }
};

struct App2 : public Base {
  virtual void print() const {
    printf("%s\n", "app2");
  }
};

std::unordered_map<std::string, std::shared_ptr<Base>> apps = {
  {"app1", std::make_shared<App1>()},
  {"app2", std::make_shared<App2>()},
  {"default", std::make_shared<Base>()}
};

void test(const char *str) {
  std::string input(str);
  if (apps.find(input) != apps.end()) {
    apps[input]->print();
  } else {
    apps["default"]->print();
  }
}

总结

不要if else的编程中将分支(if/switch)的缺点阐述的比较清楚, 容易造成高耦合。编程时并不是拒绝使用分支判断,而是拒绝过度使用。跟业务相关的地方,往往意味着变化,使用分支去处理变化, 代码很容易就变得膨胀,可读性变差。“破窗理论”启示我们,这些“坏味道”的代码通常就会加剧代码的腐烂。

话外音

c++的特性太多,从掌握到用好有一定的门槛,即便在谷歌也不是使用所有的特性,而是有所取舍。但是特性多,用好难,绝不是用c++去写c语言的理由。

如果决定使用c++开发,很多特性是不能视而不见的,比如:namespace, stl, agorithm, class, template等等。 谷歌的c++编程规范绝对是业界的典范,基于这份规范的项目可读性都非常好, 像tensorflow,v8等谷歌开源项目和impala,kudu等cloudera开源项目。

参考

01 April 2016

blog comments powered by Disqus