设计徽章系统,在哪里解雇业务逻辑?在代码或存储过程中?或两者?

时间:2008-11-24 15:08:22

标签: architecture

如果你要构建一个类似于SO的徽章系统,你会将逻辑/业务层直接放在数据库中(通过存储过程,预定的sql作业)还是将它放在服务器端?

从我能想到的,你必须:

  1. 列出与当前用户操作相关的徽章
  2. 检查用户是否已拥有徽章
  3. 为用户插入徽章
  4. 潜在选项

    1. 调用存储过程等的Web应用程序中的业务逻辑。
    2. 仅限存储过程
    3. 每x分钟运行一次的SQL服务器作业
    4. 每x分钟运行一次的Windows服务
    5. 是否需要这些组合?我认为,因为一些徽章是基于给定问题的里程碑,也许批量工作更好?

      更新

      一个系统,您可以修改徽章系统,然后为每个人重新运行整个徽章链接会更好。也就是说你改变了一些徽章的逻辑,现在你必须将它重新应用到所有的问题/答案/投票/等。

      要解决的有趣问题!!

7 个答案:

答案 0 :(得分:18)

我建议将所有业务逻辑放在业务层中。我推荐这个有几个原因:

  • 将业务逻辑保持在一个 语言/地方
  • 可扩展性 - 您可以对数据进行分区,实现 不同的缓存机制等。
  • 关注点的分离 - 让您的数据库尽其所能......存储数据,让您的编程语言对该数据做出决策。

答案 1 :(得分:8)

我会把它放在业务层,毕竟这是我们正在讨论的业务逻辑。存储过程当然可以用来取回适当的数据,但我不是仅仅在数据库中实现决策逻辑的粉丝。如果不是因为在以后重新访问代码时跟踪正在发生的事情变得越来越困难。

答案 2 :(得分:4)

就个人而言,我会离开数据库进行数据存储/检索,并将逻辑放在“业务层”中。

随着StackOverflow的成功,我对我的一个网站实现了一个成就系统非常感兴趣 - 所以我一直在考虑这个问题。

我目前正在尝试评估具有轻量级(就处理能力而言)的例程,我可以根据特定的用户操作(向上投票,新答案等)运行该例程,这可以保留大部分随着网站的到来,徽章会更新。

这将由更重量级的例程支持,可以从头开始重新计算每个徽章。这可以定期从服务运行(或至少simulated service) 确保没有遗漏任何内容 - 但也是为了回应徽章规则的变化。

我想这个问题的答案中很大一部分将取决于您基于徽章奖项的数据。 StackOverflow徽章似乎基于数据(答案,问题,投票等)和事件(编辑,重新标记等)。所以 - 徽章算法大概必须询问某种审计日志或“行动”日志。

答案 3 :(得分:2)

所以 - 这是一场经典的SO辩论和热情的程序员之间的争论。我已经问了一个类似但更通用的问题......

business logic in database layer

为了回答第一部分,我发现我在代码与数据库中看到的关于业务逻辑的最佳解释之一就在这里:

http://www.codeproject.com/KB/architecture/DudeWheresMyBusinessLogic.aspx

它继续解释为什么业务逻辑更好,可扩展。我也是这样的心态......所以为了回答你的问题,我不会在数据库或存储过程中保留任何业务逻辑,主要原因是许多其他人认为SP不受版本控制,而且很痛苦版本控制它们。更不用说,用于SP的IDE比用于代码的IDE更加原始。而sql / tsql和类似的东西并不意味着复杂的代码结构,而是基本的数据操作,正如你在文章中看到的那样,对于一些非常基本的代码结构,因为以前的客户端 - 服务器架构是有限的。

本页的一些例外情况:

在客户端服务器系统中,有两层,因此强制实现至少两层。在早期,服务器被简单地视为远程数据库,该部门被视为应用程序(客户端)和存储(服务器)。通常,所有业务逻辑都保留在客户端中,与其他层(例如用户界面)混合在一起。

不需要花很长时间才能意识到可以通过将大部分业务逻辑移出客户端来减少网络带宽并进行逻辑集中以减少客户端的不断重新部署需求。由于只有两层,因此将业务逻辑移动到的唯一位置是服务器。服务器在架构上是一个非常适合客户端服务器系统的地方,但作为平台的数据库是一个糟糕的选择。数据库是为存储和检索而设计的,它们的可扩展性是围绕这些需求而设计的。数据库存储过程语言是为基本数据转换而设计的,以补充SQL中无法完成的任务。存储过程语言旨在非常快速地执行,而不是用于复杂的业务逻辑。

但这是两个选择中较好的一个,因此业务逻辑被转移到存储过程中。事实上,我认为商业逻辑是实用主义的问题,因为存在的过程中存在着商业逻辑(捣碎,适应)。在两层世界中,它并不完美,但却是一种改进。

业务层应包含所有业务规则。

这种设计具有以下优点: - 所有业务逻辑都存在于一个位置,可以轻松验证,调试和修改。 - 真正的开发语言可用于实现业务规则。这种语言更灵活,更适合此类业务规则,而不是SQL和存储过程。 - 数据库成为存储层,可以专注于有效地检索和存储数据,而不会出现与业务逻辑实现或表示层相关的任何约束。

所以 - 现在,关于体系结构,我会这样做,以便当相关问题/答案或其他任何内容更新时,通过调用存储过程来更新每个用户标记。你把它放在问题或答案的商业逻辑中,因为我认为它对于不同类型的项目(当它们被修改时)会有所不同。因为这是基于事件的操作,所以只有在事件发生时才会执行操作。如果您有服务或计划任务,它将一直运行,虽然很少,但是当您拥有大量用户时,它最终会陷入困境。

如果您不想让每个用户的事件触发gazilion检查和更新,您可以将它们分批到表中,并有一个预定的作业来更新徽章。

为了允许系统根据新的业务逻辑更新整个用户库,您可以将所有操作包含在Windows作业或一次性作业中,并且这比tsql,恕我直言,并且会更好更具维护性和灵活性。

但是,为了获得某些性能提升,有时候复制非常少的业务逻辑可能会让您受益匪浅。但正如您在文章中看到的那样,代码中的业务层更具可扩展性,因此它可能是一个没有实际意义的点。

希望这对您来说很有用,可以决定您需要什么......

答案 4 :(得分:1)

我会编写一个存储过程,因为所需的所有信息都驻留在数据库中,因此这是访问该数据的最有效位置。

可以通过以下行中的单个INSERT语句实现一个规则:

IF eligible for <new badge> THEN
    INSERT INTO user_badges
    SELECT <new_badge>
    WHERE NOT EXISTS (SELECT NULL FROM user_badges
                      WHERE badge = <new_badge>);
END IF;

(我有点简化!)

答案 5 :(得分:1)

我强烈建议将决策留给业务逻辑,而不是存储过程。存储过程用于处理数据(即收集数据,检查特定状态和条件,删除,更新,聚合等)。它不是条件逻辑(决策制定)的创造场所。

关于事件,经文数据:优点系统中的所有内容都是(或至少可以)基于事件。

  

数据(答案,问题,投票等)和事件(编辑,重新标记,   等)

......所有这些都是事件:回答问题,提出问题,投票等等。

您可以使用存储过程获取所需的数据,以确定是否已获得徽章,但您的代码应该实际做出决定,并在适当时分配徽章。对此的算法可能与徽章一样多种多样。但是,这是一个我会遵循的逻辑:

  • 根据所涉及的事件类型对所有徽章进行分类(例如 回答问题,提出问题,进行编辑,重新命名,投票等。)
  • 发生特定事件时,请抓取与之关联的所有徽章 那个事件(即通过完成任务可以获得的事件 触发事件)
  • 遍历该类别中的每个徽章并运行它的Badge.VerifyCriteria(UserID) 方法
  • 如果用户尚未拥有徽章,请进行徽章分配

VerifyCriteria方法将是存储过程可能存在的一个很好的例子,特别是如果您需要更高的性能。这同样可以检查数据库中的特定状态或条件,因为它是业务逻辑。某些标记可​​能需要一些在数据库语言(例如SQL)中很难处理的处理,因此VerifyCriteria应该是对象的实际方法,它适当地调用存储过程和/或代码。这也使您的业务逻辑对OO友好。

如果你想完全重新标记系统中的每个人,我会在后台运行批处理作业,或者如果处理足够轻,只需在下次登录时更新用户,或者下次他们访问用户数据(例如,当有人试图查看他们的个人资料时)。但我仍然会把它全部放在业务逻辑中。

答案 6 :(得分:0)

我会将所有业务逻辑集中在逻辑上以命名空间或包中分隔的单一语言中。例如,Web界面需要完成的所有工作都将由服务器使用服务公开。