不确定因素的自进化
为什么说是,不确定因素自进化呢?通过考试系统,一点一滴的走来,遇到的问题,从模糊到清晰,最终,发现,不是问题,太多,是我们认识太少。
1、配置文件
一般来说,试卷的题型顺序是保持不变的,可是,仅仅是一般,实际生活中,不要认为你以为的就是你以为,所以只要有可能,编程就得实现。
在测试阶段我们发现了一系列我们“以为的问题”:
例如:每套卷子/每个课程的题型顺序要怎么来确定?
试卷乱序,那些题型需要乱序?
简单讨论后,决定把顺序写到配置文件中,这样可以不用更改代码,于是乎,就这么做了。本着“程序猿”的拼劲,把一套一套试卷的顺序记录,一套套合并整理;然后是乱序题型和非乱序题型的记录,忙活着,可是心里却是闷闷不乐?
因为又一次犯错了,岁岁年年,课程的题型顺序变化是绝对的,难道我要每一次都修改配置文件吗?如果把这个考试系统给其他学校,估计考试的题型又会发生变化,难道,我要给他们去配置吗?
看着这些配置:
<!--每个题型的说明配置-->
<!--一般考试-->
<!--选择题-->
<add key="xuanzeti" value=" "/>
<!--多选题-->
<add key="duoxuanti" value=" "/>
<!--填图题-->
<add key="tiantuti" value=" "/>
<!--案例分析题-->
<add key="anlifenxi" value=" "/>
<!--简答题-->
<add key="jiandati" value=" "/>
<!--计算题-->
<add key="jisuanti" value=" "/>
<!--计算简答题-->
<add key="jisuanxuanzeti" value=" "/>
<!--论述题-->
<add key="lunshuti" value=" "/>
<!--名词解释题-->
<add key="mingcijieshi" value=" "/>
<!--判断题-->
<add key="panduanti" value=" "/>
<!--填空题-->
<add key="tiankongti" value=" "/>
还有后台读取配置的代码:
//读取配置文件 隐掉不用,不灵活
// #region 增加一列,并赋值,用来排序
// //if (!dt.Columns.Contains("QuestinoTypeOrder"))
// //{
// // dt.Columns.Add("QuestinoTypeOrder", typeof(int));
// //}
// else
// {
// // for (int intorder = 0; intorder < dt.Rows.Count; intorder++)
// // {
// // switch (dt.Rows[intorder]["QuestionTypeID"].ToString())
// // {
// // case "159":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["159"]);
// // break;
// // }
// // case "160":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["160"]);
// // break;
// // }
// // case "59":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["59"]);
// // break;
// // }
// // case "61":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["61"]);
// // break;
// // }
// // case "149":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["149"]);
// // break;
// // }
// // case "48":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["48"]);
// // break;
// // }
// // case "67":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["67"]);
// // break;
// // }
// // case "47":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["47"]);
// // break;
// // }
// // case "150":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["150"]);
// // break;
// // }
// // case "163":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["163"]);
// // break;
// // }
// // case "65":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["65"]);
// // break;
// // }
// // case "164":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["164"]);
// // break;
// // }
// // case "69":
// // {
// // dt.Rows[intorder]["QuestinoTypeOrder"] = int.Parse(System.Configuration.ConfigurationManager.AppSettings["69"]);
// // break;
// // }
// // }
// // }
// }
// #endregion
结论:配置文件是可以不编译就运行,但是不是什么东西都可以往里边搁,一定要慎重。
web.config顾名思义,是系统配置文件,而非“用户配置”文件,不要把跟业务有关的东西放到里。
SO,配置文件在这种情况下不适用。如果你还在配置文件中书写“大量的用户需求之类的东西”,那就赶快行动吧,如何行动?看用户接口。
2、用户接口
考试系统做到目前为止,发现系统中的不确定因素,都是用户给造成的,也就是说,没有代码解决不了的。既然是用户造成的,解铃还需系铃人,我们还把这个“未知”抛给用户,由用户来确定。
一般来说发现了不确定因素,说明编程中,我们已经意识到这个需求可能是需要变动的,不然不会有不确定因素。所以,不确定的因素发现的前提是:为了编程的灵活性,才考虑到了需求的变动。
那么我们该怎么抛给用户?
怎么抛?——写好接口,等着用户调用。
跟用户交流,确定好需求的,留出“用户接口”,当需求发生变化,我们可以根据“用户接口”来选择不同的实现方式。这样,通过用户接口,“不确定因素”,就不复存在了。
那上边问题来说:
我们增加一个用户界面:
如图:题型分值,题型顺序这些东西,是需要用户来确定的,跟我们没有关系,我们只需要把后台控制这些的代码做好。
有什么题型,怎么排序,都交给用户去决定,我们的“以为”毫无意义。