假设如下:
/**
* 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
}
启动方法目前有一个无效的虚拟实现。 如果需要,由具体的特征/子类覆盖它。 这似乎有点笨拙。
有更好的方法吗?
答案 0 :(得分:0)
一堂课应该只做一件事而且只做一件事:
也就是说,进口商绝对不应该实施所有的E-T-L方法。它应该接收或创建E-T-L对象并适当地使用它们。
我会让E-T-L组件成为独立的单元。他们应该知道如何照顾自己:在构建时初始化,在超出范围时进行清理。
我在使用Spring的Java +依赖注入中做过这种事情。我的导入器是真正的胶水代码,只需将Spring收到的E-T-L组件组合在一行代码中。
如果您根据“只做一件事”原则重新考虑您的设计,您的问题可能会自然消失。因为你正在使用Scala,所以尽量避免突变,因为这会自然地驱使你走向更清晰的界面。 (我之所以提到这一点,是因为你的initialize *方法听起来像修改状态。)