关于业务对象中集合表示的体系结构选择
我在我的架构中做出了某些选择,我要求社区进行审查和评论。我将这篇文章分成较小的部分,以便更容易理解上下文,然后提出建议/评论。很抱歉这篇文章很长,但需要解释一下上下文。
我在构建什么
一个典型的业务应用程序,其中有应用程序用户、安全角色、基于角色的业务操作/操作权限以及多个业务模块,如库存接收、库存转移、销售订单、销售发票、销售退货、库存审计等几份报告。该应用程序是一个 WinForm 应用程序,因为它具有许多丰富且响应迅速的 UI 要求,并且大多数时候必须在断开连接模式下运行(使用本地 SQL Server)。
我做了什么
我已经构建了一个框架 - 没有什么值得夸耀的,只是一组满足我的应用程序重复需求的库,例如身份验证、基于角色的授权、数据访问、验证、异常处理、日志记录、更改状态跟踪、呈现模型的合规性以及组件之间合理的松耦合。不,我并没有从头开始编写所有内容,你可以说我将很多东西整合在一起,例如 CSLA 的一些概念、Martin Fowler 的演示模型、Enterprise Library 的块、Unity 等,以构建一组可以帮助我的开发人员的库无需在 Google 上查找许多技术要求即可快速提高工作效率。我试图保持该框架的通用性,以便它可以在典型的业务应用程序中使用,并且还尝试遵循一些最佳实践,这些最佳实践将支持在 ASP.NET MVC 环境中使用相同的业务对象。
我目前的架构很好地满足了我的目标,并且已经轻松构建了多个模块(在 WinForm 上)。该体系结构还非常适合在 ASP.NET MVC 上使用相同的业务对象集构建一些可用的原型,而无需更改任何代码行。
我的困境
我使用了自定义业务对象,因为它为我的解决方案范围中的问题范围提供了更清晰的 OOP 表示,并帮助我将整个解决方案可视化为具有数据和行为的对象集合,而不是一组关系数据(DataSet )并分别实现行为(业务逻辑、验证)等。借助 .NET 2.0 中丰富的数据绑定支持,将自定义业务对象绑定到 UI 变得轻而易举。
现在,在构建我的业务对象时,我仍然对业务对象中集合的表示感到困惑。目前,我使用数据集来表示集合,同时我看到了许多实现自定义集合的建议。例如,在我的设想中,典型的销售发票对象将包含“销售发票项目”作为集合。现在从理论上讲,我可以接受每个“销售发票项目”应该有自己的行为及其数据(项目代码、名称、数量、价格等),但通常销售发票中销售发票项目的管理是由销售部门处理的发票对象本身,例如从集合中添加/删除项目。此外,我们还可以在销售发票对象本身中放置销售发票项目的业务逻辑/规则,例如“数量不应大于订购数量”、“价格最多应比销售订单中的价格高 10%”等。
有了这种愿景,我觉得大多数业务对象子集合都可以由父集合本身管理,包括从集合中添加/删除以及实现集合项的业务逻辑,因此集合项只包含数据。
此外,典型的集合在网格的 UI 中表示,其中支持数据绑定的能力对于任何集合都非常重要。在这种情况下,实现自定义集合也意味着,我还必须为集合实现强大的数据绑定支持,这当然很耗时。
现在,考虑到子集合行为是在父集合中实现的,并且需要子集合的数据绑定,我选择 DataSet 来表示业务对象中的任何子集合。在上面的销售发票示例中,我将“发票编号”、“日期”、“客户”等作为“销售发票”的属性,但将“发票项目”作为数据集。当然,当我说 DataSet 时,它不是一个普通的数据集,而是一个扩展的 DataSet,它支持业务规则验证和我的框架的基于相同角色的安全模型,以自动允许/拒绝对 DataSet 的行/列的任何业务操作。
这种方法使我的业务对象中的集合管理和数据绑定变得更加容易,并且我的开发人员能够快速交付模块。
问题
您觉得这种做法合理吗?
您认为这种方法有什么缺点吗?
我最近正在考虑使用“类型化数据集”作为子集合,以便更容易地在代码中表示,这将允许我编写“currentInvoice.InvoiceItems”(对于数据表)和“invoiceItem.ProductCode”或“invoiceItem.Qty” ',而不是 'drow["ProductCode"].ToString()' 或 '(int)drow["Qty"]' 等。这个选择有什么缺点吗?
如果您已阅读到目前为止,谢谢您;如果您仍有精力回答,请向您致敬。
I have made certain choices in my architecture which I request the community to review and comment. I am breaking up the post in smaller sections to make it easier to understand the context and then suggest/comment. I am sorry that the post is long, but is required to explain the context.
What am I building
A typical business application where there are application users, security roles, business operation/action rights based on roles and several business modules like Stock Receive, Stock Transfer, Sale Order, Sale Invoice, Sale Return, Stock Audit etc. and several reports. The application is a WinForm application since it has a lot of rich and responsive UI requirements and has to operate in disconnected mode (with a local SQL Server), most of the time.
What have I done
I have built a framework - nothing to boast about, but just a set of libraries that serves the repetative requirements of my application, e.g. authentication, role based authorization, data access, validation, exception handling, logging, change status tracking, presentation model compliance and reasonable loose coupling between components. No, I have not written everything from scratch, you can say I have consolidated many things together like some concepts from CSLA, Martin Fowler for Presentation Model, blocks from Enterprise Library, Unity etc. to build a set of libraries that will help my developers be productive quickly without having to look up Google for many of the technical requirements. I have tried to keep the framework generic so that it can be used in typical business applications and also tried to follow some best practices that will support the same Business Objects to be used in an ASP.NET MVC environment also.
My present architecture serves my objectives well, and have built several modules (on WinForm) without much trouble. The architecture also lent itself well to build some usable prototype on ASP.NET MVC with the same set of business objects, without changing a single line of code.
My Dilemma
I have used Custom Business Objects since that gives me a clearer OOP representation of the problem scope in my solution scope, and helps me visualize my entire solution as collection of objects with data and behavior rather than having a set of relational data (DataSet) and implement behaviours (business logic, validation) etc. separately. With rich databinding support in .NET 2.0 binding Custom Business Objects to UI was a breeze.
Now while building my business objects, I am still in a dilemma about representation of collections in business objects. Currently I am using DataSets to represent collections while I have seen many suggestions to implement custom collections. For example, in my vision, a typical Sale Invoice Object will contain 'Sales Invoice Items' as a collection. Now theoritically, I can accept that the each 'Sales Invoice Item' should have its own behavior along with their data (ItemCode, Name, Qty, Price etc.) but typically managing of Sale Invoice Items in a Sale Invoice is handled by the Sale Invoice Object itself, e.g. adding/removing Items from collection. Additionally, we can also put business logic/rules for the Sales Invoice Items like "Qty should not be greater than the ordered qty", "Price should be max 10% above the price in Sale Order" etc. in the Sale Invoice object itself.
With that kind of a vision, I felt that most business object child collections can be managed by the parent itself, including add/remove from collection as well and implementing business logic for the collection items, hence the collection items hold nothing but data.
Additionally, typical collections are represented in UI in Grids, where ability to support DataBinding becomes very important for any collection. Implementing a custom collection, in that case would also mean, I have to implement robust DataBinding support as well, for the collection, which is of course time consuming.
Now, considering child collection behaviors are implemented in the parent and the need for DataBinding of child collections, I chose DataSet to represent any child collection in my business objects. In the above example of Sale Invoice I will have 'Invoice Number', 'Date', 'Customer' etc. as attributes of the 'Sale Invoice' but 'InvoiceItems' as a DataSet. Of course, when I say DataSet, it is not a vanilla dataset but an extended DataSet that supports business rule validation and the same role based security model of my framework to allow/deny any business operation to rows/columns of the DataSet, automatically.
This approach has allowed easier collection management and databinding in my business objects and my developers are able to deliver modules rapidly.
Questions
Do you feel that the approach is reasonable?
Do you see any shortcomings of this approach?
I am recently thinking of using 'Typed DataSets' as child collections, for easier representation in code, that will allow me to write 'currentInvoice.InvoiceItems' (for the DataTable) and 'invoiceItem.ProductCode' or 'invoiceItem.Qty', instead of 'drow["ProductCode"].ToString()' or '(int)drow["Qty"]' etc. Does this choice have any demerits?
Thank you if you have read so far and a salute if you still have the Energy to answer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
类型化数据集往往有点慢。
如果您使用 WinForms,我建议使用。两者都扩展了
System.ComponentModel.BindingList
。这支持更改通知。 WPF 应用当然应该使用 System.Collections.ObjectModel.ObservableCollectionCollection
并具有可以挂钩以进行添加/删除等的虚拟方法。您可能需要在集合中的对象上实现的另一个接口是
INotifyPropertyChanged
(这仅适用于您在更新过程中不替换整行的情况)。Typed data sets tend to be a bit on the slow side.
If you're using WinForms what I would suggest is
System.ComponentModel.BindingList<T>
. This supports change notifications. WPF apps should of course useSystem.Collections.ObjectModel.ObservableCollection<T>
. Both extendCollection<T>
and have virtual methods you can hook into for adds/deletes etc..Another interface you might need to implement on the objects in the collections is
INotifyPropertyChanged
(this is only if you don't replace the entire row as part of an update).