1

假设如下:

  /**
 * the importer trait that glues extractor , transformator and loader together
 * (mini etl)
 */
trait Importer[A, B, C] {

  //this makes sure that the importer 
  //implements an extractor, a transformator and a loader (selfytping)

  self: Extractor[A, B] with Transformator[B, C] with Loader[C] =>

  /**
   * this is the method call for chaining all events together
   */
  def importAndTransformData(dataSource: A): Unit =
    {

      /**
       * perform initializations if necessary
       */
      initializeExtractor
      /**
       * extraction step
       */
      val output = extract(dataSource: A)

      /**
       * before the loading takes place we initialize the Loader if required
       */
      initializeLoader
      /**
       * conversion method that gets injected the load method
       */
      val transformed = transform(output, load)

      /**
       * perform actions afterwards if required
       */
      cleanupExtractor

      cleanupLoader

    }

初始化方法目前有一个虚拟实现什么都不做。如果需要,由具体的特征/子类来覆盖它。这似乎有点笨拙。

有更好的方法吗?

4

1 回答 1

0

一个班级应该只做一件事,一个人做一件事:

  • 提取器应该知道如何提取而不是别的
  • 变形金刚应该知道如何变形而不是别的
  • 加载器应该知道如何加载而不是别的
  • 一个 Importer 应该知道如何导入,给定一个 Extractor、Transformer 和 Loader

也就是说,Importer 绝对不应该实现所有的 ETL 方法。它应该接收或创建 ETL 对象并适当地使用它们。

我会让 ETL 组件成为独立的单元。他们应该知道如何照顾自己:在构建时进行初始化,并在超出范围时进行清理。

我在 Java + Spring 的依赖注入中做过这种事情。My Importer 是真正的胶水代码,只需将它接收到的由 Spring 配置的 ETL 组件组合在一行代码中。

如果您根据只做一件事的原则重新考虑您的设计,您的问题可能会自然而然地消失。由于您使用的是 Scala,因此请尽量避免突变,因为这自然会驱使您使用更清洁的界面。(我提到这一点是因为您的 initialize* 方法听起来像是会修改状态。)

于 2013-11-14T21:35:16.253 回答