领域驱动设计之业务逻辑处理
我们做软件开发的人,经常听到的一个词“业务逻辑”,经典的三层架构:表示层、业务逻辑层、数据访问层。这里面还专门有个业务逻辑层,表示层和数据访问层我们能够清楚的知道其职责(表示层负责界面展示及用户交互,数据访问层负责数据的存放和取出)。我们可能会迷惑,对于数据操作集中的业务,多数的业务逻辑层就是对数据访问层的封装,业务逻基层具体负责什么?本文主要讲下业务逻辑以及领域驱动中对于业务逻辑的处理
到底什么是业务逻辑呢。在了解业务逻辑前先来了解下业务
业务百度百科给出的解释:
“业务”更白话一些来说,就是各行业中需要处理的事务,但通常偏向指销售的事务,因为任何公司单位最终仍然是以销售产品、销售服务、销售技术等等为主。“业务”最终的目的是“售出产品,换取利润”。所以通常会把业务员等于销售员,也就是这个原因,业务就是进行或处理商业上相关的活动。业务也是渠道就是指产家与销点之间关系是通过渠道之间建立起来的。而业务员在这中间起了重大的作用。业务员的工作直接影响到产家、销点、消费者这三者之间的关系。
从上面的解释,我们知道业务其实就是一个活动、一个过程,准确点的说是一个流程。这个业务牵涉到的对象有厂家、销点、消费者、业务员。流程的组织者是业务员,其负责处理厂家、销点、消费者这三者之间的关系,业务员本身并不包含任何行为。
什么是业务逻辑
广义上的业务逻辑——社会所赋予行业的职能,行业应具备的特性,是这个行业存在的核心和灵魂。
狭义上的业务逻辑——等同于分层架构中“业务逻辑层”的职责,是软件中处理与业务相关任务的部分,一般狭义上的业务逻辑不包含数据持久化,而只关注领域内的相关业务。
业务逻辑的组成部分
1、业务对象
业务对象就是领域驱动设计中的领域实体,其包含行为和数据。
2、业务规则
业务规则就是某个领域内运作的规则。业务规则作用于领域实体,领域实体遵从业务规则进行运作。
3、完整性约束
领域实体和业务规则构建了业务逻辑的主体,但在这主体之上,还存在着一个限制,这就是完整性约束。完整性约束是对业务领域中的数据、规则的强制性规定与约束。这种约束是系统正常运转的保证。
4、业务流程
有了上述三项,业务逻辑还不能正常工作,因为还没有“启动器”和“过程托管器”。设想我们有了各种实体类,它们有各自的属性和行为,也有定义好的业务规则和完整性约束。现在实体类仅仅具有实现业务规则的能力,但它们如何启动并交互协调完成业务规则呢?因此我们需要有东西去触发和协调实体。
业务流程或工作流是启动及托管协调领域实体完成既定规则的过程。
以银行转账为例
在银行领域内,转账时从A账户扣除相应款项,在B账户添加相应款项,并从A账户扣除相应手续费,并通过某些途径通知A和B账户的户主
领域实体Account
public class Account : AggregateRoot
{
#region Ctor
public Account()
{
}
public Account(decimal amount,string name)
{
this._amount = amount;
this._name = name;
}
#endregion
#region Field
private decimal _amount;
private string _name;
#endregion
#region Property
public decimal Amount
{
get { return _amount; }
set { _amount = value; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
#endregion
#region Method
/// <summary>
/// 帐户增加金额
/// </summary>
/// <param name="amount"></param>
public void Deposit(decimal amount)
{
Amount += amount;
}
/// <summary>
/// 帐户减少金额
/// </summary>
/// <param name="amount"></param>
public void Withdraw(decimal amount)
{
if (Amount - amount >= 0)
{
Amount -= amount;
}
else
{
throw new ApplicationException();
}
}
#endregion
}
Account 类就是一个业务对象。
application层的AccountService 类 调用代码
Account accountA=new Account(10000.00,”张三”);
Account accountB=new Account(0.00,”李四”);
decimal amount=5000.00;
accountA.Withdraw(amount);
accountB.Deposit(amount);
accountRepository.Save(accountA);
accountRepository.Save(accountB);
注意上面的代码应该使用事物处理,来保证转帐业务的完整性。 一般要引入 unitofwork (工作单元)