ember.js是否鼓励过多的控制器?

时间:2012-07-24 18:37:56

标签: ember.js

我正在尝试了解构造ember.js应用程序的最佳实践。来自tomdale的这张幻灯片:

https://speakerdeck.com/u/tomdale/p/emberjs-more-than-meets-the-eye?slide=55

简要描述了如何分配应用程序逻辑。但是,在尝试遵循这些指导原则时,我发现了一些问题:

  1. 路由器变得太大了。根据演示文稿,路由器“响应来自视图的事件”,但是当有数十个视图时会产生大量代码。
  2. 有大量的控制器。在Rails应用程序中,CRUD操作通常驻留在同一个控制器中,但是对于ember应用程序,似乎应该有一个控制器来列出记录,一个用于查看记录,一个用于创建记录等。
  3. 它感觉不太干,因为我最终在控制器,视图和把手模板之间有这么多文件,每个模板只有几行代码。

    我正在尝试确定问题是我是否错误地应用了指南,或者这些指南是否仅适用于简单的应用程序。

    有没有人有任何建议 - 尤其是如何管理路由器的增长?

2 个答案:

答案 0 :(得分:19)

我认为说Ember鼓励太多控制器就像说Javascript鼓励太多功能。是的,你可以疯狂地扩散其中之一。或者你可以做相反的事情,让它完全按照你的需要工作。一般来说,永远记住你的应用程序应该完全像它需要的那样复杂,并且不再如此。你不需要使用某种架构或模式只是因为一些着名的编码人员使用它,甚至也不是因为它似乎是“琥珀”的方式。即使是“环球好事”也是如此。像分离关注,MVC等是原则&您应该尝试完全理解的模型,然后使用它们满足您的需求。我认为,出于正确理由选择性地打破规则和模式的能力,更能说明一个伟大的黑客的迹象,而不是对编程之神的教条的盲目奉献。这是一种手艺,而不是宗教。 (但是YMMV。也许那里有像我这样的编码器的特殊地狱圈。我打赌它。)

特定于Ember,我倾向于在我的数据模型周围和/或围绕特定用户工作流使用控制器,而不是围绕每个视图。然后使用路由/状态管理器作为视图之间的粘合剂,我通常在视图上使用事件管理器来处理每个视图中的浏览器事件,包括向路由器发送指令。所以,如果我有一个围绕客户和产品的应用程序,我会为每个应用程序配备一个控制器,就像我在Rails中做的那样。这将导致每个控制器保持比一些人喜欢在一个地方拥有的更多功能和计算属性。这也意味着我无法在另一个环境中重复使用我的视图,因为它们已经硬连接到控制器。是的,这是一个糟糕的关注点。但如果它导致没有收益的复杂性,这并不是绝对的好事。

同样关于控制器的主题,我认为人们特别倾向于不必要地为主数据模型的子集增加控制器。假设您有一个产品控制器,并且您希望将给定用户正在收集的产品存储在比较工具中。大多数人似乎为此创建了一个新的控制器,但将这些控制器推送到Products控制器或客户控制器或客户模型中的其他阵列或其他Enumerable中是完全合法的。这使得在更近的范围内依赖于相同功能和属性的对象。每个控制器中的content对象是AFAIK,只是另一个Enumerable。它有一些对Controller的特殊隐式引用,但并不神奇。没有功能原因我发现也没有使用其他功能。它们与#each等的绑定一样好用。

同样地,有些人只需要将他们的应用程序分解为一百万个文件,将它们嵌入到文件结构的深处,等等。如果这有助于您可视化底层逻辑,并使其明确你团队的其他成员。对我来说,这只会减慢我对只有1-3人工程团队的项目的影响。人们也倾向于重现他们熟悉的其他MVC系统的基于文件的风格(如Rails),其中文件是分离视图和其他逻辑对象的必要显式结构。这成为一种信仰和深深根深蒂固的习惯。但是在Javascript MVC中,我发现它通常没有这样的用途,并且对于隐式设计是严格多余的。我倾向于为我的整个Ember应用程序使用一个精心组织的文件(将其与任何其他非库JS分开),并使用大量缩进和嵌套来帮助我可视化层次结构。无论你做什么,文件方面,它在运行时都是一样的,前提是你在正确的时间将它们全部送到正确的地方。使用Ember和JS,文件结构可以满足您团队的需求,而不是其他任何内容。相应地进行校准。

(重要的CAVEAT:如果你使用了一百万个文件,你最好使用预编译器将它们全部一起显示给用户,或者你是'在单独提供所有这些文件时会产生巨大的延迟。)

(另一个重要的CAVEAT:对于一个大团队或rapid daily release schedule like GitHub's,基于文件的逻辑分离可以使版本控制比在同一个文件中进行大量合并更容易,在这个文件中你的合并工具可能会混淆同样,这是一个管理和监控人类流程,仔细进行合并的问题,而不是JS框架强加的技术要求。)

(最后重要的CAVEAT:然而,有时技术要求和人/程序要求之间的差异是模糊的。如果你打破了开发人员的大脑,你也往往会破坏应用程序。所以,做什么适用于你必须处理它的人和过程。)

正如我之前所说,YMMV。我不是一个编码器的上帝,你可以从我的声望分数中得知,所以你可以随意忽视我。但我支持这样的想法:你应该只使用尽可能多的复杂性,只使用尽可能多的文件结构,并且只使用尽可能多的更高级别的抽象(如路由,对于有限用途的单页应用程序实际上可能过度杀伤)作为服务您的需求;而且没有了。

答案 1 :(得分:8)

我认为我们正在开发一个非常大的余烬应用程序(目前大约有45个视图)。它意味着几乎相同的控制器和模板数量)。 事实上,我们的路由器非常庞大,但我们通过将其分成许多文件来轻松管理它。基本上,每个文件代表应用程序的一个屏幕,并负责维护功能集。以下是路由器的摘录:

Router = Ember.Router.extend({
  root: Ember.Route.extend({

  index: Ember.Route.extend({
    route: '/',

  unlogged: Ember.Route.extend({
    route: 'welcome',

    connectOutlets: function (router) {
      var applicationController = router.get('applicationController');
      applicationController.connectOutlet('welcome');
    }
  }),

  logged: Ember.Route.extend({
    route: 'app',

    projects: Ember.Route.extend({
      route: 'projects',

      collection: ProjectsRoute,
      member: ProjectRoute,

      showProjects: function (router) {
        router.transitionTo('projects.collection');
      }
    })
  })
})

然后在ProjectRoute中也一样。每次在一条路线中似乎有许多功能,我们将它拆分。 您甚至可以重新打开路径来扩展它,并在其中插入其他功能。

ProjectState.reopen({

  scenarios: ScenariosRoute,

  showScenarios: function (router) {
    router.transitionTo('scenarios.collection');
  }
});

它意味着更多的文件,但是组织良好,并不难维护,因为你很少同时处理所有功能。通常,我同时没有更多4个打开的文件(视图,控制器,模板,路径)

我不知道这是不是最佳做法,但它对我们来说非常好