您的位置:首页 > 其它

由XmlDocument对象引起的思考,是否太过执着于面向对象而忘记了需求?

2011-01-16 20:17 330 查看
本人大四学生,断断续续学了1年的C#编程,只有很少的编程基础,之前又去跑实习,又去学Ajax。最近一周回归C#,开始认真学习面向对象和设计模式,可以说已经看得有点病态了,看见代码就想重构,结果写了又删删了又写,发现竟然写不出代码了,以前不懂什么面向对象,却能傻乎乎地写代码写得不亦乐乎。遂发篇文章,向诸位讨教一二。

先举个正在纠结的例子,当然不会涉及太多细节。

需求:在ASP.NET页面需要保存一些用户配置,在不同的页面间共享。例如是用户选择的字体,然后把这些变量保存在Session对象中。

实现很简单,直接访问Session对象

string Font=Session["Font"].ToString();//读取

Session["Font"]="宋体";//写入

但是Session对象在连接断开后就没了,于是需求变化了,希望能够持久地保存注册用户的配置信息,就用XML作为数据源吧,同时没有注册的用户继续使用Session

于是我们需要一个User类来进行验证,本例关注配置文件,其他细节不考虑,下面使用一点伪代码来表述

代码

public class Config
{    public string Font;//字体
public int Size;//文字大小
    public Config(string xmlFilePath){/*解释指定路径的xml,给字段Font和Size赋值*/}
public Config(object sessionObj){/*转换object为Config对象,给字段Font和Size赋值*/}
}
//代码调用
ASP页面PageLoad事件
{
Config config;
if(User.验证()==true)
{
config=new Config("C:\\config.xml");
}
else
{
config=new Config(Session["Config"]);
}
//使用设置好的config对象
}


这里把原来的ReadXXXConfig()改成了重载的构造方法,其实本菜一直搞不清楚构造方法重载和工厂模式有什么实际区别,有高手给我上一课的话感激不尽啊,总之这里用比较容易理解的。

通过重载构造方法,给予了Config类不同的实例化方式,省掉了一大堆Read神马Config(),看起来清爽多了,去掉了很多丑陋的代码。好了,现在肯定会有大牛们指出我的代码依然不够OO,如果数据源的种类增加,上面的if……else子句还是会不断膨胀,会不会真的有那么多种类的数据源另说,但是设计上的确还是欠缺考虑。

于是我应该添加一个Config的抽象类,让XmlConfig,SessionConfig继承它,然后再定义一个接口IReadable,里面有一个方法ReadConfig(),用这个接口从不同的Config子类中读取数据?这样会不会有设计过度的嫌疑呢?但如果不这样写是不是会设计不足?这就是本菜一直纠结的地方。不知道谁最开始流传的那么一句话,“如果if……else或者switch的分支超过3个,就该考虑用多态重构了”,但从需求出发,似乎不太可能有那么多数据源,撑死也不过三四种吧,是否需要为这个看起来不太复杂的分支语句进行重构呢?这样做if……else好像是消除了,但程序的逻辑不变,需要分支决策的地方还是得分支,否则独立的类之间零耦合度,拿什么实现逻辑呢?只是可能一连串的if……else被打散在不同的类中,或者将实现了多态的类交给客户端调用,使得代码看起来比较容易读懂。但是过分地抽象程序,继承层次太复杂,滥用接口,反而会适得其反,让程序更难读懂,甚至还不如分支语句清晰。我们抽象的时候又应该抽象到什么粒度?这些问题都深深地困扰着本菜呀。

如果坚持看到这里的朋友会发现,说了半天,LZ你的帖子跟XmlDocument这个对象有半毛钱关系?用过Xml编程的同学肯定不会对下面的代码不陌生吧:

XmlDocument xmlDoc = new XmlDocument();

//从文件路径加载一个XML文档
xmlDoc.Load("C:\\config.xml");

//从字符串加载一个XML文档
xmlDoc.LoadXml("<?xml version=‘1.0’?>……省略一堆");


两个Load方法都是用来载入XML文档,是不是觉得很眼熟?跟我上面写的ReadXmlConfig()和ReadSessionConfig()根本就是一样的嘛!

哈,微软的coder你也写渣代码!你也不懂面向对象!

且慢!微软真那么好忽悠,那连本菜都能当MVP了。

这就是在写配置文件时引发本菜思考的地方,于是我尝试着从合理角度来给微软的程序员开脱解释,从需求出发,XML文档还需要哪几种加载方式?呃,本菜搔破头,好像就是原来那两种了,数据库什么的,自己写个DB类去读啊。

Load和LoadXml两个方法的参数都是string类型,这也表示不能用重载Load方法()来构造两个不同的实例。如果加入一种XmlString类型来保存用字符串表示的XML文档,倒是可以重载,像这样

xmlDoc.Load("C:\\config.xml");

xmlDoc.Load(new XmlString("<?xml version=‘1.0’?>……省略一堆"));


但也略显麻烦了,这里微软的coder似乎选择了一种偷懒简洁的写法,虽然不是最优雅的写法,但很好理解,只有两种加载方法也不难区分。我这里该说微软的coder很好地把握了需求了么?

于是本菜马上又想到了,我是不是应该写一个Database类来操作数据库,再写一个Xml类来读写xml,这两个类再通过一个IDataSource接口来和Config类沟通,让数据层的差异对Config类透明呢?本菜已经心力交瘁,几近崩溃了。

码了这么多字,主要是写一写最近的学习体会,以及提出一些抑压已久的疑问,相信观点会有不少错误的地方,言辞有所偏颇,前言不搭后语。请不吝指教,多加斧正,本菜感激不尽。

最后,本人绝非用记事本写项目的大牛,网页文本框打的代码估计错漏甚多,引号分号漏掉无数,请多多包涵。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: