我总是被困在一块石头和一个坚硬的地方之间。理想情况下,您的业务逻辑完全不关心数据库或 UI 相关问题。
按键导致问题
尽管如此,我还是发现诸如主键和外键之类的东西会导致问题。即使是像 Entity Framework 这样的工具也不能完全消除这种蠕变。将作为 POST 数据传递的 ID 转换为它们各自的对象,仅将其传递给业务层,然后再将它们传递给数据层以再次被剥离,这是非常低效的。
即使是 NoSQL 数据库也存在问题。它们倾向于返回完整的对象模型,但它们返回的通常比您需要的多,并且可能导致问题,因为您假设对象模型不会改变。并且在 NoSQL 数据库中仍然可以找到密钥。
重用与开销
还有代码重用的问题。数据层返回完全填充的对象是很常见的,包括该特定表中的每一列。但是,业务逻辑通常只关心此信息的有限子集。它适用于仅携带相关数据的专用数据传输对象。当然,您需要在表示之间进行转换,因此您创建了一个映射器类。然后,当您保存时,您需要以某种方式将这些较小的对象转换回完整的数据库表示或执行部分更新(意味着另一个 SQL 命令)。
所以,我看到很多业务层类接受直接映射到数据库表(数据传输对象)的对象。我还看到很多业务层也接受原始 UI 值(表示对象)。业务层在计算过程中调用数据库以检索所需数据的情况也很常见。尝试预先获取它可能效率低下(想想 if 语句如何影响检索到的数据),并且延迟加载的值会导致大量魔术或意外调用数据库。
先写出你的逻辑
最近,我一直在尝试先编写“核心”代码。这是执行实际业务逻辑的代码。我不了解你,但很多时候在查看别人的代码时,我会问这样一个问题:“但是,它在哪里做 [业务规则]?”通常,业务逻辑充满了对抓取数据、转换数据等问题的关注,以至于我什至看不到它(大海捞针)。所以,现在我首先实现逻辑,当我弄清楚我需要什么数据时,我将其添加为参数或将其添加到参数对象。让其余代码适应这个新接口通常需要某种中介类。
不过,正如我所说,在编写业务层时,您必须牢记很多事情,包括性能。上面的方法最近很有用,因为我还没有版本控制或数据库模式的权限。我在一个黑暗的房间里工作,到目前为止我只了解需求。
在写作时考虑到测试
利用依赖注入对于预先设计好的架构很有用。尝试考虑如何在不访问数据库或其他服务的情况下测试代码。这也适用于可以在多个上下文中运行的小型、可重用类。
结论
我的结论是,确实不存在完美的业务层。即使在同一个应用程序中,有时一种方法也只能在 90% 的时间内起作用。我们能做的最好的事情就是尝试编写最简单的东西。在最长的时间里,我避免使用 DTO 并使用对象包装 ADO.NET DataRows,因此更新会立即记录在底层 DataTable 中。这是一个巨大的错误,因为我无法复制对象,并且约束导致在奇怪的时间抛出异常。我这样做只是为了避免显式设置参数值。