您正在寻找的大多数(所有?)框架都解决了相同的问题,但是它们以略有不同的方式实现了不同的目标。
我认为可以说所有这些项目都可以解决以下类别的问题:
- 提供合理的默认设置
- 减少样板代码
- 在BackboneJS构建块的顶部提供应用程序结构
- 提取作者在其应用中使用的模式
我从2011年12月开始建立的“木偶戏”还牢记一些非常不同的目标和理想:
- 复合应用架构
- 企业消息传递模式的影响
- 模块化选项
- 增量使用(无全有)
- 没有服务器锁定
- 轻松更改这些默认值
- 代码作为配置/超配置
我并不是说其他框架都没有这些相同的目标。但我认为,木偶戏的独特之处在于这些目标的结合。
复合应用架构
我花了5年多的时间使用WinForms和C#在胖客户端,分布式软件系统中工作。我为台式机,笔记本电脑(智能客户端),移动设备和Web应用程序构建了应用程序,这些应用程序共享一个核心功能集并与同一服务器后端多次协作。在这段时间里,我了解了模块化的价值,并迅速地走下了复合应用程序设计的道路。
基本思想是“组合”您的应用程序的运行时经验,并从许多彼此不必了解的较小的单独部分中进行处理。他们在整个复合应用程序系统中注册自己,然后通过各种分离的消息和调用方式进行通信。
我在博客上写了一些有关此的内容,介绍了Marionette作为Backbone的复合应用程序体系结构:
消息队列/模式
相同的大型分布式系统还利用消息队列,企业集成模式(消息模式)和服务总线来处理消息。最重要的是,这对我解耦软件开发的方法产生了巨大影响。从这个角度,我开始看到单进程的内存中WinForms应用程序,不久,我的服务器端和Web应用程序开发就受到了影响。
这直接转化为我对Backbone应用程序设计的看法。我在Marionette中为高级Application对象以及您在应用程序中创建的每个模块提供了一个事件聚合器。
我考虑可以在模块之间发送的消息:命令消息,事件消息等。我还将服务器端通信视为具有这些相同模式的消息。有些模式已经进入了木偶戏,但还没有。
模块化
代码的模块化非常重要。对于任何规模和复杂性非常高的系统,必须创建具有单个焦点,定义明确的入口和出口点的小型,封装良好的软件包。
Marionette直接通过其module
定义提供模块化。但是我也认识到有些人喜欢RequireJS并希望使用它。因此,我同时提供了标准版本和RequireJS兼容版本。
MyApp = new Backbone.Marionette.Application();
MyApp.module("MyModule", function(MyModule, MyApp, Backbone, Marionette, $, _){
// your module code goes here
});
(尚无与此相关的博客文章)
增量使用
这是我对木偶的每个部分都可以接受的核心哲学之一:对使用木偶没有“全有或全无”的要求。
骨干本身采用非常增量的模块化方法来处理所有的构建块对象。您可以自由选择何时使用。我坚信这一原则,并努力确保木偶的工作方式相同。
为此,我在Marionette中内置的大多数组件都是独立运行的,可以与Backbone的核心组件协同工作,甚至可以更好地协作。
例如,几乎每个Backbone应用程序都需要在屏幕上的特定位置动态显示Backbone视图。应用程序还需要处理关闭旧视图并在放置新视图时清理内存。这是木偶Region
戏的出现地。区域处理获取视图,调用其上的render并将结果填充到DOM中的样板代码。然后,将关闭该视图并为您清理它,前提是您的视图上具有“关闭”方法。
MyApp.addRegions({
someRegion: "#some-div"
});
MyApp.someRegion.show(new MyView());
但是您不需要使用木偶的视图来使用区域。唯一的要求是您要在对象原型链中的某个时刻从Backbone.View扩展。如果选择提供一个close
方法,一个onShow
方法,或其他木偶的地区将在适当的时候打电话给你。
没有服务器锁定
我在多种服务器技术之上构建Backbone / Marionette应用程序:
- ASP.NET MVC
- Ruby on Rails
- 红宝石/西纳特拉
- NodeJS / ExpressJS
- PHP /苗条
- 爪哇
- Erlang
- ... 和更多
当在浏览器中运行时,JavaScript是JavaScript。服务器端JavaScript也很棒,但是对于我编写基于浏览器的JavaScript的方式,其影响为零。
由于我构建的项目和客户使用的后端技术的多样性,因此我不能也不会将Marionette出于任何原因锁定在单个服务器端技术堆栈中。我不会提供样板项目。我不会提供红宝石宝石或npm包装。我想让人们理解,木偶不需要特定的后端服务器。它是基于浏览器的JavaScript,后端无关紧要。
当然,我完全支持其他人为其语言和框架提供软件包。我在Wiki中列出了这些软件包,并希望人们继续根据需要构建更多的软件包。但这是社区的支持,而不是木偶的直接支持。
轻松更改默认值
为了减少样板代码并提供合理的默认值(这是我直接从Tim Branyen的LayoutManager中“借用”的想法),我认识到其他开发人员需要使用与我略有不同的实现。
我<script>
默认使用Underscore.js模板为模板提供基于内联标签的渲染。但是您可以通过更改“ 木偶”中的Renderer
和/或TempalteCache
对象来代替它。这两个对象提供了渲染功能的核心,并且有Wiki页面显示了如何针对特定的模板引擎和不同的加载模板方式对此进行更改。
使用Marionette v0.9,它变得更加容易。例如,如果要用预编译的模板替换内联模板脚本块的使用,则只需在Renderer上替换一种方法:
Backbone.Marionette.Renderer.render = function(template, data){
return template(data);
};
现在整个应用程序将使用您附加到视图template
属性的预编译模板。
我什至提供了带有v0.9的Marionette.Async插件,该插件使您能够支持异步呈现视图。我一直在努力使替换木偶中的默认行为尽可能容易。
代码配置
在某些情况下,我喜欢“约定之上的配置”。这是完成工作的有力方法,并且木偶提供了一点点-老实说,虽然不是太多。与Marionette相比,许多其他框架(尤其是LayoutManager)在配置方面提供了更多约定。
这是有目的和有目的的。
我已经构建了足够的JavaScript插件,框架,附加组件和应用程序,以了解尝试使约定以有意义且快速的方式工作的痛苦。可以快速完成此操作,但通常以更改它为代价。
为此,我对“木偶戏”采用“编码即配置”方法。我没有提供很多“配置” API,您可以在其中提供具有静态值的对象常量,这些静态值会改变一系列行为。相反,我通过注释的源代码和实际的API文档来记录每个对象所具有的方法,目的是告诉您如何更改Marionette使其以所需的方式工作。
通过为Marionette对象提供简洁明了的API,我创造了一种情况,替换特定对象或Marionette的行为总体上相对简单且非常灵活。我牺牲了“简单”配置API调用的灵活性,因为它提供了自己的代码以使事情按您希望的方式工作。
在木偶中找不到“配置”或“选项” API。但是您会发现大量的方法,每种方法都有非常特定的目的,带有清晰的签名,可以轻松更改木偶的工作方式。