跨 domain 的 API 问题(上)

很多时候写某个复杂的过程,数据从一个 domain 转换到另一个 domain,每个 domain 里面都有一些与某几个公共概念相关的代码,我们通常需要反复的处理这类问题,有没有什么办法能够减少这类问题的 boilerplate 呢?

下面以一个 learning/inference 中常处理的 label 的 API 设计作为例子。我们知道通常很多不同性质的 label 可能会导致很多 domain 里面的行为差异:

  • 类型转换:每个 label 在某个 domain 中的表示可能很不一样,对应的转换代码需要根据 label 区分
  • calibration:两类分类、多类分类、regression 如果都需要根据某些 benchmark 进行校准的话,采用的算法也会有所差别
  • 等等

虚函数

如果我们能为这一族类型关联上一族继承同一父类并拥有一个 reflection 的 factory method,一个简单的想法就是我们通过类型名(string)找到对应的一个实现类,调用对应的 virtual method。这样不同 domain 里面我们可以或者实现多个一样的结构,或者在公用的类里面加入更多的 virtual method。

class label {
public:
  virtual ~label() {}

  static const label& get(const std::string& l);

  // domain A
  virtual void transfrom(const domain_a_input& in, domain_a_output& output) const = 0;

  // domain B
  virtual void write(const domain_b_input& in, domain_b_output& output) = 0;
};

class gender {
public:
  void transfrom(const domain_a_input& in, domain_a_output& output) const override {
    // implementation
  }

  void write(const domain_b_input& in, domain_b_output& output) const {
    // implementation
  }
};

这样一来,我们可以

// domain A code
void do_something(const string& l, const domain_a_input& in, domain_a_output& output) {
  label::get(l).transform(in, output);
}

// domain B code
void do_something(const string& l, const domain_b_input& in, domain_b_output& output) {
  label::get(l).write(in, output);
}

这样的做法有一点奇怪,这个 label 类的 virtual function 随着 domain 的增长而变得复杂,如果某些 domain 仅仅对某几个类型的 label 有效,我们仍然不得不为他们提供实现(default to fail),这些类因为 cross domain 而需要链接更多的 library 最后 build 可能变得非常的缓慢。很显然寻找到类本身就足够决定调用的函数了,但是我们还是得使用 virtual function 来保证这些对象是属于一个类型的。

Advertisements
跨 domain 的 API 问题(上)

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s