【IT168 技术】应用程序架构描述组成应用程序的主要部分。例如,在Java世界里,应用程序架构都描述两个内容:用于构建特定应用程序的框架组合 — 我称其为框架级架构 — 以及更多传统的逻辑关注点分离,我一直称这些内容为应用程序架构。将框架架构作为一个独立部分,因为大多数面向对象语言的从业者已经发现单独的类不能实现良好的重用(您最后一次从 Internet 中下载一个单独的类以供某个项目使用是什么时候?)。目前面向对象语言中的重用部分都是库或框架。

当您用提供丰富框架的语言(如 Java 语言)启动一个新项目时,首要的架构关注点之一就是应用程序的框架级架构。这种重用设计在 Java 世界中获得了巨大成功,以至于我已经开始认为我们应当停止把 Java 编程称为面向对象的语言,而应当称其为面向框架的语言。在许多方面,框架级架构代表特定构建块所描述的物理架构。

  应用程序架构的另一个有趣的方面描述应用程序的逻辑部分如何整合在一起。这属于设计模式和其他结构描述的领域,并且因而趋向于更具抽象性和逻辑性,而非物理性。例如,您可以说 Web 应用程序遵循模型-视图-表示器(Model-View-Presenter)模式,而无需详细说明您使用哪个框架实现逻辑安排。这种逻辑安排是在开始处理应用程序的新组件时,最有可能增添到工作空间白板(whiteboard)中的内容之一。

企业架构(企业级架构)

  企业级的架构是指,考虑到以上的功能所开发的架构,如程序在物理上、逻辑上的分布式、跨平台、多系统的数据集成功能、多系统的整合功能、和一定的可扩展性和可维护性等。

  企业架构关注如何使企业作为一个整体(通常意味着在大型组织内运行的应用程序)来使用应用程序。关于企业架构与应用程序架构之间关系的常见比喻是把企业比作城市规划,把应用程序比作建筑结构。城市规划者必须考虑获得水、电、污水和其他服务才能使城市运转。一栋大楼使用的自来水不能多于提供给它的配额。企业架构需要为应用程序考虑同样的事情:您不可以允许一个应用程序使用所有网络带宽,而如果基础设施服务崩溃,就会出现大量问题。

  企业架构在过去几年里得到了很多关注,这都是因为面向服务架构(Service-Oriented Architecture,SOA)。SOA 是一个独立的庞大主题,因此本系列未来几期文章将把它处理为特殊案例。它拥有自己的有趣方面,因为它在规定应用程序构造的特性时,它模糊了企业架构与应用程序架构之间的界限。

  企业级应用

  企业级应用是指那些为商业组织、大型企业而创建并部署的解决方案及应用。这些大型企业级应用的结构复杂,涉及的外部资源众多、事务密集、数据量大、用户数多,有较强的安全性考虑。

  当代的企业级应用决不可能是一个个相互独立的系统。在企业中,一般都会部署多个彼此连接的、相互通过不同集成层次进行交互的企业级应用,同时这些应用又都有可能与其它企业的相关应用连接,从而构成一个结构复杂的、跨越Intranet和Internet的分布式企业应用群集。

  此外,作为企业级应用,其不但要有强大的功能,还要能够满足未来业务需求的变化,易于升级和维护。

  过度设计的陷阱

  设计人员往往喜欢套用设计模式、多层架构来进行架构的设计,其通病往往是过度设计。过度设计的解决方案不能说不好,其动机也十分明显:如果我们构建许多扩展层,我们稍后可以在其上更轻松地构建更多层。但是,这是一个危险的陷阱。因为一般性将增加熵(复杂度),所以您将破坏在项目初期中通过有趣的方式演化设计的能力。增加过多灵活性将使对代码库的每一次更改都变得更加复杂。

  此外,过多时使用配置文件和配置项也使得系统使用、维护和设计都异常复杂,代码可读性和维护性下降。除了开发人员自己,没有人能简单的维护和升级这个系统,这样的设计不能不说糟糕。

  当然,您不可以忽略可扩展性。敏捷的移动性在决定如何实现功能时很重要:YAGNI(You Ain't Gonna Need It)。这是避免过度设计简单功能的信条。只实现目前需要的功能,在以后您需要更多功能时,可以再进行添加。我看到过某些 Java 项目为了实现一般性和可扩展性,在架构与设计方面使用了大量折衷,最后导致项目失败。这是个令人感到讽刺的教训,因为本来希望尽可能延长项目的生命周期,结果反而缩短了生命周期。了解如何把握可扩展性与过度设计之间的微妙界限十分困难。

  设计的折衷

  您可能由于外部压力(例如日程压力、资金压力)在设计中有所折衷,但糟糕的是架构设计往往具有不可逆性,也就是说,一旦今天你决定了系统的架构,就像你铺好了建筑物的龙骨一样,不可能简单的逆转了。能改的只是建筑物的外表和装饰了,就像代码级别的重构一样。架构重构?资金和风险,决定了其不可逆。

  我的一个同事为一家具有工会组织的公司做过一个工资系统。该工会为其某些成员争取的一项福利是在狩猎季节开始时有一天额外的休假(嘿,他们一定是有优秀的谈判代表)。涉及的员工只在一家工厂工作,但是提供额外的休假是整个公司的工资系统的合法部分。这项更改给软件增添了许多复杂度,而这种业务需求又必须满足,如何能不破坏我们的设计而满足这种特殊需求呢?您可能由于外部压力(例如日程压力、资金压力)在设计时给它开了一个口子,这种折衷很明显会破坏良好的架构。但这种复杂性确实存在。

  另一个示例:输入表单的字段级安全性。许多业务人员都认为他们需要对每个字段的安全特性进行精细控制。实际上,一旦实现这样的精细控制,他们几乎总是很讨厌它,因为这将给需要定义和维护所有元数据的用户带来负担。我们的一个项目中的业务人员真的非常需要此功能,因此我们为他们在其中一个屏幕中实现了部分此功能。在他们粗略意识到使用此功能所需的工作后,他们决定,由于访问应用程序的惟一方法是通过一间上了锁的办公室,因此他们可以采用更粗粒度的安全性。这是一个在业务人员认识到他们认为必需的功能之后做出设计决定的优秀示例。设计师的难处就在于此。