10.9 总结
我们介绍了shelve模块的基本用法,包括创建shelf并用存放在shelf上的对象设计键。我们也介绍了访问层需要在shelf上执行低层的CRUD操作。这样做的主要目的是我们需要分离为我们的应用程序本身服务的类和其他用于持久化的类。
10.9.1 设计要素和折中方案
shelve模块的优势之一是允许我们保存不同的元素。这为确定合适的元素粒度的设计增加了负担。过于细的粒度会浪费时间将它们从碎片组装起来。过于粗的粒度会浪费我们的时间去获取和保存不相关的元素。
由于shelf需要键,因此必须为对象设计合适的键,也必须管理不同对象的键。这意味着使用额外的属性保存键以及可能需要为shelf上的元素创建额外的键集合作为索引。
用来访问shelve数据库上元素的键就像weakref,它是一个间接引用。这意味着需要额外处理基于引用追踪和访问元素。关于weakref的更多信息,参见第2章“与Python无缝集成——基本特殊方法”。
设计键的一种方式是选择不会被改变并且适合作为主键的一个属性或者一些属性的组合。另外一种方式是生成不可以改变的代理键,这种方式让其他所有属性仍然可以被改变。由于shelve依赖于pickle表示shelf上的元素,所以我们有一种高性能的方式表示Python对象。这降低了保存在shelf上的类设计的复杂度。任何Python对象都可以被保存在shelf上。
10.9.2 应用软件层
由于使用shelve时程序会变得相对复杂,因此我们的软件必须更合理地分层。通常,我们将软件架构分为下面几个层次。
- 表示层(Presentation layer):顶层用户界面,可能是一个Web引用或者是一个桌面GUI程序。
- 应用层(Application layer):让应用程序得以正常工作的内部服务或者控制器。这层也可以被称为处理模型,与逻辑数据模型不同。
- 业务逻辑层或者问题域模型层(Business layer or problem domain model layer):定义了业务领域或者问题域的对象,这层有时候被称为逻辑数据模型。我们通过Blog和Post的博客例子介绍了应该如何定义这些对象。
- 基础架构(Infrastructure):它通常还包括一些其他层和一些其他的横切关注点(cross-cutting concerns),例如日志、安装和网络访问。
- 数据访问层(Data access layer):这层包含了用来访问数据对象的协议或者方法。我们介绍了如何设计用于访问shelve数据库的对象。
- 持久化层(Persistence layer):这是文件存储系统中的物理数据模型。shelve模块实现了持久化。
当我们进入第11章“用SQLite保存和获取对象”时,会更清楚如果想要掌握面向对象编程则必须掌握一些设计模式。我们不能简单地设计独立的类,相反地,我们需要关注类是如何被组织为更大的结构的。最后,也是最重要的,穷举搜索是一个可怕的东西,我们必须避免使用它。
10.9.3 展望
下一章和本章类似,我们会介绍如何用SQLite而不是shelve来持久化我们的对象。复杂的地方是SQL数据库没有直接支持保存复杂Python对象,这就带来了阻抗失配问题(impedance mismatch problem)。我们会介绍两种用诸如SQLite的关系型数据库解决这个问题的方法。
第12章“传输和共享对象”会将注意力从简单的持久化转到传输和共享对象上。这会基于我们在本章所介绍的持久化技术,同时会加入网络协议。
