不确定因素的自进化
为什么说是,不确定因素自进化呢?通过考试系统,一点一滴的走来,遇到的问题,从模糊到清晰,最终,发现,不是问题,太多,是我们认识太少。
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、用户接口
考试系统做到目前为止,发现系统中的不确定因素,都是用户给造成的,也就是说,没有代码解决不了的。既然是用户造成的,解铃还需系铃人,我们还把这个“未知”抛给用户,由用户来确定。
一般来说发现了不确定因素,说明编程中,我们已经意识到这个需求可能是需要变动的,不然不会有不确定因素。所以,不确定的因素发现的前提是:为了编程的灵活性,才考虑到了需求的变动。
那么我们该怎么抛给用户?
怎么抛?——写好接口,等着用户调用。
跟用户交流,确定好需求的,留出“用户接口”,当需求发生变化,我们可以根据“用户接口”来选择不同的实现方式。这样,通过用户接口,“不确定因素”,就不复存在了。
那上边问题来说:
我们增加一个用户界面:
如图:题型分值,题型顺序这些东西,是需要用户来确定的,跟我们没有关系,我们只需要把后台控制这些的代码做好。
有什么题型,怎么排序,都交给用户去决定,我们的“以为”毫无意义。