跳转至

开发Aqueduct应用的最佳实践

将Dart项目分开

由于Dart是跨平台的,因此开发人员应避免将客户端应用程序项目与Aqueduct项目结合在一起。 相反,请对系统的每个方面使用具有独立项目的单个存储库。 如果有机会在平台之间共享代码(通常是在Flutter和AngularDart之间),则共享代码可以存在于同一存储库中的依赖项项目中。

多方面应用程序的典型目录结构如下所示:

application_name/
  aqueduct/
  flutter/
  angular/
  shared/

项目定义

项目是一个包含pubspec.yaml文件和lib目录的目录。

在服务器和客户端应用程序之间共享数据模型类型是很诱人的,但这对于除了最简单的应用程序以外的任何东西都不适用。 数据模型的四种表示形式(在数据库中,在服务器上,在网络(JSON)上和在客户端上)在行为上有足够的差异,以至于单一类型很难包含。 相反,请使用aqueduct document生成OpenAPI规范,并使用许多开源工具之一来生成客户端数据模型类型。

使用测试驱动开发(或类似的工具)

在Aqueduct中,测试是一流的公民。aqueduct_test包里有一些类和方法,用于初始化和运行应用程序的测试,向应用程序发出请求,并验证响应。使用像Postman或CURL这样的工具来测试概念验证代码是有价值的,但是aqueduct_test包是专门为取代这些工具而设计的,同时随着项目的发展保留了自动测试。

一个测试套件的例子是这样的:

void main() {
  final harness = new Harness()..install();

  test("GET /endpoint returns 200 and a simple object", () async {
    final response = await harness.agent.get("/endpoint");
    expectResponse(response, 200, body: {"key": "value"});
  });
}

使用bin脚本验证假设

在导入项目的bin/目录下保留一个简单的Dart脚本文件。 在提交测试套件之前,将此文件添加到暂存器用以测试探索性代码。 不要将此文件添加到源码的版本管理中。

import 'package:myapp/myapp.dart';

Future main() async {
  var whatIsThis = await someYetToBeNamedUsefullyMethod();
  print("$whatIsThis");
}

从模板中创建新项目

使用 aqueduct create来创建具有适当结构和模板的应用程序。有不同类型的应用程序的模板;使用aqueduct create list-templates查看这些模板。

使用调试器

调试器允许你在某一行代码上停止执行正在运行的应用程序,以验证变量值,然后继续逐行执行该代码。它可以在运行测试套件或通过bin/main.dart脚本运行应用程序时使用。

在IntelliJ IDEA中,右击任何有main函数的文件(包括测试套件)并选择Debug选项。使用断点(通过点击文本编辑区左侧的沟槽区域),可以在执行特定行之前停止执行。

使用建议的项目目录结构

See Aqueduct 项目结构.

将服务传递给entryPoint中的控制器

entryPoint中向控制器传递服务对象,并且只传递控制器将使用的服务。

class AppChannel extends ApplicationChannel {
  GitHub githubService;
  PostgreSQLConnection databaseConnection;

  @override
  Future prepare() async {
    databaseConnection = new PostgreSQLConnection();
    githubService = new GitHub();
  }

  @override
  Controller get entryPoint {
    final router = new Router();

    router
      .route("/data")
      .link(() => new DBController(databaseConnection));

    router
      .route("/github")
      .link(() => new GitHubController(githubService));

    return router;
  }
}

通过这样的引用,可以注入依赖于环境的依赖关系;例如,在生产、开发或测试过程中。它也避免了应用程序中的对象之间的紧密耦合。

尽量减少控制器对其依赖关系的访问;例如,当它只需要SinkStream时,不要传递给它一个 StreamController

使用测试套件

测试工具会在测试套件中初始化您的应用程序。 它具有内置的行为,您可以添加到特定于应用程序的行为中。 在您的应用程序中使用测试工具的文档位于这里

使用 config.src.yaml

使用config.src.yaml文件的约定来防止配置错误和注入测试依赖项。

了解Aqueduct 如何使用隔离

请参阅 应用程序结构.

使用ResourceController子类

子类化ResourceController提供了大多数应用程序的请求处理逻辑所使用的显着便利性、安全性和行为。 最好将此类用于非中间件控制器。

保持ApplicationChannel整洁

ApplicationChannel应该处理初始化、路由,仅此而已。考虑将非初始化行为移到一个单独的文件中的服务对象中。

避免原始SQL查询

首选使用Aqueduct ORM。 它针对各种错误发送适当的HTTP响应,验证输入数据,并确保查询与您的数据模型匹配。

使用API参考资料

Aqueduct是一个面向对象的框架--行为由某种类型的实例来实现。对象的类型,它们的属性和行为都遵循类似的命名规则,使API更容易被发现。

Aqueduct中的许多类型都有一个与相关类型共同的前缀。例如,像 AuthServerAuthServerDelegateAuthCode这样的类型都是相关的,因为它们处理的是身份验证和授权。方法的命名在不同的类中是一致的(例如,asMap是一个常见的方法名)。

在寻找解决方案的时候,看看你可以访问的对象的API参考。这些对象可能已经有了你想要实现的行为,或者有一个具有该行为的对象的引用。

谨慎使用try-catch

所有请求处理代码都包装在try-catch块中,该块将解释异常和错误并返回有意义的HTTP响应。 未知异常将产生500服务器错误响应。 通常,除非您想要的HTTP响应与针对异常返回的响应不同,否则无需使用try-catch。

如果错误对于应用程序成功启动是致命的,则不应捕获在初始化期间引发异常的代码。