这个项目开发已经有近8个月了,这段时间里,对C#有了深入的了解。对ASP.net也是感悟很深。就对这个项目,记一些个人体会。
项目的开发环境,VS.net2003,ASP.net 1.1 加SQL Server 200。
1、解决方案的管理。
一般而言,一个大的解决方案都会分成几个小的项目。当然,一开始我不是很清楚。所以就一个Webb.WAVE项目,做为核心UI。后来又添加了一个Webb.WAVE.Countrol的逻辑层,当然,这个项目添加的比较早,所以它的内容也比较多。而后来又添加了几个项目。目前一共有5个项目在里面。
Webb.WAVE 核心UI
Webb.WAVE.Controls 核心逻辑
Webb.WAVE.Controls.Upload 上传组件,在我的博客上有关于这个组件的源代码
Webb.WAVE.Resource 资源项目
Webb.WAVE.WaveSystem 系统服务项目,主要是一些系统全局函数及Global等一些内容。
Webb.WAVE.WebService Web Service项目。
最开始只有前两个项目,数据库就先不在这里涉及。也就是简单的一个三层架构模式。然而开发到后来,越来越发现这样的架构不合理了。
首先就是UI层的用户认证与资源冲突问题。为了安全,UI层里的所有页面都是要认证的。所以,如果用户不登录,就不能访问任何页面(除Login.aspx页面以外)。刚开始这样的架构没有问题,因为没有考虑也其它的在非认证的情况下对网站的访问。然而接下来的一个简单问题就是系统管理员在什么情况下可以对系统进行恢复。也就是在系统出现问题,登录不起作用,或者系统要重新Reset的时候,要求在不登录的情况下访问系统。开始的解决方法是也在login.aspx页面里做。后来又有其它的功能也添加进去了,例如验证码的生成,不得不添加到login.aspx里。还有取回密码等功能。结果使得一个login.aspx做的很庞大了。
这样的做法显然错误了,为了方便,必须将它分解成几个小模块,使得一部份要求认证,一部份不要求认证,于是添加了一个WebService项目,这个项目不要求认证,但由于它集成在WAVE项目里,因此可以随时要求某个页面进行认证,这样就灵活了许多。
例如:一个文件列表的请求(XML文件),它可以在不登录的情况下请求,所以这个页面在WebService里,不要求认证。
而另一个TreeView节点数据的请求(XML数据岛),它要在登录的情况下请求,也放在WebService里,添加特别的认证,这样,在UI层上调用它的时候,必须是认证过的。方便又实际。
其次就是系统初始化的问题。因为系统还有一些服务,如发送邮件,清理资源等,必须在全局上设定一个线程让它来完成这样的工作。然而问题是,如果把它放在UI层上(Webb.WAVE)的global类里,确实可以很好的解决问题,然而,麻烦的是:每次小的改动,一点小的编译,都会使IIS重新加载整个Webb.WAVE.dll文件,从而使每次的调试变得很慢(一方面是文件的加载,另一方面是线程的停止以及重新运行)。于是我又把它分成了一个项目,这样,如果WaveSystem不编译的时候,IIS就不会重新加载它,也就不会停止系统服务,当然,你的其它调试也会很快。还有资源文件重新也做一个项目,这样也方便。
所以,尽可能合理的把一个项目分解成几个小的项目来管理,相互之间做到尽可能独立。因此,在分解项目的时候,要考虑的就是项目之间的引用要合理,千万不要分解后成了A引用B,B又要引用A,那就分解的不合理了。
2、第三方组件的使用。
这里主要是MS的WebControl的使用。对于这几个控件(TreeView,ToolBar,MultiPage和TabStrip),在项目里使用的最多的是TreeView,然而存在的一个问题是,它的数据结构,如果让它存在视图,这几乎是一个灾难性的后果!当数据节点达到上百个后,Page上的ViewStatus代码N多,几MB都有可能。所以后来直接放弃了它的数据结构,改成JS+WebService绑定。最后还发现,这几个控件如果想用好,客户端的脚本十分的重要!可以在MSDN上查找DHTML来解决一些问题。千万不要直接在服务器端使用他们,这样会使服务器与客户双方负担都成几何级数的增加。
3、充分利用数据库的功能
开始做的时候,一方面对SQL2K不熟悉,另方面为了与Access数据库兼容,我放弃了很多数据库功能,例如存储过程。大量的SQL语句都在逻辑层上。当时心想,这样管理逻辑层就可以很好的管理数据库了。因为这样对数据库就是透明的了。而且数据库的配置也很简单,除了数据表,什么都不要了。然而这样一来,就使我的逻辑层计算量快速的倍增。例如树的数据产生,删除及父子表关系等!如果在数据库里实现,这是很简单的,然而把它放在逻辑层上,只是多一点的计算,例如删除子表里的数据!看上去在逻辑层上也可以方便的完成,但带来的后果是,一方面你得多写上几十行的代码,这还是小事,数据库的来回访问又会添加服务器的负担。还有,这样对错误的机率也提高了。再例如,删除一条记录的时候,要做一个日志!如果在逻辑层上做,看上去是很合理也很方便,然而在实际的开发中,你会发现比在数据库里直接做日志麻烦至少10倍。因此,充分利用数据库功能!尽可能在数据层上把数据合理化,这样会使逻辑层方便许多,另一方面也会使UI层简单了。特别是父子表,深有体会!还有把它交给数据库吧!虽然.net一再推荐用DataSet可以用完成父子表关系,但该谁做的事,还是交给谁自己去做,不要越权。
4、充分利用UI层上的用户控件!
这样一个很好的功能。但请注意:如果只是表面上像设计UI一样,做一个控件,然后在PAGE上调用,那一点意义都没了。我要说的是,充分利用控件!首先,你要明白它是一个类,因此,类的一切属性都可以用到!例如你可以继承自己的UI控件,可以从原控件继承等。最主要的是,你可以自己在里面定义很多的事件。例如:一个页面上,可能要显示两个控件A和B,现在要求B上有一个BUTTON,点击后,B隐藏,A显示。看上去很简单,然而做起来还有点麻烦。因为你要在子控件B里调用页面的一些方法。因此,在B控件上添加一个事件是最合理的。这样你就可以随心所欲的处理各个控件之间的关系了。例如,我们可以对一个类做一个独立的控件,让它可以自己更新数据库,可以显示数据。你只用给它一个共有方法,LoadData(),传一个ID,它就自己加入数据,完了再加一个UpDateData(),最后加一个OnReturn来回调页面上的函数来隐藏或者从页面上删除它。利用这样的结构可以解决很多棘手的问题。
注意:充分利用控件的性质,充分利用.net的威力!
5、备份与日志管理
看上去简单,然而出现三个服务器,而且不同时更新的时候,你就麻烦了。特别是数据库的改动!做好日志吧,利用日志来管理它们是绝对正确的!做好更新日志,这样你可以方便快速的更新其它的服务器。备份的重要性就不用说了吧。请做一些永久的备份,特别是一些项目做大的改动的时候,例如分解项目的时候,或者发布测试版的时候。
6、测试
一般的功能测试就不说了,因为如果边功能都没有完成的项目不能算是完成了。最后还得进行一下正规的测试。当然有测试人员是最好了,用工具进行一些测试也是必要的。当然,我的项目压力测试是不合格的,这意味着一些核心模块要重新开发。而在开发的单元测试是,感觉还不错。千万不要和我有同样的想法,这是极度危险的!还是进行专业的测试吧。
一点个人体会。