合同优先SOA:devise业务领域:WCF
我正在构build一个使用WCF的全新系统。 我将使用契约优先方法来构build基于面向服务概念的服务。 我有一个服务操作,返回一个用户的银行帐户的详细信息。 该帐户可以是“FixedAccount”或“SavingsAccount”types。 我devise的服务如下。
[ServiceContract] interface IMyService { [OperationContract] AccountSummary AccountsForUser(User user); } [DataContract] class AccountSummary { [DataMember] public string AccountNumber {get;set;} [DataMember] public string AccountType {get;set;} }
这很好。
现在,我需要开发此服务的业务领域。 我可以想到两个select(任何新的方法总是受欢迎的)
1) 方法1 :提出一个BankAccount基类。 从它派生的专门类是“FixedAccount”和“SavingsAccount”。 BankAccount将有一个方法为Transfer(string toAccount)。 这成为我们熟悉和有效的OOAD。 这涉及到AccountSummary DTO和FixedAccount / SavingsAccount域类之间映射的映射器。
2) 方法2 :不使用映射器转换层。
问题
1)假设我正在使用方法1.是否有任何文章/教程解释如何根据DTO(条件映射)中的AccountType值将AccountSummary DTO映射到FixedAccount / SavingsAccount域类?
2)如何在方法2中完成任务?
读:-
-
http://www.soapatterns.org/service_facade.php
-
SOA架构数据访问
-
在WCF中devise服务和操作
-
WCF数据合同和参考实体数据?
-
什么时候逻辑属于业务对象/实体,什么时候属于一个服务?
首先 – 您需要了解您是否真的需要全面的SOA。
SOA基本上意味着每一个操作都经历了将我们的系统从其他系统中分离出来的服务。 在极less数情况下(如果应用程序变得非常庞大) – 从另一个系统的一部分。
您的应用程序会与其他应用程序“交谈”吗?
如果没有,你只是build立庞大的网站,解放你的思想,并削减SOA的bullcrap。 否则,你将最终用无用的抽象层。
这是您应用第二种方法的唯一方法,因为您无法将域模型完全解耦合,而无法将其映射到其他位置。
如果确实需要SOA – 我们必须封装,从外部世界隐藏我们的领域模型。 这意味着 – 我们的模型必须有一些映射到DTO。
是否有任何文章/教程解释如何将AccountSummary DTO映射到FixedAccount / SavingsAccount
映射本身并不复杂。 这里有一个简单的方法来映射对象:
class AccountSummary{ public string InterestingThing {get; set;} public string AnotherThing {get; set;} } class AccountSummaryMapper{ public static Map(BankAccount a){ return new AccountSummary{ InterestingThing=a.SomethingSomething, AnotherThing=a.Something.Else.ToString() }; } } var accountSummary= AccountSummaryMapper.Map(myBankAccount);
这可能看起来没有效果。 像Automapper这样的对象到对象映射器可以提供帮助。 通过教程,它应该是足够好,让你去。 想法并不困难 – 你创buildMaps,在应用程序启动时告诉Mapper它们,然后使用Mapper通过给定的configuration来映射你的对象。
另外 – 考虑映射方向。 良好的面向对象的代码通常意味着你要么提出问题,要么告诉对象去做东西。 对象不应该知道其他对象职责的内部运作。
比方说,家长完成孩子的家庭作业是不好的,因为孩子不会学到任何东西,父母也会因为不必要的工作而背负。 相反,父母应该强迫孩子独立工作。
将AccountSummary直接映射到BankAccount并重新设置其状态就像做功课一样。 不应该需要这样的映射。 相反 – 告诉BankAccount BankAccount.DoHomework(铅笔,副本,一些强词)。
开发业务领域
你不开发业务领域。 您开发的领域模型只是业务领域的一个反映,是为了解决特定的问题。
在您完成这部分工作之前,您需要确定您的客户将从每个服务方法调用中获得什么。 客户是否需要FixedAccount / SavingsAccount,还是只需要一个AccountSummary?
如果方法(如你的例子中的那个)只返回AccountSummary,那么一个简单的方法就是向BankAccount添加一个方法来创buildAccountSummary。 然后,当你想要返回一些东西(不pipe是什么types的帐户,但假设你的两个帐户从BankAccountinheritance),你只需要这样做:
return someAccount.ToSummary()
有些人会告诉你,这是不是“纯”的,因为你是BankAccount类现在知道你的AccountSummary,但我个人总是觉得它更容易处理。 如果你不喜欢这样的话,像AutoMapper这样的工具也可以很有效地做到这一点(正如其他答案中提到的那样)。
如果你返回的是某种派生类而不是实际的类本身,那么就没有办法在某个地方映射它(如果你使用AutoMapper或者自己写一些东西的话)。 避免执行任何映射的唯一方法是返回BankAccount本身,而不build议用于服务,因为类的内部更改会影响服务。 现在很容易记住,但是在另一个开发人员进行维护的三年内,也很容易忘记。 映射也只是发送你明确告诉它的服务,所以它又帮助避免了泄漏数据的错误。
BankAccount.ToSummary()的内容非常简单
public AccountSummary ToSummary() { AccountSummary s = new AccountSummary(); s.AccountNumber = AccountNumber(); s.Balance = Balance() return s; }
对于方法一,考虑使用像AutoMapper这样的工具,而不是手动实现映射。 可以为你节省很多的痛苦。 AutoMapper