2017年度工作总结

2017年度工作总结

使用“年度总结”这样的词汇似乎有些夸张,毕竟工作并没有一年的时间。姑且加着实习期的大半个月,满打满算不到八个月的时间。这篇总结沿时间线涉及期间内做过的所有技术方面遇到的问题和最终解决办法,但并不针对某一问题做详细展开说明。

五月

实习期。初来乍到,原本就对这一行业心生敬畏,终于有机会自己尝试。
从C语言开始,训练写代码的能力,先后完成了:
随机出10道两位数加减乘除分数运算的计算器,并返回正确结果及做对题目的个数;

  • 高精度除法;

  • 图形打印;

  • 打印万年历;
  • 读取csv文件;

题目看似功能单一,但其中涉及到的知识是非常多的,由浅入深,逐步接触C语言的指针,内存,堆,栈等核心功能。也因为功能单一,所以结果看起来尤为重要:只有一个功能,若是没有按时完成,相当于持续的工作输出成果为零,加之时间上的严格限制,10 min,20 min等等,难度也随之提升了。工作以项目为单位,有时间起止,花费成本,效率一定是第一位的。
在这个过程中,学习了代码书写规范,研究和应用如何以系统性的、规范化的、可定量的过程化方法去开发和维护软件。由于实现过程中对指针内存应用混乱,重新学习了指针和内存。接触面向对象语言之前,对C语言的理解停留在Console界面,简单地认为面向对象的语言比C语言高级,理由就是出现了类和对象,开发者能够轻易做到功能对象层复用,而C语言面向过程先具体逻辑细节,再抽象问题整体,只能做到方法层复用。现在回头来看,能更深刻地理解C语言在与操作系统交互时的便利,在解码内存方面功能的优势。夸张一点讲,“万物皆内存”,只要有权限获取到,便可以有多种方式操作。最震撼的便是在文件传输过程,例如以TCP/IP协议加头和去头,以达到双方对应协议层之间的数据交流,全部可以使用结构体完成,指定分配内存的大小,按协议重新解析,完成信息传输。
语言都仅仅是工具,了解当前实际需求,以解决好问题为目标,切勿盲目跟风。

七月

开始接触C#。C#是微软推出的一种基于.NET框架的、面向对象的高级编程语言。本科期间学习过VB,第一门面向对象的语言。从面向过程转向面向对象思想上是有较大的转变的。接触一门新的语言,总是习惯用原来的语言书写习惯书写现在的代码。于是对于我来讲,C#对于我而言,只需要找到类似于C语言程序的入口点,其余都是同样的面向过程即可。以实现功能为主,正规化是在不断实践深入了解的过程中完成的。一直以来,我认识问题总是喜欢系统化,从局部开始往外扩散,总觉得缺少点什么。突然之间发现新的没有了解过的功能,又会在新的功能上展开,于是发现了新大陆,再继续深入,不能自拔。这种“认识论”的问题在于,随着细节问题的不断深入,没有尽头,可能在某个深度之后对解决当前问题无益,已经不记得当初为什么要了解现在看到的这个知识了。就跟查网页一样,链接不断点下去,距离目标关键词越来越远这时候应该回到最初的关键词重新搜索。
也有尝试过读完一整套说明文档再去实践,但能联系起来的知识寥寥无几。大多数只是充当了混淆记忆的元凶罢了。也自知这样的学习方法有问题,所以也不断在纠正。
正式学习线程。多线程,使程序得以将其工作分开,独立运作,不互相影响。相比于之前写的程序,最直接的感受便是:程序调试再也不能F10了,程序并不是严格按照顺序执行的,多线程程序无法预期;执行次序无法保证,线程彼此之间的执行顺序应该视之为随机所以很严肃的线程安全问题,自然成为要考虑的主要问题。进一步学习Lock的用法,以完成Simon游戏中出题过程和答题过程可能同时操作按钮的事件冲突。
学习跨线程更新UI。跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建控件的线程访问它”的异常。所以借助委托,定义委托类型,定义线程的主体方法,定义更新UI控件的方法,使用控件的Invoke/BeginInvoke方法,将委托转到UI线程上调用,实现线程安全的更新。
学习使用Nuget中的CSVHelper库:不要重复造轮子。如果已经有前人实现过相同的功能,在可信度可复用的前提下,完全可以在此基础上开发,无需自己写。这里需要注意的是,这个复用的成本有多高,前一段时间闹得沸沸扬扬的facebook的React协议重新告诉人们在使用他人的代码之前,一定要了解清楚所使用的协议

协议

听闻正在使用React的同学讲,的确是很好用,弃用很难。这时候就要权衡利弊了。最好用的协议,当属MIT许可证。

八月

学习C#中的重要功能:反射。什么是反射:
在程序运行时,
动态获取加载程序集
动态获取类型(类,接口)
动态获取类型的成员信息(字段,属性,方法)
在运行时,
动态创建类型实例,以及调用和访问这些实例成员。
反射在功能独立,插件化开发中占有重要地位。
学习Log4Net的库,程序一旦部署后,就不大可能再利用专门的调试工具了。日志记录往往是软件开发周期中重要的组成部分,可供开发人员尽快找到应用程序中的bug,一旦在程序中加入了Log输出,程序在运行过程中就能生成并输出日志信息而无需人工干预。就目前开发的设备管理器而言,Log4Net还用的不大好,没有在安装更新卸载中将日志输出,以至调试还靠系统错误日志。

九月

尝试做网络文件传输。做了一个仿服务器客户端文件传输的实例,分别实现客户端和服务器的功能(两个程序),之间可实现文件传输,考虑断点续传和文件完整性校验。了解了传输协议,套接字以及读写文件,怎么发文件,怎么校验已接收文档的正确性。传数据的方式有很多,我选择了NetworkStream【同步】,一个线程可以一直写,另外一个线程可以一直读(当然,如果流里面没有数据自然不能读了),它们没有交叉打断的功能,只有在读的一方没有数据可读了,才会等待写的一方往流里面写数据。数据帧是以帧头+数据的方式传送的,所以绝不能允许一直往流里边写数据的情况,会造成取数据的紊乱,解析结果乱码的错误。因此,应该手动加入控制,客户端读完一句后再让服务端往里边写,手动同步该过程。注意区分,同时和同步是针对不同的对象描述的,二者不等价。最终以单线程同步完成传输。
期间也学习了SVN,一个托管代码的版本控制器,完成第一次PPT成果分享。学会的衡量指标是把一个完全不懂的人讲会。
开始逐渐向设备管理器过渡了。完成了简易版的任务管理器,这个真的是简易,需求:简易版任务管理器——进程和性能两个页面的部分内容。如同前面所言,功能听起来很简单,但背后隐藏的综合性是难以想象的,可以这么说,当时觉得这个很难,要解决Windows任务管理器中各个数据的来源问题,数据含义问题,到底是根据当前性能计算出来的呢?还是系统中提供了获取途径?起初没有搞清楚,在寻找数据上花费了好久。当时并没有了解过有先用C++读取系统数据,传给托管C++,再传给C#这种方法,而是直接利用C#调用windows API,也叫C#如何直接调用非托管代码,直接调用从 DLL 导出的函数:

  1. 使用 C# 关键字 static 和 extern 声明方法。
  2. 将 DllImport 属性附加到该方法。DllImport 属性允许指定包含该方法的 DLL 的名称。
  3. 如果需要,为方法的参数和返回值指定自定义封送处理信息,这将重写 .NET Framework 的默认封送处理。

十月

学习WPF——Windows Presentation Foundation。在学习WPF之前,学习了HTML+CSS的布局。WPF的核心就是绑定。所以对绑定的学习是必然的。起初是简单的单项绑定,在XAML中实现,比如,textbox和滚动条之间的数据绑定。绑定的好处在于设计和代码分离,更有利于团队合作开发,对代码的独立性要求也更高。现在写代码这方面做得还不好,功能不独立,函数不独立,复用性差,经常是一个函数内部实现多个功能。需要加强。用WPF做了一个简易版的计算器和仿QQ的登录界面,以熟悉Grid,stack等容器,其中仿QQ的登录界面中涉及到虚拟键盘,算是彻底将布局学了一遍。同样地,里边有很多新的概念没有了解过,但是功能方面学懂了就好。最重要的是学会了Template的使用,类似于html中的CSS,可以按需控制xaml中控件的样式。

十一月

学习使用DITA。最简单的陈述:结构化写作。一般用来写技术文档,解决了同一份资料由于需要不同输出格式而不得不重新写一遍源文件的问题。DITA仅仅是一种规范,需要有人来实现,不然就是废了的协议。实现它的最常用的就是一个开源命令行工具就是DITA-OT,内置支持很多输出格式:常见的,pdf,chm,html等等。
要学习DITA,就避不开ANT,自动化编译工具,功能很多,我们在这里用的就是组织文件将文件编译。ANT本身是用JAVA写的,天生对JAVA程序编译支持,其他的需要扩展,这里我们也可以看出,ANT的运行需要Java环境。ANT里边最常见的一个概念就是build.xml,即build文件,这个名字可以换。build文件中写明了需要执行的任务及顺序,即target,最小的执行块单位。
重新认识xml。Xml的功能大了去了,包括xaml都是xml的翻版。标记语言的典型代表。顺带着认识了Schema和dtd。XML Schema 的作用是定义 XML 文档的合法构建模块,类似 DTD。
最终做出使用帮助文档的试用DITA版。

十二月

开始做设备管理器。前边提到做任务管理器,有过调用windows API的经验,做起来会相对容易一些。不曾想有关设备的信息居然要以伪驱动的方法读取,这是在逐步追踪现有设备管理器的工作方式得出来的结论。但是这种方法是不安全的,微软并没有保证接口长时间有效开放,这就意味着,如果继续按照这个方式获取我们想要的数据,并不会持久,可能某一天微软的补丁升级就会导致软件无法使用。我们应该杜绝这样的不安全行为。在这个问题上纠结了很久,终于找到解决良方:依旧是在setup api中。
读取问题解决了,接着要解决插件加载的问题。这里的插件指的是,每一个硬件节点所支持的功能都应该由硬件厂商(虽然是我们自己)来完善,我们做的仅仅是支持加载该硬件,并可以使用字符串对硬件进行唯一识别,读写硬件。所以必须把硬件支持的功能插件化。这时候就用到了动态链接库和C#的反射。这部分在调试的时候需要改变项目属性,比如,生成后事件,附加目录,所需要的lib名称等等,避免由于dll引用错误出现的低级错误。

一月

设备管理器中左侧栏Treeview的Node应该是可以修改的,将修改结果与配置文件同步。同样,看似简单的需求简单的功能,背后的工作量可不小。首先,WPF并没有默认提供Treeview的节点可修改功能,需要自己实现。这时就需要用到Template,自定义节点处的控件。事实也证明,可修改节点是textblock和textbox的复合体,当需要编辑时,textbox的enable属性设置为true,并将textblock显示的文本与textbox绑定。一旦节点重命名便将该文本传递给textblock,对于用户而言,完成一次节点的重命名。太多时候,我们觉得很假的实现,事实上正规做法就是这样。大胆猜想,小心求证。软件开发同硬件开发还是有很大的区别的。软件开发中我们只要做了备份,什么都可以尝试,别害怕出错,只要能调试,终归是会找得到问题所在的。即便是多线程,也有它的调试方法。当然,随着代码量的增多,开发基本都是在已有基础上开发,很少从0开始写。我们应该先读懂功能,按模块调试而不是按行调试。二分法是不错的选择。
设备管理器的雏形大致完成,着手做安装程序。

二月

开始做安装程序。使用installshield。这是一款专门做安装程序的软件。我们使用的是2015 pro版。起初,要求不高时,我们可以按installshield wizard一步步操作。但是当我们有一些复杂功能时,比如要启动自己的服务,读写文件,调用dll,这时候就需要用到installscript,这是一种脚本语言。语法简单,但是工作流难掌握,比如,到目前为止,并不清楚如何才能正确终止它必须走完的安装流程。脚本语言不涉及多线程问题,但即使我们把脚本中的代码全部删光,依旧会一步步安装完成,这部分功能写在哪儿?能否改变?这是没有搞清楚的问题。关于installshield update,包含major update和minor update,几番周折之后,终于完成了升级包的制作。最后便是卸载了。存留的问题便是如何正确阻止在完全删除文件后卸载程序对文件的恢复,如何正确妥当地退出后续恢复。
接下来的工作便是要将代码整理,实现分层接口。

总结

总的来看,在工作中,我学到了很多技术上的知识,也发现了自己距离标准化工作之间还有差距,存在很多亟待解决的问题。时间很快,不能用时间弥补效率。工作习惯和工作思维的不成熟,也是我以后要在工作中不断磨练和提高自己的地方。所以接下来的日子里,进一步提高工作效率,注意工作优先级划分,注重实效、注重结果,一切工作围绕着目标的完成。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值