今天之前写的OPCTools算是正式在服务器上调试使用,并交付,在项目收尾的阶段,学到了一些说大不大说小不小的“程序员职业操守”=。=关于代码最后的规范化和一些优化(在代码能够成功运行并完成目标任务)工作。
自己总结了几点,看起来都是一些鸡毛蒜皮的小事,有的根本都不影响代码的功能运行,但是也是需要多注意的地方:
1.关于配置文件中的连接字符串
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="ConnectionString" value="server=localhost;port=****;user id=****;password=*********;persistsecurityinfo=True;database=*****"/>
<add key="ConStringEncrypt" value="true"/>
<add key="OPCService" value="**********"/>
</appSettings>
</configuration>
这个OPC项目里有两个appsetting,一个是数据库的连接字符串,一个是OPC名称的包含字符串。很多刚毕业的从业者(比如我0.O),都喜欢不用配置文件,直接在代码文件里定义字符串,然后使用,这样方便直观,而且这东西跟效率也没什么关系,确实如此。但是要考虑多种连接的情况,使用配置文件这样的思想,当你面对一个庞大、冗杂、多种连接共存,特别是与他人代码交互的情况,使用配置文件里的字符串是必要的,让你有一个清晰的思路,直接在cs文件里写,一个字,乱。
2.内存处理:
这里面涉及到内存释放、回收等。
比如在我这个项目里,大家都是知道,DataReader这个东西对于连接字符串是独占性的,如果是sql server数据库,可以对默认的字符串多重使用设置进行更改,也就是说加上MultipleActiveResultSets=True,但是因为mysql压根就不支持MutipleAciveResultSets这个属性,所以不行,我只好不停地打开关闭数据库,然后定义使用多个字符串。一到循环里面就要close()原来的连接,然后打开一个新的,这样才会保证不冲突报错。
还有一个点就是while(true)死循环的时候,因为项目要求每隔几秒钟就进行一次全表更新,所以要把update语句执行写在一个死循环里面,但是在死循环里,还存在这一个
string sqlAll = "select * from opc_items";
查询全表的语句,如果我一直使用死循环,那就是说我每一次都要select全表,这样对于内存非常不友好0.0
GC.Collect()方法,可以解决一部分的死循环内存浪费的问题,它的功能就是强制对所有代进行垃圾回收。代,是指托管内存中不同的区域,对象越老位于的代越靠后,比如,第一次垃圾回收后某个对象没有被回收,它就可能从0代移动到1代,以此类推。
顺便说一下关于内存垃圾,就是指没有任何的对象和它存在引用关系,就是说从这个对象开始找它的引用,一直找,如果找到了,那它就不是垃圾,如果一直在结束都没有找到,那就是垃圾,需要回收掉。其实一般来说垃圾回收都是会自动进行的,只有一些特殊情况,你需要把内存回收提前进行,在某个特殊需要的位置尽快回收垃圾,那么就使用以下GC.Collect()吧。
GC.WaitForPendingFinalizers()方法一般配合GC.Collect()使用,功能是挂起当前线程,直到处理终结器队列的线程清空该队列位置。
connUpdate.Close();
Console.WriteLine(currentTime+":更新数据完毕");
GC.Collect();
GC.WaitForPendingFinalizers();
Thread.Sleep(5000);
还有就是有一个点,就是关于select的时候,select count(1)和select *的效率区别。经常会有人说,count(1)肯定会比*快啊,因为select*是全表扫描
在数据库内部测试,不加where条件情况下,select count(*)和select count(1)效率相差不大,当然当数据庞大的到一定数量级的时候,count(1)会快很多。这其中其实还牵扯到主键的问题,如果没有设置主键,那么count(1)是比较快,有主键的情况下,它俩差不多,count(key)最快,如果你的表中只有一个字段的话,count(*)是最快的。
3.console.write();内容的规范和需求:
每一个输出都是客户需要看到的,要弄清楚你面对的对象,遣词造句要严谨、简介、明了,实时更新类的程序一定要在每一个输出语句之前都加上采集的时间:
System.DateTime currentTime = new DateTime();
currentTime = System.DateTime.Now;
告诉客户每一笔操作的实时时间,方便追踪。
4.项目以及代码名称规范:
首先是项目解决方案名称,命名规则,要按照企业要求。
细致一点的,就是代码里面的命名规则了,每一个变量的名称都要注意。比如我说在一个函数里有好几个sql语句要执行,每一个sql语句的功能不同,第一个是查询语句,第二个是插入语句,第三个是更新语句,第四个可能需要再查询一次,这个时候,不能是:string sql=""; string sql1="";这样的命名规则(用1234或者abcd等这样来区分同类变量名是不是戳中了大部分人),而是要根据你的功能和要用的到地方来明明,查询语句就用sqlselect,插入语句用sqlInsert,更新用sqlupdate这样的规则,其他的同理。要别人看了你代码,能一眼看出来什么东西,用在什么地方。
5.log日志文件:
这个是需要扩展的,日志文件可以记录运行情况,是一个后期需要追踪的文件。