The more complicated our application gets, the more important separation of concerns becomes.
At 100 klocs, the application was one big blob, as much business code in form classes as anywhere else and calls into form methods from the business classes. With much wailing and gnashing of teeth, we separated out the business logic from the display logic. Any class that needed to notify the user of its progress raised an event that was sunk by the UI. And, for a while, all was right with the world.
Around 200 klocs, we added a data layer. The architecture of our application was such that most of our data was processed as soon as it came in and immediately discarded. Most configuration information was stored in the third-party application with which ours shared a symbiotic relationship. But, settings were starting to accumulate in all sorts of odd corners. We wound up with three configuration management systems, all intricately woven into the business logic. With an extensive rewrite, we were able to separate out the configuration information into its own layer and the handling of streaming data into another layer.
Near the 250 kloc line, we decided to end our relationship with the third-party vendor and make our application stand alone. We began a massive rewrite and, for the first time, added an actual database to our application. Because we had clear lines between streaming information, data storage, and business logic, this was a fairly seamless integration.
Now, approaching 500 klocs, we're moving the application to a grid-based architecture. Not only will the UI be separated from the business logic on a different computer, the actual computation of the quotes and orders that the application sends out will be load balanced and spread out to maximize efficiency. This would be impossible without an n-tier architecture.
At each stage of growth, we were either aided by a clean separation or hindered by our own muddle of communication, data, business, and UI. There probably hasn't been a more important concern than that separation in the creation of this application.
That's a great question! Something every ASP.Net developer needs to think about. You will probably get a lot of answers, I'd encourage these basic common-sense ideas.
--Consider simplicity and speed of delivery as a part of a "successful" architecture, not just "purity". Try to balance between holding to architectural ideals, and being practical.
--In general, it seems to make sense to divide the code out into layers as you mention. I would suggest though that for page-specific logic, it could be left in the page if it's simpler/faster--why create generic business objects for code which is just used in one place. As it's been said "Premature optimization is the root of all evil.”.
--Keep the layers and complexity to a minimum to reduce coding time and improve readability and maintainability.
There are many purists on this site who like to do architecture for architecture's site -- use architecture as a tool to deliver a solution to a business problem, not as just an art-form for it's own sake, let it be a useful tool rather than it using you.
将关注点分开。 这是非常非常重要的。 不要将 UI 与 Biz 以及 Biz 与数据层混合在一起。 使用抽象。 使用抽象还使测试(单元测试)变得更容易(模拟它们)。 我严格将每一层保留在其所属的位置。 请记住,任何项目中最高的成本都是其维护成本。 如果你把这些担忧混为一谈,那么维护将成为一场噩梦。
Keep the concerns seperate. It is very very important. Don't mix UI with Biz and Biz with data layer. Work with abstraction. Working with abstraction also makes the testing (unit testing) easier (Mock them). I strictly keep each layer where it belongs. Remember that the highest cost in any project is it's maintainance. If you mix the concerns then maintainance is gonna become a nightmare.
We have a Winforms app, and an ASP.NET app. They both use the same Business Objects project (about 140 classes).
The Winforms project consists of about 350 form and user control classes, and a very few (<10) of these need metadata about themselves from the database.
The ASP.NET project has about 100 .aspx pages.
We have a data access layer consisting of 5 classes, which concern themselves with ADO.NET, threads and transactions. They convert requests from the Business Objects into SQL Server calls.
The UI layers (with the exception of the few classes that need metadata about form sizing) do no database access at all. Even the few exceptions go through the DAL like anything else.
The Business layer knows nothing about the internal workings of the data access layer, and when it needs data, only ever calls public methods on the DAL classes.
I'm not at all a fundamentalist when it comes to this kind of thing, but we've never needed to cut corners on this one.
So in short, 100% pure. It's simply always worked out better to do it right.
We'd have to have a hell of a good reason to move away from this now.
Code Monkeys and Purists are a lot like any other extremist in life.
We have extreme right wing and extreme left wing. Very few people are exactly one or the other and they find a good middle ground where they sit. If it wasn't for the extremists we wouldn't know where the boundaries lie.
As far as the way I code goes. I listen to the purists way of doing it. I see the code monkeys going about their methods. I use my experience to choose a middle ground that gives me the right amount of flexibility and manageability along with the time I need to produce it and the amount of money I'm actually going to get for doing it.
但这并不是说强制分离的技术手段没有用处。 事实上,我发现,确保“跨境调用”有些困难,会让人们花更多时间思考跨境界面中他们真正需要什么,从而导致界面更干净。 无论困难是技术性的(因为您必须使用 COM 或 CORBA)还是其他方面的困难(您必须一式三份填写 7 页的表格),这并不重要。
The bigger the code, the longer the lifetime, the more different people work on the code (both simultaneously or during the lifetime) the more important she separation in layers is. In the beginning, it seems to be a bit more unnecessary work, but in the long run it pays for itself several times over.
As for enforcing the separation: That is why your lead programmer or technical architect needs good soft skills as well as pure technical skills. You can try to enforce the separation technically (see below) but in the end, you need to convince (or coerce) your developers to keep the big picture clean.
But this is not to say that technical means to enforce the separation have no use. In fact, I found that ensuring that "cross border calls" are somewhat difficult to make will make people spend more time thinking about what they really need in the cross-border-interface, leading to cleaner interfaces. It doesn't matter if the difficulty is technical (because you have to use COM or CORBA) or something else (you have to fill out a 7 page form in triplicate).
发布评论
评论(6)
我们的应用程序越复杂,关注点分离就变得越重要。
在 100 klocs 下,应用程序是一个大块,表单类中的业务代码与其他地方一样多,并从业务类调用表单方法。 我们咬牙切齿地把业务逻辑从显示逻辑中分离出来。 任何需要通知用户其进度的类都会引发一个由 UI 沉没的事件。 有一段时间,世界一切都好。
大约 200 klocs,我们添加了一个数据层。 我们的应用程序的架构是这样的:我们的大部分数据一进来就被处理并立即被丢弃。 大多数配置信息都存储在与我们共享共生关系的第三方应用程序中。 但是,各种奇怪的角落开始积累设置。 我们最终得到了三个配置管理系统,它们都错综复杂地融入到业务逻辑中。 通过大量重写,我们能够将配置信息分离到自己的层中,并将流数据的处理分离到另一层中。
在 250 kloc 线附近,我们决定结束与第三方供应商的关系,并使我们的应用程序独立。 我们开始大规模重写,并首次向我们的应用程序添加了实际的数据库。 因为我们在流信息、数据存储和业务逻辑之间有清晰的界限,所以这是一个相当无缝的集成。
现在,接近 500 klocs,我们正在将应用程序迁移到基于网格的架构。 不仅 UI 将与不同计算机上的业务逻辑分离,应用程序发送的报价和订单的实际计算也将进行负载平衡和分散,以最大限度地提高效率。 如果没有 n 层架构,这是不可能的。
在成长的每个阶段,我们要么受到彻底分离的帮助,要么被我们自己的沟通、数据、业务和用户界面的混乱所阻碍。 在创建此应用程序时,可能没有比这种分离更重要的问题了。
The more complicated our application gets, the more important separation of concerns becomes.
At 100 klocs, the application was one big blob, as much business code in form classes as anywhere else and calls into form methods from the business classes. With much wailing and gnashing of teeth, we separated out the business logic from the display logic. Any class that needed to notify the user of its progress raised an event that was sunk by the UI. And, for a while, all was right with the world.
Around 200 klocs, we added a data layer. The architecture of our application was such that most of our data was processed as soon as it came in and immediately discarded. Most configuration information was stored in the third-party application with which ours shared a symbiotic relationship. But, settings were starting to accumulate in all sorts of odd corners. We wound up with three configuration management systems, all intricately woven into the business logic. With an extensive rewrite, we were able to separate out the configuration information into its own layer and the handling of streaming data into another layer.
Near the 250 kloc line, we decided to end our relationship with the third-party vendor and make our application stand alone. We began a massive rewrite and, for the first time, added an actual database to our application. Because we had clear lines between streaming information, data storage, and business logic, this was a fairly seamless integration.
Now, approaching 500 klocs, we're moving the application to a grid-based architecture. Not only will the UI be separated from the business logic on a different computer, the actual computation of the quotes and orders that the application sends out will be load balanced and spread out to maximize efficiency. This would be impossible without an n-tier architecture.
At each stage of growth, we were either aided by a clean separation or hindered by our own muddle of communication, data, business, and UI. There probably hasn't been a more important concern than that separation in the creation of this application.
这是一个很好的问题! 每个 ASP.Net 开发人员都需要考虑的问题。 你可能会得到很多答案,我会鼓励这些基本的常识性想法。
--将简单性和交付速度视为“成功”架构的一部分,而不仅仅是“纯粹”。 尝试在坚持建筑理想和实用性之间取得平衡。
-- 一般来说,正如您提到的,将代码分为几层似乎是有意义的。 我建议,对于特定于页面的逻辑,如果它更简单/更快,则可以将其保留在页面中 - 为什么要为仅在一个地方使用的代码创建通用业务对象。 正如所说的“过早的优化是万恶之源”。--
将层次和复杂性保持在最低限度,以减少编码时间并提高可读性和可维护性。
这个网站上有很多纯粹主义者,他们喜欢为架构而架构网站——使用架构作为一种工具来提供业务问题的解决方案,而不仅仅是一种艺术形式,让它成为一个有用的工具,而不是使用你。
That's a great question! Something every ASP.Net developer needs to think about. You will probably get a lot of answers, I'd encourage these basic common-sense ideas.
--Consider simplicity and speed of delivery as a part of a "successful" architecture, not just "purity". Try to balance between holding to architectural ideals, and being practical.
--In general, it seems to make sense to divide the code out into layers as you mention. I would suggest though that for page-specific logic, it could be left in the page if it's simpler/faster--why create generic business objects for code which is just used in one place. As it's been said "Premature optimization is the root of all evil.”.
--Keep the layers and complexity to a minimum to reduce coding time and improve readability and maintainability.
There are many purists on this site who like to do architecture for architecture's site -- use architecture as a tool to deliver a solution to a business problem, not as just an art-form for it's own sake, let it be a useful tool rather than it using you.
将关注点分开。 这是非常非常重要的。 不要将 UI 与 Biz 以及 Biz 与数据层混合在一起。 使用抽象。 使用抽象还使测试(单元测试)变得更容易(模拟它们)。 我严格将每一层保留在其所属的位置。 请记住,任何项目中最高的成本都是其维护成本。 如果你把这些担忧混为一谈,那么维护将成为一场噩梦。
Keep the concerns seperate. It is very very important. Don't mix UI with Biz and Biz with data layer. Work with abstraction. Working with abstraction also makes the testing (unit testing) easier (Mock them). I strictly keep each layer where it belongs. Remember that the highest cost in any project is it's maintainance. If you mix the concerns then maintainance is gonna become a nightmare.
我们有一个 Winforms 应用程序和一个 ASP.NET 应用程序。 它们都使用相同的 Business Objects 项目(大约 140 个类)。
Winforms 项目由大约 350 个表单和用户控件类组成,其中极少数 (<10) 个类需要来自数据库的有关其自身的元数据。
ASP.NET 项目大约有 100 个 .aspx 页面。
我们有一个由 5 个类组成的数据访问层,它们涉及 ADO.NET、线程和事务。 它们将来自业务对象的请求转换为 SQL Server 调用。
UI 层(除了少数需要有关表单大小调整元数据的类之外)根本不进行数据库访问。 即使是少数例外也会像其他事情一样通过 DAL。
业务层对数据访问层的内部工作一无所知,并且当它需要数据时,仅调用 DAL 类上的公共方法。
在谈到这类事情时,我根本不是原教旨主义者,但我们从来不需要在这件事上走捷径。
简而言之,100% 纯净。 正确地做事总是效果更好。
我们现在必须有充分的理由摆脱这种情况。
We have a Winforms app, and an ASP.NET app. They both use the same Business Objects project (about 140 classes).
The Winforms project consists of about 350 form and user control classes, and a very few (<10) of these need metadata about themselves from the database.
The ASP.NET project has about 100 .aspx pages.
We have a data access layer consisting of 5 classes, which concern themselves with ADO.NET, threads and transactions. They convert requests from the Business Objects into SQL Server calls.
The UI layers (with the exception of the few classes that need metadata about form sizing) do no database access at all. Even the few exceptions go through the DAL like anything else.
The Business layer knows nothing about the internal workings of the data access layer, and when it needs data, only ever calls public methods on the DAL classes.
I'm not at all a fundamentalist when it comes to this kind of thing, but we've never needed to cut corners on this one.
So in short, 100% pure. It's simply always worked out better to do it right.
We'd have to have a hell of a good reason to move away from this now.
代码猴子和纯粹主义者很像生活中的任何其他极端主义者。
我们有极右翼和极左翼。 很少有人恰好是其中之一,他们会找到一个很好的中间立场。 如果没有极端分子,我们就不知道边界在哪里。
就我编码的方式而言。 我听的是纯粹主义者的做法。 我看到代码猴子正在使用他们的方法。 我利用我的经验来选择一个中间立场,它可以为我提供适当的灵活性和可管理性,以及制作它所需的时间和我实际上将获得的资金数额。
Code Monkeys and Purists are a lot like any other extremist in life.
We have extreme right wing and extreme left wing. Very few people are exactly one or the other and they find a good middle ground where they sit. If it wasn't for the extremists we wouldn't know where the boundaries lie.
As far as the way I code goes. I listen to the purists way of doing it. I see the code monkeys going about their methods. I use my experience to choose a middle ground that gives me the right amount of flexibility and manageability along with the time I need to produce it and the amount of money I'm actually going to get for doing it.
代码越大,生命周期越长,处理代码的不同人越多(同时或在生命周期内),层分离就越重要。 一开始,这似乎是一些不必要的工作,但从长远来看,它会带来数倍的回报。
至于强制分离:这就是为什么您的首席程序员或技术架构师需要良好的软技能以及纯技术技能。 您可以尝试从技术上强制执行分离(见下文),但最终,您需要说服(或强制)开发人员保持大局清晰。
但这并不是说强制分离的技术手段没有用处。 事实上,我发现,确保“跨境调用”有些困难,会让人们花更多时间思考跨境界面中他们真正需要什么,从而导致界面更干净。 无论困难是技术性的(因为您必须使用 COM 或 CORBA)还是其他方面的困难(您必须一式三份填写 7 页的表格),这并不重要。
The bigger the code, the longer the lifetime, the more different people work on the code (both simultaneously or during the lifetime) the more important she separation in layers is. In the beginning, it seems to be a bit more unnecessary work, but in the long run it pays for itself several times over.
As for enforcing the separation: That is why your lead programmer or technical architect needs good soft skills as well as pure technical skills. You can try to enforce the separation technically (see below) but in the end, you need to convince (or coerce) your developers to keep the big picture clean.
But this is not to say that technical means to enforce the separation have no use. In fact, I found that ensuring that "cross border calls" are somewhat difficult to make will make people spend more time thinking about what they really need in the cross-border-interface, leading to cleaner interfaces. It doesn't matter if the difficulty is technical (because you have to use COM or CORBA) or something else (you have to fill out a 7 page form in triplicate).