为WebForms说几句话,以及一些ASP.NET开发上的经验(1)

简介:
记得数年前,当ASP.NET刚出现时,天下间Web开发框架中似乎出现了一个“巨人”,WebForms这种似乎人人都能掌握的开发框架几乎瞬间流行起来。如果谁还在用传统ASP这种控制与表现混合的开发方式,似乎立即变得低俗了许多。于是乎许许多多人都学会了拖控件+绑定的方式,“Web开发人员”也越来越多,一片红火,好不热闹。
  风水轮流转,不知从什么时候开始Rails框架随着RoR忽的流行了开来,.NET社区也出现了Monorail,批判WebForms声音也慢慢多了起来。如今微软自己也推出了基于ASP.NET平台的MVC框架,很多WebForms的反对者似乎更加自信了:连微软自己都抛弃了WebForms,证明WebForms的确该退出历史舞台了,也听到了一些类似于“WebForms不适合Web开发已经是公认的事实”这样“无比肯定”的话。先不说微软推出MVC到底是不是意味着它抛弃了WebForms,单从那些MVC追捧者们“念念不忘”的WebForms的缺点上来看,我认为他们大部分只是在“跟风”,就和当年许许多多人追捧WebForms一样。
  不过我必须承认,我对ASP.NET MVC的了解仅限于 Scott Gu博客上所写的内容,至今还没有下载过ASP.NET 3.5 Extensions CTP。而对于RoR和Monorail也仅限于一些资料和示例,从来没有写过一行代码。按照我的“标准”,我自己是没有资格评论MVC框架的优劣的。不过我还是想写这篇文章,因为我只会WebForms平反,而不会“贬低”MVC框架;我只是想证明WebForms的那些缺点到底真的是缺点,还是开发人员自身没有好好利用起这把利器。因此我将会根据我的经验,一一回应对WebForms比较常见的指责。如果措辞上有任何的不妥,也请大家多多包涵。
  我下面提到的做法,都是在经过实际开发过程检验的(例如开发人员与美工的合作),可能不是最佳,但是我认为还是不错的。

一、ViewState

  HTTP是无连接无状态的协议,因此ASP.NET中提出了ViewState的概念,这样数据被重新Post回页面时,页面(控件)的状态就能恢复,因此才有了很多丰富的功能,例如一些复杂的控件事件。但是ViewState带来的问题就是,如果使用不当,那么页面体积就会增加许多,网络中传输的数据太多自然会影响性能。
  但是ViewState真是必须的吗?我可以很负责任地说,在如今大部分Web应用的页面中,出现的几乎都是大量的链接,点击链接就会跳转到一个和当前页面完全无关的新页面,这样的话,页面上的ViewState又有什么用?因此我如果新建一个Web项目,做的第一件事情就是去Web.config中将enableViewState从全局关闭——同时关闭的还有enableSessionState,这也是影响性能的因素之一(stateless也便于做Web服务器层面的负载均衡)。
  有人曾经反驳我,关闭了ViewState,用WebForm还有什么意义?我的答案是:意义多的很。WebForm提供了控件模型,我能够使用“人人都能看懂和编写”的方式来设置或读取一个文本框里的值。我能轻松地响应不同按钮的事件来编写触发各种业务逻辑。这就是意义,WebForms的开发还是非常简单而清晰的(在一定程度上吧,不要“滥用”永远是正确的)。
  嗯?刚才不是说只有保持ViewState才能使用控件的事件吗?没有ViewState怎么从控件中重新获取状态呢?请注意我之前所说的是“复杂事件”。什么是复杂事件?TextBox的TextChange事件就是“复杂事件”,GridView的Command事件也是复杂事件,但是Button的Click事件就是“简单事件”;与此相对的,GridView里的每一行的数据每一个子控件的状态是“复杂状态”,而TextBox的Text属性则是“简单状态”。“复杂状态”和“复杂事件”需要ViewState,因为与之有关的这些“控件”是ASP.NET“无中生有”的,但是“简单事件”和“简单状态”基于页面中“必然”会提交的数据,它们自然能够还能够使用。在我的ASP.NET开发过程中,使用的几乎都是“简单事件”和“简单状态”,而印象中放弃“复杂事件”和“复杂状态”并没有给我带来任何的困扰。
  当某人送给我们10件礼物,而其中只有4件是我需要的,那么为什么不能简单地放弃其余6件,偏偏要去感谢只送给我们3件礼物的人而去指责前者呢?要知道他并没有恶意,那多余的6件也没有给我们造成任何困扰。
  但人就是那么奇怪。

二、性能

  WebForms的一个重要特点就是一个强大(很多情况下也是“复杂”的代名词)的组件模型。这个组件模型包含一个叫做“生命周期”的玩意儿,也就是这个玩意儿被不少人指责为性能杀手。这个复杂的生命周期的确在很多时候只是“无谓”地一遍遍执行,似乎的确造成了“浪费”,但是这真的到了“杀手”级别了吗?
  如果您认为这个组件模型为性能杀手,不如编写一个内置1000个动态Button控件的页面,然后部署到服务器上,我保证运行的飞快。1000个不够的话那么可以试试看3000、5000甚至10000个控件。您哪张页面上控件的数量会比这个还多?但是您多少页面的性能会比它高?也有文章说“尽可能少的使用服务器端控件,最多使用HTML控件加上runat=server”,这更加没有理由了:一个加了runat=server的HTML控件,它已经变成了服务器端控件了。而普通的HTML最后在控件树中仅仅被作为普通的文本而处理,在控件树中是用一个Literal保存其中的“字符”。至于具体内容是什么,ASP.NET根本不会关心。
  造成性能问题的原因多种多样,在对性能问题进行探索和优化之前,一定要找准性能瓶颈是什么,才能对症下药。如果从某些层面上讲,将公共部分提取成新的方法,会造成执行上多一次call指令的执行,性能也就“降低”了,但是我相信没有人会因此将同样的代码到处复制。在我们接触到的Web应用中,性能瓶颈大都是在数据库访问上(或者外部Service访问,等等),多执行一次数据库查询操作可能就能抵得上内存中1亿次引用拷贝。我相信,如果一个ASP.NET应用程序的性能不高,几乎不可能是因为组件模型或生命周期造成的问题。
  既然Web应用瓶颈大都在数据库访问上,那么一般该如何解决这个问题呢?最直接的方式应该是优化数据库的查询,但是最关键的可能还是缓存。君不见每个谈到Web应用性能优化的讲座都将Cache放在数一数二的位置上,因为这的确是最有效的优化方式之一。在一个并发较高的Web应用中,对一些数据进行1分钟的缓存也能带来相当可观的性能提高。其他的方式可能还有生成静态页面(没有比这访问速度更快的了),异步调用(例如一篇刚发布的文章,在数分钟后才能被搜索到也没有关系,那么何必一定要同步地、即时地写入数据或者创建索引呢?)、分离不同作用的服务器(可以为不同服务器进行有针对性的配置,例如分离图片服务器),做Web服务器端的负载均衡(stateless的重要性由此可见),对数据库进行纵向切割(加快内存中载入的数据量可以提高查询性能,并且纵向切割后能够使用多台数据库服务器分担压力),横向切割(sharding,将数据分置在不同的数据库中,以此可以通过scale out来扩展减少每台服务器的负载,提高性能),作数据冗余或Master-Slave(稍稍降低写操作的性能而提高读取数据的性能,普通Web应用大都“读取”远多于“写入”)等等。
  当然我上面提到的都是应用程序实现和架构方面的东西,事实上开发一个高性能Web应用还涉及到硬件/软件/操作系统等多方面,这里就不多解释了(其实这方面我也还在探索过程中)。其实我在这里想说的仍然是,开发高性能Web应用程序的关键大都与具体所用的实现技术无关:只要“实现”正确,做法大都相同,无论Sql Server/Oracle,Windows/Linux还是ASP.NET/RoR,其本质都差不多。Ruby和C#的性能相差十倍(存疑,求证),不还是能够开发出高性能的Web应用吗?


本文转自 jeffz 51CTO博客,原文链接:http://blog.51cto.com/jeffz/59539,如需转载请自行联系原作者
相关文章
|
2天前
|
人工智能 量子技术 C#
【专栏】.NET 开发:开启数字化新时代
【4月更文挑战第29天】.NET开发在数字化新时代中发挥关键作用,借助跨平台能力、高性能和现代编程语言支持,如C#,助力企业实现数字化转型。通过企业级应用开发、移动应用和云计算集成,.NET加速业务流程和提升用户体验。未来,.NET将涉足AI、ML、MR/AR及量子计算,持续推动技术创新和数字化转型。开发者应提升技能,适应高性能需求,把握发展机遇。
|
2天前
|
缓存 监控 算法
【专栏】.NET 开发:实现卓越性能的途径
【4月更文挑战第29天】本文探讨了.NET开发中的性能优化,强调了理解性能问题根源和使用分析工具的重要性。基础优化包括代码优化(如减少计算、避免内存泄漏)、资源管理及选择合适算法。高级策略涉及并行编程、缓存策略、预编译(AOT)和微服务架构。持续性能测试与监控是关键,包括性能测试、监控分析和建立优化反馈循环。开发者应持续学习和实践性能优化,以构建高性能应用。
|
2天前
|
开发框架 .NET C#
【专栏】理解.NET 技术,提升开发水平
【4月更文挑战第29天】本文介绍了.NET技术的核心概念和应用,包括其跨平台能力、性能优化、现代编程语言支持及Web开发等特性。文章强调了深入学习.NET技术、关注社区动态、实践经验及学习现代编程理念对提升开发水平的重要性。通过这些,开发者能更好地利用.NET构建高效、可维护的多平台应用。
|
2天前
|
机器学习/深度学习 vr&ar 开发者
【专栏】.NET 技术:引领开发新方向
【4月更文挑战第29天】本文探讨了.NET技术如何引领软件开发新方向,主要体现在三方面:1) 作为跨平台开发的先锋,.NET Core支持多操作系统和移动设备,借助.NET MAUI创建统一UI,适应物联网需求;2) 提升性能和开发者生产力,采用先进技术和优化策略,同时更新C#语言特性,提高代码效率和可维护性;3) 支持现代化应用架构,包括微服务、容器化,集成Kubernetes和ASP.NET Core,保障安全性。此外,.NET还不断探索AI、ML和AR/VR技术,为软件开发带来更多创新可能。
|
2天前
|
物联网 vr&ar 开发者
【专栏】.NET 技术:为开发注入活力
【4月更文挑战第29天】本文探讨了.NET技术的创新,主要体现在三个方面:1) .NET Core实现跨平台开发革命,支持多种操作系统和硬件,如.NET MAUI用于多平台UI;2) 性能提升与生产力飞跃,C#新特性简化编程,JIT和AOT优化提升性能,Roslyn提供代码分析工具;3) 引领现代化应用架构,支持微服务、容器化,内置安全机制。未来,.NET 7将带来更多新特性和前沿技术整合,如量子计算、AI,持续推动软件开发创新。开发者掌握.NET技术将赢得竞争优势。
|
2天前
|
人工智能 前端开发 Cloud Native
【专栏】洞察.NET 技术的开发趋势
【4月更文挑战第29天】本文探讨了.NET技术的三大发展趋势:1) 跨平台与云原生技术融合,通过.NET Core支持轻量级、高性能应用,适应云计算和微服务;2) 人工智能与机器学习的集成,如ML.NET框架,使开发者能用C#构建AI模型;3) 引入现代化前端开发技术,如Blazor,实现前后端一致性。随着.NET 8等新版本的发布,期待更多创新技术如量子计算、AR/VR的融合,.NET将持续推动软件开发的创新与进步。
|
2天前
|
开发框架 物联网 测试技术
【专栏】.NET 开发:打造领先应用的基石
【4月更文挑战第29天】本文探讨了.NET开发框架为何成为构建领先应用的首选。高性能与稳定性是.NET的核心优势,它采用先进的技术和优化策略,如.NET Core的轻量级设计和JIT/AOT编译模式。跨平台兼容性让开发者能用相同代码库在不同操作系统上构建应用。现代化的开发体验,如C#语言的创新特性和Visual Studio的强大工具,提升了开发者生产力。丰富的生态系统和广泛支持,包括庞大的开发者社区和微软的持续投入,为.NET提供了坚实后盾。
|
2天前
|
人工智能 前端开发 Devops
【专栏】洞察.NET 技术在现代开发中的作用
【4月更文挑战第29天】本文探讨了.NET技术在现代软件开发中的核心价值、应用及挑战。.NET提供语言统一性与多样性,强大的Visual Studio工具,丰富的类库,跨平台能力及活跃的开发者社区。实际应用包括企业级应用、Web、移动、云服务和游戏开发。未来面临性能优化、容器化、AI集成等挑战,需持续创新。开发者应深入理解.NET,把握技术趋势,参与社区,共创美好未来。
|
2天前
|
机器学习/深度学习 人工智能 开发者
【专栏】.NET 技术:为开发带来新机遇
【4月更文挑战第29天】本文探讨了.NET技术如何为软件开发带来新机遇,分为三个部分:首先,.NET的跨平台革命,包括.NET Core的兴起、Xamarin与.NET MAUI的移动应用开发、开源社区的推动及性能优化;其次,介绍了云服务与微服务架构的集成,如Azure云服务、微服务支持、DevOps与CI/CD,以及Docker容器化;最后,讨论了AI与机器学习集成,如ML.NET、认知服务、TensorFlow和ONNX,使开发者能构建智能应用。面对这些机遇,开发者应不断学习和适应新技术,以创造更多价值。
|
2天前
|
算法 Java 编译器
【专栏】.NET 开发:实现高效能的秘诀
【4月更文挑战第29天】本文探讨了提升.NET应用性能的三个方面:理解.NET运行时(垃圾回收、JIT编译器、异步编程和线程并发)、优化代码与算法(代码细节、数据结构选择和算法效率)以及利用工具和框架(性能分析工具、高性能库和CI/CD流程)。通过深入学习、合理设计和有效工具,开发者可实现.NET应用的高效能。