灵活的配置设计

前面讨论了一种 cross domain 公用概念相关的 API 设计 pattern,这里提供另一个非 compile-time 的思路。我们之所以在前面希望每个 label 对应的实现是固定的,是因为很多时候他们的确是固定的,一旦实验成功,没有必要继续修改这些行为。

然而某些 domain 的问题的性质并非如此。不少建模领域,我们可以为同一个概念提供若干不同的表示:

  • dense representation 我们可能用一个 float vector 表示某类 sparse signal
  • sparse representation 我们可能直接使用字符串本身作为表示

但是不同的表示可能有一定的 tradeoff,我们往往希望能够根据不同的 case 进行实验,并有很大的可能两种选择都是 valid 甚至在不同的情况下作为分别的最优。这时,我们就不能使用之前的 pattern,另一种选择也很简单我们需要将标识和 action 两者作为一个整体来进行配置。通常 action 本身可以与标识无关,但是如果它需要标识本身的一些信息,我们可以将其 constructor 修改接受对应的 enum 并获得这些信息即可。这意味着我们最好提供一个 factory method 用于创建不同的 action 对象。

因此一个使用 protobuf 设计的典型的 pattern 如下

message GlobalScope {
  enum Foo {
    UNKNOWN = -1;
    LLAMA = 0;
    GOAT = 1;
  }
}

message SomeScope {
  message ProcessUnit {
    optional GlobalScope.Foo foo = 1;
    oneof kind {
      DenseOpConfig dense = 2;
      SparseOpConfig sparse = 3;
    }
  }

  repeated ProcessUnit unit = 1;
}

比如我们在 SomeScope 中需要某种处理过程,通过 ProcessUnit 将 enum 和 action 绑定后就可以

class SomeOp {
public:
  static std::unique_ptr<SomeOp> Create(const SomeScope::ProcessUnit& config);

  // Domain specific API
  virtual void DoSomething() = 0;

  virtual ~SomeOp() {}
};

class DenseOp : public SomeOp {
public:
  DenseOp(GlobalScope::Foo foo, const DenseOpConfig& config);

  void DoSomething() override;
};

这样一来实现的时候可以写类似下面的代码

static std::unique_ptr<SomeOp> SomeOp::Create(const SomeScope::ProcessUnit& config) {
  auto kind = config.kind_case();
  switch (kind) {
  case SomeScope::ProcessUnit::kDense:
    return std::make_unique<DenseOp>(config.foo(), config.dense());
  case SomeScope::ProcessUnit::kDense:
    return std::make_unique<SparseOp>(config.sparse());
  default:
    // fail
  }
}

这种方式很容易能够获得最灵活的配置方式,只是每一个 enum value 都需要与 action 显式的绑定。

Advertisements
灵活的配置设计

发表评论

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