很粗,错漏也一定很多,自己也处于理解阶段,有不足还望大家指正。
Architecture
During development of Gears, we experimented with many different architectures for offline-enabled web applications. In this document we briefly look at some of them and explore their advantages and disadvantages.
As we experimented, we found some common themes. All the offline-enabled applications we created had the following design issues that needed to be addressed:
isolating the data layer
deciding which features to implement offline (connection strategy)
deciding on the app’s modality
implementing data synchronization
架构:
在开发Gears的过程中,我们尝试了不同的离线WEB应用程序的架构。在尝试的过程中,我们发现一些通用原则。我们创建的所有离线程序具有下面的设计目标需要达到:
1-独立的数据层
2-判定哪些功能需要实现离线功能(联线策略)
3-决定应用的形式
4-实现数据的同步
Isolating the Data Layer
In most web applications today there is no real data layer.
独立的数据层:
在目前的大多数WEB应用中没有真正的数据层

AJAX calls originate throughout the code, without any single clean communication layer. This is usually fine for AJAX applications because there is only one data source: the server. In effect, the API that the server exposes to AJAX acts as a data layer.
在代码中贯穿了ajax调用,没有任何单一干净的通信层。这对于ajax应用一般是可以接受的,因为仅仅有一个数据源:服务器。实际上,服务器响应Ajax行为的API扮演着一个数据层的角色。
Architecture with a data layer
In general, isolating the data layer is a good first step.
When you add a local datastore to your application, you will have a single place through which all data storage and retrieval requests pass.
一个数据层架构
一般来说,独立的数据层是一个好的开始。
当你添加一个本地数据到你的应用的话,你就拥有了一个唯一的地方,所有的数据可以存储在这里,获取数据也直接从这里获取。

For example, if your AJAX application issues a JSON request directly to the server to get all the accounts for a user, you might change this to instead ask an intermediate object for all the accounts for the user. This object could then decide whether to retrieve the data from the server, the local store, or some combination of both. Similarly, when the application wants to update the user’s accounts, the app does so by calling the intermediate object. The intermediate object can then decide whether to write the data locally, whether to send the data to the server, and it can schedule synchronization.
例如:如果你的ajax应用发起一个json请求到服务器获取一个用户的所有账号,更好的方式是请求一个中间对象来获取用户的所有账号。这个对象来决定是否从服务器、本地存储或者一些其他组合来获取数据。类似的,当应用程序需要更新用户账号的时候,应用程序只需要调用中间对象。中间对象来决定是否将这些数据写入本地存储,是否发送数据到服务器,同时它(中间对象)还可以定制同步计划。
You can think of this intermediate object as a data switch layer that implements the same interface as the data layer. As a first step, you can make the data switch forward all your calls to the data layer that interacts with the server. This step is useful since it is the code path that is followed when Gears is not installed or if the user doesn’t want to enable the application to work offline. Note that a data switch is not strictly necessary (for example GearPad does not have a data switch layer).
你可以认为这个中间对象是一个数据交换层,该数据交换层实现了数据层一样的接口。作为第一步,你可以让使这个数据交换层透明的传递你的调用到数据层(直接和服务器交互的数据层)。这一步是很有用的代码路径当Gear没有安装或者用户不想让应用程序离线处理时。注意:数据交换层不是严格的需要的(例如GearPad没有这样的一个数据交换层)

The next step, as shown in the figure below, is to create a new local data layer that uses a Gears database instead of going to the web server for data. It’s simpler if this data layer has the same interface as the existing data layer used to communicate with the server. If the interface is different then some translation needs to be done and you might as well do that inside this data layer.
To test this step, you can set the data switch layer to talk to this new (local) data layer. You might want to pre-populate the database to make things easier to test.
下一步,如下图所示,创建可一个新的使用Gears数据库的本地数据层取代从WEB服务器获取数据。如果该数据层拥有和当前数据层一样的接口来和服务器通讯的话是非常简单的了。如果接口有一些不同,比如有一些转换需要做,你应该在该本地数据层中进行处理。
为了测试这一步,你可以设置数据交换层于该本地数据层通信。不过之前最好建立一个数据库以使得测试更容易一些。

Architecture without a data layer
If the application is not structured with a data layer and adding a data layer is not an option, it is still possible to isolate the data layer by intercepting all the calls to the web server just before they are sent. For example, you could intercept a form submit (listen to the submit event) and decide if the application should use the local data store or the data on the server.
Implementing this approach involves finding all functions and methods that send requests to the server, and rerouting them. The challenge is that this method requires a lot of extra work, like parsing URLs, iterating over forms as well as generating the same result as the server would. In practice you end up reimplementing large parts of the web server on the client side. Regardless, this can be a viable option for existing AJAX applications that can’t be otherwise rearchitected.
没有数据层的架构
如果应用没有设计数据层或者添加一个数据层是不可行的话,仍然可能通过于服务器交互来构造出一个数据层出来,仅仅需要在所有的请求发送之前做一点事情。例如,你可能发起一个表单提交(监听submit事件)并且决定应用程序应该使用本地存储或者服务器上的数据。
实现这种方式需要找到所有发送请求到服务器的函数和方法,然后重新路由它们。挑战是,这样需要做很多额外的工作,例如解析URL地址,像服务器返回结果一样的重新生成表单。实际上你需要在客户端重复实现你在服务器端所做的大部分工作。不管怎样,对于已有的不能重新设计架构的ajax应用来说,这样的方式是可选的。
Feature Availability Offline
For practical reasons, every feature of an application may not become a feature that’s available offline. You need to choose which features you want to support locally and implement the logic that decides when to use the local store and when to connect to the server. We call this the “connection strategy.”
离线功能
由于一些实际原因,不可能一个应用的所有功能都实现离线处理。你需要选择一些功能你想支持本地处理并且实现其中的逻辑来决定何时使用本地存储,何时连接到服务器。我们称之为“联线策略”。
You might think that you would always want to use the local store since it is faster. However, there are many practical reasons why you may want or need to access the data on server instead. For instance:
Data may be so transient in nature that it makes no sense to cache it.
你也许认为你需要经常使用本地存储,因为这样很快。但是,有很多实际原因,你需要或者必须访问服务器端的数据。例如:
数据可能存在的时间很短暂,没有必要缓存住它。
For example, an application providing real-time stock quotes would not benefit from serving old stock quotes.
Some application’s data makes sense only while online.
As an extreme example, an Instant Messaging application makes sense only while connected.
例如:一个提供实时股票信息的应用存储过时的股票信息是没有价值的。一些应用的数据只有在在线的时候才是有意义的。另外一个例子就是实时IM应用,这个就不多说了。
The app may choose to store only the most frequently accessed data.
For example, if the user can set a preference that changes the language of the application, this preference change might not be supported offline because the cost of implementing this offline feature is not worth the benefit for a preference that is seldom changed.
应用应该选择只存储一些经常访问到的数据。例如,如果用户可以设置一个应用的语言,这些语言的数据最好不要实现离线功能,因为这样的功能是很少使用的,实现这样的功能代价有点大。
Computational and/or disk space requirements make it unfeasible to recreate the feature offline.
For example, if the feature requires huge amounts of data to be useful, beyond a reasonable amount for a personal computer.
计算和/或磁盘空间需求使得该离线功能不太可以被接受。
例如,如果功能需要使用大量的数据,超出一台PC可以接受的数量。
Typically, the optimal solution is to use the local store as much as possible, since it’s usually faster than a remote connection. However, the more work an application does locally, the more code you need to write to implement the feature locally and to synchronize the corresponding data. There is a cost/benefit tradeoff to consider, and some features may not be worthwhile to support locally.
典型的,可选的解决方案就是尽可能的本地存储,因为它一定比远程连接要快地多。但是,一个应用所做的本地工作越多,你需要编写的实现该功能的本地化和同步数据的代码就越多。有一个性价比需要考虑进来,并且一个功能可以没有必要实现本地化。
Modality
One fundamental question that all offline-enabled applications must answer early is that of “modality”.
Modal applications have distinct offline versus online modes, usually indicated through some change in the user interface. The user is made aware of the state and participates in switching states in some manner.
Modeless applications attempt to transition seamlessly between online and offline states, without significant UI changes. The user does not need to participate in switching states, which the application does automatically.
模态化
一个基本的问题所有的可离线应用必须尽早回答是“形态”。
模态的应用程序具有不同的离线相对与联线模式,这个通常是指一些用户界面上的变化。用户应该意识到状态和体验到在不同的方式之间切换。
Modal
In a modal application, when the application is online it communicates with the server. When it’s offline, it uses the local store. Data must be synchronized when the app switches between modes.
The advantage of making a modal application is that it’s relatively simple to implement and therefore a reasonable way to bootstrap the application to function offline.
The disadvantages are:
The user must remember to switch modes. If they forget, they will either not have the data they need when offline, or will work online in an unintentionally disconnected mode.
If the network connection is intermittent, the user will either need to choose one of the settings or will have to constantly switch between modes as the connection comes and goes.
Since the local store is not always up-to-date, it can’t be used to improve the application’s responsiveness when connected to the server.
模态
在一个模态应用中,在线时应用与服务器交互,离线时,就使用本地存储。当应用在两种模式之间切换时,数据必须被同步。
制作一个模态化的应用的优点是,它的实现相对还是比较简单的因此是一个合理的方式来引导应用在离线状态下的使用。
缺点是:用户需要记得去切换模式。如果他们忘记了,他们可能既得不到离线时的数据,或者也可能联线时确处在离线时的模式。
如果网络时断时续,用户需要选择一个设置或者不得不在频繁的连接和断开之间转折。
因为本地存储不一定一直是最新的,这样就不能在连接到服务器时改善应用的响应。
Modeless
In a modeless application, the application works with an assumption that it is offline, or that it can lose the network connection at any time. The app uses the local store as much as possible, and does continuous, small data syncs in the background when the server is available. Data synchronization is also done when coming back online.
The advantages of modeless applications are:
A better user experience. The user does not have to be aware of network connectivity or switching states.
The application works smoothly even with intermittent network connections.
Since the local store is kept up-to-date, it can be used to optimize the server connection.
The disadvantages of modeless applications are:
It is more difficult to implement.
Care must be taken to avoid letting the synchronization background process consume too many resources and make the overall application feel sluggish.
Testing the app can be more challenging, since synchronization logic occurs in the background and not in reaction to specific user actions.
The sample application Gearpad is an example of a modeless offline application. It always writes to the local database, and then independently synchronizes the changes with the server.
Google Reader is currently an example of a modal application. It has a distinct offline mode that a user must explicitly enable. In Reader’s case, implementing a modal state was a pragmatic choice, as it was faster to implement and made it possible to release an early version of Google Reader with Gears.
去模态化
在一个没有模态的应用中,应用程序假定运行在离线状态,或者可能随时断开网络连接。应用尽可能的使用本地存储,并且在后台,当服务器可用时持续地进行着小数据量的同步。当再次联机时,数据同步已经完成。
去模态化的优点是:
更好的用户体验。用户不需要仪式到网络连接的状态或者切换状态。
应用在网络断断续续时也可以运行的很平滑。
本地存储一直保持最新,这样就优化了服务器连接。
缺点是:
实现起来比较复杂和困难。
需要注意避免后台同步进程占用太多的资源和使应用运行不顺畅。
测试应用可能更加有挑战性,因为同步本地发生在后台和用户的行为没有一定的影响。
示例程序GearPad是一个去模态化的应用示例。它经常将数据存储在本地数据库,然后独立地同步数据到服务器。
GoogleReader目前是一个模态化的应用示例。它有一个独特的离线状态用户必须明确的允许。从Reader的角度来看,模态化状态是一个实际的选择,因为实现一个可以用的带Gears的Google Reader早期版本是比较快的。
Data Synchronization
No matter which connection and modality strategy you use, the data in the local database will get out of sync with the server data. For example, local data and server data get out of sync when:
The user makes changes while offline
Data is shared and can be changed by external parties
Data comes from an external source, such as a feed
Resolving these differences so that the two stores are the same is called “synchronization”. There are many approaches to synchronization and none are perfect for all situations. The solution you ultimately choose will likely be highly customized to your particular application.
Below are some general synchronization strategies.
数据同步
不管你使用什么样的连接和模态策略,在本地数据库中的数据都会与服务器数据失去同步。例如,下面情况下本地数据和服务器数据会不同步:
1-用户在离线状态下进行了一些改变
2-数据被分享有可能被外部合作者修改
3-数据来自一个外部资源,例如一个feed
解决这些差异,让两个数据仓库里存储的数据一致就叫“同步”。有许多同步方法,没有放之四海皆准的方法。你最终选择的解决方案应该适合你自己的特定应用。下面是一些一般同步策略。
Manual Sync
The simplest solution to synchronization is what we call “manual sync”. It’s manual because the user decides when to synchronize. It can be implemented simply by uploading all the old local data to the server, and then downloading a fresh copy from the server before going offline.
Manual sync requires that:
The amount of data is small enough to download in a reasonable amount of time.
The user explicitly indicates when he or she is going offline, typically via a button in the user interface.
The problems with this method and with the offline mode it creates, are:
Users don’t always know the state of their network connections. Internet connections may die unexpectedly or be intermittent, for example, on a bus.
Users may forget to synchronize before going offline.
Manual sync can be a good way to get started as it is relatively easy to implement. However, it requires the user to have awareness and involvement in the synching process.
手动同步
最简单的同步解决方案我们称之为“手动同步”。之所以称之为手动是因为由用户来决定何时同步。通过上传所有老数据到服务器,然后下载所有最新拷贝到本地来简单的实现它。
手动同步需要:
数据量应该比较小可以在一个合理的实现内下载完。
用户明确指示他/她什么时候离线,典型的化通过界面上的一个按钮。
这种方式以及它所创建的离线模式引起的问题是:
用户可能忘记在离线前同步数据。
手动同步可以是一个好的开始方式因为它比较容易实现。但是它需要用户有意识的介入到同步流程中来。
Background Sync
In a “background sync”, the application continuously synchronizes the data between the local data store and the server. This can be implemented by pinging the server every once in a while or better yet, letting the server push or stream data to the client (this is called Comet in the Ajax lingo).
The benefits of background synching are:
Data is ready at all times, whenever the user chooses to go offline, or is accidentally disconnected.
The performance is enhanced when using a slow Internet connection.
The downside is that the sync engine might consume resources or slow down the online experience with its background processing (if it’s not using the WorkerPool). Using WorkerPool the cost of synching is minimized and no longer affects the user’s experience.
后台同步
在后台同步中,应用程序持续不断的在本地存储和服务器之间同步数据。可以通过下面方式实现,每隔一小段时间ping服务器让服务器推送流数据到客户端(在ajax中被称之为Comet)
这种同步方式的优点是:
所有时间数据都是准备好可以使用的,无论是用户选择离线还是突然断开连接。当网速很慢的时候可以最大程度增强程序性能。下载的一方,同步引擎可能消耗资源或者降低在线体验度因为它的后台进程(如果没有使用WorkerPool)。使用WorkerPool的话,同步的花费是最小化的并且不会影响用户体验。

Conclusion
There are many design choices to be made along the way to enabling an application to work offline. This document reviewed a few of the possible choices for the common design issues that arise. The decisions made for an application will need to reflect the user experience you want to achieve as well as the application’s limitations and goals.
概述
有许多设计可以用来选择来实现应用程序的离线功能。本文档回顾了一少部分可选的方案对于现存的一般设计。一个应用程序的架构需要反映你想达到的用户体验以及应用的局限性和应用所要达到的目标。