ASP.NET——如何在不过度设计的情况下有效地使用设计模式!

Posted

技术标签:

【中文标题】ASP.NET——如何在不过度设计的情况下有效地使用设计模式!【英文标题】:ASP.NET -- How to effectively use design patterns without over-engineering! 【发布时间】:2010-10-05 00:10:45 【问题描述】:

我很感激人们对我自 ASP.NET 出现以来一直在苦苦挣扎的困境提出的想法。

在经典 ASP 中,代码层很少。 ASP 页面包含 html 和脚本组合。 COM 组件包含业务逻辑和DAO 基础设施。 ASP 页面本身很乱,但一切都在一个地方。

ASP.NET 的代码隐藏整理了代码,这很好。这些控件允许我们在表示层上更加面向对象。这些东西很好。

这是我的问题。我参与的许多项目都是企业 Web 应用程序,但并不是那么复杂,比如 10 个左右的网页/用户界面、大量的数据库交互等。这些过去理解起来是小菜一碟。现在我经常会遇到 5 到 10 层代码来创建一个相当简单的网页。这些可能包括 ASP、代码隐藏、控件类、DTO 类、ORM 对象,然后还有一些其他的东西。

除了访问数据库的 5-10 层之外,还有许多仅为存储普通数据而创建的自定义对象,而不是像集合那样使用 POCO(普通的旧 CLR 对象)。要理解这些对象,通常必须追溯包括 3 级或更多级别的对象和接口的继承层次结构。

这里是关键:以前,我查看 1 个 ASP 页面并说 1 或 2 个小对象,一些 SQL 查询,这些都完成了工作并且维护和理解相当简单。

现在,对于同一个页面,实际上可能有 50 个或更多对象,分布在自定义命名空间中的数百个对象中。

请问各位代码工匠,这是进步吗?是不是有些人对他们的滑稽有趣的新设计图案玩具有点过火了?有快乐的媒介吗? 有没有一种方法可以有效地使用设计模式,而不会创建太多的对象,以至于它变得比旧的程序范式更糟糕的意大利面条代码?

请分享你的想法。

【问题讨论】:

主观和论证。 不管这是否属于 SO,我认为这是一个很好的问题,也是我也在努力解决的问题。也许它更适合programmers.stackexchange? 【参考方案1】:

撇开组织需要这些抽象级别的可能性不谈(不太可能,但确实会发生),开发人员(尤其是在非敏捷、公司/企业环境中)添加太多的抽象层是很常见的。抽象。它发生在经典的 ASP 中,.NET 让它变得更容易。我们这个行业中的大多数人都有一种将事情过度复杂化的自然倾向,这需要纪律和积极的思维来克服这一点。

此外,许多平庸的开发人员错误地认为,最大化抽象层和模式使用会使他们成为更好的开发人员。

最后,许多平庸的开发人员被教导他们应该使用层、抽象和模式,但没有被教导得足够好,以至于不知道如何、何时或为什么。所以他们进入一个项目时会想“好吧,我知道我应该在这里有一些层......”你可以想象会发生什么。

归根结底,最佳实践的“最佳实践”是尽可能简单地编写代码,直到遇到阻碍您前进的真正问题。很多时候,您的工具箱中应该有适合该任务的模式或最佳实践,就像您有合适的扳手拧螺母一样。最佳实践和模式是工具——你不会拿出锤子开始摆动,直到你有一个需要敲打的钉子。软件开发也是如此。

【讨论】:

我喜欢你的雷克斯风格。欢迎来到 SO!从到目前为止我看到的答案中,您一直在提供可靠的建议 @simucal 谢谢!实际上,从私人测试版(用户#67!)的凌晨开始,我就一直在“开启” SO,但直到最近才觉得有必要真正参与进来。 好答案。作为一个平庸的开发者,我从第 3 段中笑了出来。太真实了。 非常感谢分享。我十分同意。不久前,我也是第 3 段。【参考方案2】:

有些人是architecture astronauts,他们会坚持认为这些层都是必要的,除非你包含它们,否则设计绝对是垃圾。

另一方面,有些人将这一切抛在一边,只是将所有代码拼凑在一起:这很简单,对,所以为什么不在代码隐藏中将 SQL 查询直接填充到列表框中控制?

您已经发现了 astronaut 版本的问题,只是执行简单任务过于复杂。

第二种方法的问题在于,虽然它适用于小型应用程序,但这些相同的应用程序有发展成大型应用程序的趋势,然后一切都崩溃了。您花费大量时间一遍又一遍地修复相同的错误,因为相同的查询或代码段已根据需要被复制/粘贴,并稍作修改,并传播到各处。

当然,有一个中间立场。取决于你问的是谁,具体的谎言在哪里会有所不同。但它就在那里。

建立一个健全的业务层是实现目标的好一步。这应该是呈现系统中对象的最简单视图的层,并且不包含面向公众的数据库相关内容(除了可能告诉业务层如何访问数据库的 Connection 对象)。这将您的所有逻辑整合到一个地方,因此项目的 ASP 部分只需将抽象的“User.LoadAll()”方法连接到显示用户列表的表。 ASP 应用程序应该不知道它是从数据库、Web 服务中读取数据,还是只是一堆编造的东西……它只是与业务层对话。

在业务层下,您可以直接进行查询,您可以使用 ORM,您可以构建更深的数据访问层来执行这些操作.. 好在这个决定完全由业务层包含(而且您可以如果需要,以后再修改它,而不影响业务层的公共 API)。

现在所有与用户相关的查询都包含在 User 对象中。如果您在加载权限的方式上存在错误,可以在一个地方进行修复。

我刚刚进行了如上所述的迁移(在代码隐藏中使用 SQL 的 ASP,到一个独特的表示 - 业务 - 数据源 (ORM) 层),它很棒。尽管它确实为获取实际信息增加了几层,但一旦业务方法起作用,其余代码就起作用了。修复错误很简单,并且可以在任何地方修复它。接近尾声时,很快就会出现这样的情况,当您需要获取用户可以运行的报告列表时,有人已经为此编写了一个业务方法(User.GetReports()),而在此之前,您可能永远不会找到它,如果它已经完成 - 如果你幸运的话,它被编写为一个函数,而不仅仅是内联代码。

【讨论】:

+1 仅供宇航员参考,但其余部分也很好。【参考方案3】:

我从事的项目在相反的方向上做得很糟糕(200 多 MB 的源代码树,没有设计模式)。相信我,这也不是正确的解决方案。代码变得无法维护,开发人员绊倒了旧代码,等等。

另一方面,回答您关于设计模式的问题:

不,这不是进步。是的,有些人过火了。可能有一个快乐的媒介,但我认为它需要世界上的设计模式专家冷静一点。

我尝试使我的解决方案尽可能简单。这可能涉及设计模式……也可能不涉及;真的没关系,只要能用,而且容易维护。重要的是……设计模式不是解决糟糕代码的灵丹妙药。仅仅因为一个人使用设计模式并不意味着一个人的代码写得很好。不幸的是,太多的开发人员被教导(或他们自己相信):如果他们使用设计模式,他们的代码质量会更高;这不一定是真的(我认为甚至不是定期的)。

顺便说一句:如果您想要一个出色的过度设计示例,请查看 CruiseControl.NET 托盘应用程序的源代码。这是对设计模式失控的一个很好的演示(老实说,Thoughtworks 整体就是一个很好的演示)。

【讨论】:

【参考方案4】:

对我来说,问题源于关注了太多文章,而作者没有花时间解释解决方案的背景。

为中型企业编写商业应用程序的人受制于某些技术,与为向其他公司销售软件的供应商工作的人构建应用程序的方式不同。

所以对于想要做“正确的事情”的缺乏经验的开发人员来说,我认为过度工程是一个容易掉入的陷阱。

还有其他人只是希望每个项目都“完美”。我不知道对那些家伙说什么。我从来没有足够的时间或预算来让任何项目“完美”。

【讨论】:

【参考方案5】:

我认为您看到的大部分内容可能是正式的业务层和数据层代码。在这种情况下,代码应该遵循明确定义的模式,以便清楚地知道什么在哪里以及(更重要的是)为什么。如果不是这样,您就不是在查看具有代表性的 ASP.NET 代码。

与您关于易于遵循 Classic ASP 的论点相反,我发现任何大小的经典 ASP 站点很快就会变成一个未记录的包含文件的迷宫,因此很难确定函数的实现位置或声明的变量.

主要是 ASP.NET 在帮助开发人员安全地重用代码方面比经典 ASP 做得更好,所以当他们利用这一点时不要感到惊讶。

现在这并不能真正解决您对分层设计过度的担忧。真的,我认为这取决于情况。如果您的网站是唯一系统访问数据库并且它不是那么大,那么它可能是矫枉过正。但即使在这种情况下,大部分数据和业务层代码都可以由ORM 解决方案编写,这是一件好事,因为这样的代码通常没有错误,并且可以被推到修订系统的某个阴暗角落并忘记了。然后,当(不是“如果”)网站发展成为可以真正利用精心构建的数据层的东西时,该代码已经到位以支持它,并且生产或维护成本非常低。

另一方面,如果您的网站与企业报告软件或用于管理的 Windows 桌面应用程序共享对数据库的访问权限,或者多个小型应用程序与同一个数据库通信,那么可能所有这些“额外”代码都可以使用一个目的。编写数据和业务层代码的一个重要原因是,该代码可以在与数据库通信的每个不同系统之间共享,这样该代码就可以在一个地方实现。也许这是为一个小型网站编写的大量代码,但在这种情况下,它不是为该站点编写的。它是为网站和其他几个应用程序运行的环境编写的。

【讨论】:

完全同意经典的 ASP。任何重要的事情都很难正面或反面。【参考方案6】:

我认为在 Classic ASP 中使用我熟悉的设计模式会很困难,因此在这方面我们处于领先地位。

虽然我没有在 ASP.NET 中使用 MVC 实现,但我的理解是它解决了您的许多问题,因为它更直接和简单。

【讨论】:

【参考方案7】:

您提到的所有工具和技术的目的是在业务需求快速变化的世界中管理复杂性。 “复杂性和快速变化的业务需求”是否是您的应用所在世界的特点?

【讨论】:

管理复杂性和不断变化的需求的最佳方法是使代码更简单、更易于理解。除了 ORM 系统之外,OP 提到的所有内容都只会使代码的目的复杂化和混淆。【参考方案8】:

我认为这是一个更高层次的一般原则的例子。

这就像我们在小学时使用的剪刀一样,尖端是圆形的,边缘是钝的。你不能剪得很好,但你自己(或其他任何人)也不能很容易。

任何强大的东西都可以创造更大的利益和更大的潜力……否则。

值得称赞的是,微软在提供入门门槛低的工具方面做得非常好,因此任何老程序员都可以相对快速地完成一些有用的事情。但由于它们的简单性,有时它们不能很好地扩展,您需要升级到更复杂的工具集 - 但学习如何正确有效地使用新东西是值得的。所以你的问题是一个很好的问题,因为这是“首先理解它”过程的一部分。

【讨论】:

【参考方案9】:

这是进步,也不是进步。我们使用的新工具的使用情况可能是这里的问题,因为有些可能过度构建,而另一些可能构建不足,例如从标记到数据库逻辑再到业务逻辑,一切都在一个代码中,只是为了将它们放在一起。

在某些情况下,设计模式可以作为解决问题的好方法。例如,在以前的工作中,这些设备有一些必须支持的常用命令,因此我为每种类型的设备构建了一个适配器类和一个类,可以很好地解决问题。另一个帮助设计模式的例子是让外观模式隐藏外部系统如何运作的一些细节,以便有一个通用的内部功能列表来支持。

【讨论】:

【参考方案10】:

根据我的经验,完全不使用自定义数据库对象会更加敏捷。在较旧的 .NET 版本中,您可以传递 DataTable 对象。在 .NET 3.5 中,您可以使用 LINQ 免费获得强类型。

令人惊讶的是,一些开发人员花费 75% 的时间从数据库中检索数据。哪个 .NET 没有任何自定义代码就可以完美运行。使用标准库,您会发现自己有更多的时间来解决业务问题。

【讨论】:

【参考方案11】:

感谢到目前为止所有的 cmets。再澄清一点,在经典的 ASP 中,我们使用的是 VB 组件,这自然限制了我们将它们过度复杂化的能力,这在某种意义上是好的,因为它保持了它的简单性。

我喜欢 Rex 的回复“最终,最佳实践的‘最佳实践’是尽可能简单地编写代码,直到遇到阻碍你前进的真正问题。”

这听起来和我听到的另一个类似“过早的优化是万恶之源”。

在此之后,如果我们只是将所有总线逻辑放在代码隐藏中,然后在我们发现哪些代码真正被多个页面使用时将其移动到共享库中呢?例如,如果它是一页,您可以在代码隐藏中包含所有内容。如果有两个页面共享一个逻辑,则制作一个组件。如果两个组件使用 SQL Server,则创建一个新组件以简化 SQL 查询等。

我也喜欢 Dana 在构建自定义应用程序与构建单个应用程序方面的区别。如果有 1000 个其他人会使用它,那么拥有一个成熟的 API 是一回事。将相同的能量用于一次性应用程序可能是浪费时间。

“建筑宇航员”是过度工程倾向的一个很好的术语!

许多人表示有一个中间立场,我认为(希望)这就是我们都在寻找的!也就是说,C# 让我们能够做到rocket science,但也许这个级别只需要 5% 的时间。我认为加剧这个问题的事实是,如今大多数面试官都喜欢你非常熟悉所有火箭科学......

我想提出的另一个相关问题是:仅使用 POCO(.NET 提供)对象在 ASP.NET 架构中存储数据怎么样。我已经看到一些架构为每种类型的数据交换创建一个新对象。仅仅创建一个集合对象(比如列表)并称其为“this data”、“thatdata”等不是更简单吗?

【讨论】:

以上是关于ASP.NET——如何在不过度设计的情况下有效地使用设计模式!的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 Visual Studio 的情况下使用 ASP.NET MVC 实现站点?

asp.net中,在不播放视频的情况下如何获得视频长度

如何在不使用 Visual Studio 的情况下使用 ASP.NET MVC 实现站点?

如何在不刷新的情况下使用 Ajax 在 ASP.NET MVC 中保存表单数据

如何在不使用角色的情况下使用 ASP.NET WebAPI 实现基于声明的授权?

ASP.NET CORE MVC 选择标签助手 - 如何在不使用 ModelView 的情况下设置选定值