软件开发述职报告(共4篇)
第1篇:软件开发述职报告
软件开发述职报告
软件开发述职报告
本人于xxx年x月份加入xxx发展有限公司,入职后在工程部工作,任土建工程师,作为一名加入公司的新人,最重要的就是要在最短的时间内度过“适应期”,尽快适应工作环境,快速转换角色。
一、新的岗位,新的挑战
来到公司的第一天,给我最大的感受就是公司的规范化的管理,不光体现在工作中,同时在企业形象、个人形象中同样能够得到体现。土建工程师是一个对实际工作经验要求很高的职位,而我正是在这方面有所欠缺,我将通过工作中锻炼自己、提高自己、塑造自己。这种学习是一种见机行事,是让自己适应工作中的知识技能,使自我希望通过学习能增强自己的竞争力,同时也增强公司的竞争力。
二、规范自己的言行,做合格的职员
在工程部工作,免不了要与上下左右及社会各界联系,我将始终牢记自己是公司的一员,言行举止都注重约束自己。对各级领导,做到谦虚谨慎,尊重服从。但是服从并不代表盲从,对于有利于项目的开展的合理的意见也要及时的反馈给领导,做事大胆,不避讳上下层的关系,真正做到对工程负责,对公司负责,要把自己真正的当成公司的主人。
三、加强学习,提高现场工程管理水平
在对施工单位的管理上,以合同、规范为依据,按照《工程管理手册》向施工单位灌输我公司的管理方法和理念,立好规矩,制定好标准,树质量、安全文明标兵从而带动后进的单位,同时增强服务意识,进行充分的沟通、协调是做好对施工单位管理的基础。
对监理公司的管理,首先应充分支持监理的工作,其次要检查、督促、指导监理的工作,对待监理日常工作不到位的地方及时指出,在对施工单位的管理上有时可借助监理的力量,往往可以取得良好的效果。
在工程协调上坚持以合同为依据,站在公司利益的立场上处理事情,坚持原则,但又要有一定的灵活性,协调的目的是保证工程进度更快,质量更好更有保证,造价最低,整体效果最好。
在三控两管上,做到有计划有跟踪有落实,紧盯合同目标制定关键控制节点,在总体进度计划的基础上把计划分解到每季、月、周,制定相应的考核制度;质量控制做到事前、事中、事后控制,关键是过程控制;投资控制上严格审查各种签证和变更资料,确认其合理性、必要性,避免增量多报和减量漏报;在合同管理上,充分熟悉合同条款,落实合同条款的执行情况,严格按照合同执行;在信息管理上做到规范、系统、统
一、有条理。
四、尽心履职,全心全意当好称职的土建工程师
作为工程部的一名土建工程师,我的理解,没有什么谋求利益和享受待遇的权力,只有承担责任、带头工作的义务。在平时的工作中,对领导交办的工作,从不讨价还价,保质保量完成;对自己分内的工作也能积极对待,努力完成,做到既不越位,又要到位,更不失职。在同办公室其他几位同事的工作协调上,做到真诚相待,互帮互学。
最后,我想说的是,我需要做到的就是成为一个优秀的员工。
软件开发述职报告
通过一年学习实践,在以下技能上面有了较大进步:
1)对研发、生产各项环节的更清晰认识。经过2x2 Triplexer、ECAN CNU、ECAN CLT几个案子的历练,增进了对设计预研,设计验证,设计导入生产等环节的熟悉程度;同时,更多参与与各部门间的交流,沟通能力得到锻炼,增加了处理各种问题的经验。对产品的研发历程和成本产生等有了一个比较完整的认识。
2)对网络的更深认识。年初花了不少时间对Triple play相关技术的规格,以及实现方案做了很多调研工作。在实现方案调研过程中,查漏补缺,让我对网络的认识更加的完善。硬件上主要有,对OSI七层网络结构模型的更深认识,对PON网络结构有较清晰了解,Ethernet产品的一般实现方案有较深了解,知道了一些路由及交换产品的一般实现方案,还了解到VoIP产品的构成及实现方案等等;软件上主要有,对Linux系统的更深认识,对SIP协议的细节认识,对Router软件实现的认识的加深,以及SIP服务器的移植、使用等。
3)对产品可靠度设计的更深刻认识。包括de-rating,ESD,Hi-pot等设计考虑的深入学习。
4)对硬件基本调试方法的更深刻认识。包括使用万用表,示波器,网络分析仪等设备对产品各参数的测量,并bug shooting等。5)一些基本的PCB Layout常识学习。对如Signal Integrity,Designe For Manufacturing,PCB Fabrication,PCB过流能力考虑等等,都有了一个初步的认识。
6)对一些元件的更认可认识。在制作采规及元件选用时,及时对各种器件的基本知识做了整理,对电阻、电容、二极管、Power IC等元件有了更加全面的认识。
硬件方面:
1)学习硬件调试、维修。增加数字电路调试经验,单片机常用外围单元调试、设计经验等。
2)继续完善各种元件的基本知识。
3)增加PCB Layout经验
Linux编程方面:
4)Linux Makefile编程、及shell编程继续学习,以提高工作效率。
5)Linux应用编程继续练习。争取明年一年能熟练Linux应用编程!
6)继续熟悉Linux系统,可简单进行移植,裁剪,驱动编程。
以上,结合公司project,重点进行强化。
嵌入式技术应用广泛,比如,可作为设备的控制模块,CATV编解码终端中的应用,各种网络设备中的核心控制器模块。嵌入式技术在增加产品附加价值,如易用性、界面友好性等方面表现突出;同时,嵌入式技术又可以快速集成现有技术,IC,或IP以形成新产品,来满足市场需求。
综合公司业务范围,嵌入式技术优势,以及个人所学专业知识,未来2~3年内,定位为嵌入式工程师,努力学习相关知识。
第2篇:软件开发的述职报告
软件开发的述职报告
篇1:一位软件工程师6年的工作总结 “又是一年毕业时”,看到一批批学子离开人生的象牙塔,走上各自的工作岗位;想想自己也曾经意气风发、踌躇满志,不觉感叹万千……本文是自己工作6年的经历沉淀或者经验提炼,希望对所有的软件工程师们有所帮助,早日实现自己的人生目标。”所以放在每一条,让刚刚毕业的朋友们早点看到哈!2、一定要确定自己的发展方向,并为此目的制定可行的计划。”。在技术型团队中,技术与人品同等重要,当然长相也比较重要哈,尤其在MM比较多的团队中。”四分五裂、各奔东西。本人自毕业以来,平均每天实际学习时间超过2小时。我买的那些家伙出的书,!00%全部后悔了,无一本例外。7、在一种语言上编程,但别为其束缚了思想。“代码大全”中说:“深入一门语言编程,不要浮于表面”。深入一门语言开发还远远不足,任何编程语言的存在都有其自身的理由,所以也没有哪门语言是“包治百病”的“灵丹妙药”。编程语言对开发人员解决具体问题的思路和方式的影响与束缚的例子俯拾皆是。我的经验是:用面对对象工具开发某些关键模块时,为什么不可以借鉴
C、C51、汇编的模块化封装方式?用传统的桌面开发工具(目前主要有VC++、Delphi)进行系统体统结构设计时,为什么不可以参考来自Java社区的IoC、AOP设计思想,甚至借。
1欢迎下载
鉴像Spring、Hibernate、JBo等等优秀的开源框架?在进行类似于实时通信、数据采集等功能的设计、实现时,为什么不可以引用来自实时系统、嵌入式系统的优秀的体系框架与模式?为什么一切都必须以个人、团队在当然开发语言上的传统或者经验来解决问题???“他山之石、可以攻玉”。
8、养成总结与反思的习惯,并有意识地提炼日常工作成果,形成自己的个人源码库、解决某类问题的通用系统体系结构、甚至进化为框架。众所周知,对软件开发人员而言,有、无经验的一个显著区别是:无经验者完成任何任务时都从头开始,而有经验者往往通过重组自己的可复用模块、类库来解决问题(其实这个结论不应该被局限在软件开发领域、可以延伸到很多方面)。这并不是说,所有可复用的东西都必须自己实现,别人成熟的通过测试的成果也可以收集、整理、集成到自己的知识库中。但是,最好还是自己实现,这样没有知识产权、版权等问题,关键是自己实现后能真正掌握这个知识点,拥有这个技能。
9、理论与实践并重,内外双修。工程师的内涵是:以工程师的眼光观察、分析事物和世界。一个合格的软件工程师,是真正理解了软件产品的本质及软件产品研发的思想精髓的人(个人观点、欢迎探讨)。掌握软件开发语言、应用语言工具解决工作中的具体问题、完成目标任务是软件工程师。
2欢迎下载的主要工作,但从软件工程师这个角度来看,这只是外在的东西,并非重要的、本质的工作。学习、掌握软件产品开发理论知识、软件开发方法论,并在实践中理解、应用软件产品的分析、设计、实现思想来解决具体的软件产品研发问题,才是真正的软件工程师的工作。站在成熟理论与可靠方法论的高度思考、分析、解决问题,并在具体实践中验证和修正这些思想与方式,最终形成自己的理论体系和实用方法论。10、心态有多开放,视野就有多开阔。不要抱着自己的技术和成果,等到它们都已经过时变成垃圾了,才拿出来丢人现眼。请及时发布自己的研究成果:开发的产品、有创意的设计或代码,公布出来让大家交流或者使用,你的成果才有进化和升华的机会。想想自己2000年间开发的那些Windows系统工具,5、6年之后的今天,还是那个样子,今天流行的好多Windows系统工具都比自己的晚,但进化得很好,且有那么多用户在使用。并且,不要保守自己的技术和思想,尽可能地与人交流与分享,或者传授给开发团队的成员。“与人交换苹果之后,每个人还是只有一个苹果;但交换思想之后,每个人都拥有两种思想”,道理大家都懂,但有多少人真正能做到呢?
11、尽量参加开源项目的开发、或者与朋友共同研制一些自己的产品,千万不要因为没有钱赚而不做。网络早已不再只是“虚拟世界”,网上有很多的开源项目、合作开发项目、。
3欢迎下载
外包项目,这都是涉猎工作以外的知识的绝好机会,并且能够结识更广的人缘。不要因为工作是做ERP,就不去学习和了解嵌入式、实时、通信、网络等方面的技术,反过来也是一样。如果当他别人拿着合同找你合作,你却这也不会,那也不熟时,你将后悔莫及。
12、书到用时方恨少,不要将自己的知识面仅仅局限于技术方面。诺贝尔经济学奖得主西蒙教授的研究结果表明: “对于一个有一定基础的人来说,他只要真正肯下功夫,在6个月内就可以掌握任何一门学问。”教育心理学界为感谢西蒙教授的研究成果,故命名为西蒙学习法。可见,掌握一门陌生的学问远远没有想想的那么高难、深奥。多方吸取、广泛涉猎。极力夯实自己的影响圈、尽量扩大自己的关注圈。财务、经济、税务、管理等等知识,有空花时间看看,韬光养晦、未雨绸缪。13、本文的总结与反思:
A:不要去做技术上的高手,除非你的目标如此。虽然本文是关于提高软件开发知识的建议,做技术的高手是我一向都不赞同的。你可以提高自己的专业知识,但能胜任工作即止。
B:提高软件知识和技术只是问题的表面,本质是要提高自己认识问题、分析问题、解决问题的思想高度。软件专业知识的很多方法和原理,可以很容易地延伸、应用到生活的。
4欢迎下载
其它方面。C:在能胜任工作的基础上,立即去涉猎其它领域的专业知识,丰富自己的知识体系、提高自己的综合素质,尤其是那些目标不在技术方面的朋友
篇2:软件工程师述职报告 作为刚从学校出来的应届毕业生,第一份工作就落在智通,来到智通,深深地被这个企业的文化所感染,我很认同智通的企业文化,智通的企业精神“统一,专一,事业第一”体现出了这一行业优秀企业文化的特点。在这三个月的学习与亲身感受之下,我更加坚定地要使自己成为一名合格并争取优秀的智通人,我对自己有信心,对智通更有信心。
作为一名在技术岗位的职员,要具备一定的专业知识,不断地充实自己,在不断的工作学习与研究中成长,要有很好的团队协作精神,有很强的执行力,能真正为企业做实事。在智通上班的三个月里,我主要完成了以下工作项目:
一、刚来的两个星期,由于目前网站工作的需要,师傅指导一边熟悉工作职位环境一边学习asp,用了两个星期系统地学习了这门从未接触过的asp语言,为接下来一个月的工作打了坚实的基础。
二、接下来的时间,主要配合网站先前asp的后台管理系统进行某些功能优化与系统维护工作。先后完成了销售管理模块的最新注册企业查询、职业推荐给求职者、把求职者推荐给企业、会员职位刷新、职位刷新统计等几个模块的功。
5欢迎下载
能修改与优化,解决了业务员带权限控制的查询、推荐时间的控制与查询速度优化、企业职位刷新时的权限控制与企业职位时效性的控制以及完成对各销售组成员的职位数统计,职位刷新数统计的功能设计。在完成这些各种功能需求的时候,对后台管理系统进行了深入的分析研究,因此对销售管理模块非常熟悉,给目前网站新版开发的后台设计提了不少建设性的想法。之后还完成了logo管理模块中的投票项目添加优化与投票结果统计查询修正、logo、banner的管理与文本文件的生成。还完成了客服管理模块中后台开通资料查询的改进,企业管理、个人管理模块查询功能的改进。期间还完成了部分功能错误的修正,如校园招聘管理图片不能上传、文章类别不能修改、文章不能删除等。
三、目前新版是用jsp开发的,在这三个月里,我进一步对java,jsp的深入学习,了解了mvc模式开发,在这阶段的学习期间,我以一个小商务系统的开发作为学习任务。还对当前流行的jive代码与开发思想进行了初步的学习研究。
四、作为一名系统开发与维护工作者,当然不能忽视对数据库知识的学习,在这段时间我也进一步对sql语句进行了深入的学习,对sql语句的查询进行了分析,比较重视数据库性能分析与调整这方面的知识学习。通过这阶段的学习,把这些知识与方法运用到了对后台管理系统会员查询的。
6欢迎下载
速度优化功能上,在实际工作中得以实践运用。
五、网站新版开发方面,主要还为新版做了几个数据库对照表。
六、还参加了网站新版的第二轮测试工作,主要以后台管理系统为主做测试,还参与了前台个人管理与企业管理的流程测试,测出了不少关键性的bug。
七、入职以来,还担任了网站部群发邮件的工作。三个月内完成了好几批邮件群发的工作,每天定时定量地给在无忧无虑网站上注册的企业或会员群发几十万封邮件。还配合客服部群发了两批特殊活动的邮件,配合网站营销活动群发了两批群件,每天坚持固定给注册会员群发。
在网站技术部工作的三个月里,自己感受非常多。首先,作为刚从学校出来的毕业生,在实际开发中的经验尚不够成熟,还需要在工作中不断的提升自己。其次,要进一步提高自己的开发技能,使自己的技能满足今后的需求,主动获取并学习当今最新技术信息,平衡自己的知识结构,在不断的学习中提高自己。然后,要加强与同事们的沟通,融入团队,互相学习、相互提高,在团队中不断完善自己。
我相信,通过我的努力,一定能成为智通的优秀员工,一定会在优秀成绩之上提升自己。同时我希望公司能根据情况给我培训深造的机会,也希望部门内能有经常性的专业技术学习。
7欢迎下载
在此,我要感谢我的师傅吴长锦对我的指导,感谢李经理、范主管以及网站部的同事们对我的关心与帮助,感谢公司提供我发挥自己才能的机会。
篇3:软件开发人员工作总结 金秋十月是个收获季节,希望我们每一天的生活都如这个季节一样,又一个月过去了,现对工作中收获与不足总结
一、工作内容
九月份的工作比较繁忙,工作重点有四方面:s6测试,医院软件开发、测试,售后服务,文档书写及培训。1、关于s6测试
s6的新增修改功能大约30多项内容,测试的重点如:其一,每日结账时更正库存的操作,此项功能涉及的方面比较多,影响数据的准确性,测试起来比较烦琐、测试量也比较大;其二,由于业务开票时程序内部处理发生了改变,由原来的控制台转移到存储过程中处理,所以对此部分也进行了重点测试;其三,饮片划价自动批号的测试;其它方面的测试包括,gsp报表、客户对应商品销售、批次会员录入以及远程配送价格等的测试,再有就是售后人员随时提出的问题随时测试,如打印模块加完打印项还是不能打印、某些模板在99pbl修改以后还是不好用、哪个报表数据是否有问题等。2、医院软件开发、测试
对于新版医院软件的功能模块开发工作也做出了一点贡。
8欢迎下载
献,作了15个打印模块(如入库重打、划价重打、盈损重打等),12个查询模块(入库报表查询、住院报表查询、入出院费用查询等),所做模块包含的内容为:菜单挂接、将窗口中不需要的按钮隐藏、书写查询报表中所需要的sql语句(大约60句,但语句结构并不复杂)、打印模块及查询模块所需的数据窗口大约80个;测试方面,现在只是进行了表面性的测试,测试的内容包括每个窗口中的字体是否一致、按钮是否对齐、点击按钮后弹出的提示是否正确、开票窗口的金额、价格、数量、库存等的变
化情况是否正确,焦点移动问题等,现已测出的问题100多个;其它方面,修改了库结构,将每个的表中将不允许为空的字段修改正确以及将a25、a35等字段在每个表的长度统一等。3、售后服务
s6的售后工作,由于每日结账时更正库存,造成几个客户的库存数据不准确,通过查询客户实际的数据库找到了问题的原因,再有就是在电话中为售后人员解答一些问题;其它方面,上门服务三次,分别是,解决了先知医疗器械公司的应收应付财务问题,通胜医药财务软件中辅助核算的客户查不到,从后台修改数据已解决问题,汉华林销售出错库存未减,原因未查到;远程及电话解决客户提出的财务软件、财务接口、金税接口等问题。由于十一休息,售后人员少,在。
9欢迎下载
月末休息前做了两天售后工作。4、其它方面
s6的培训文档写了两次,其次就是书写了加强版与s6的区别,再有就是编译序程、备份程序、程序注册等工作,其中程序注册是随时性,所以也占用一定的时间。
二、工作分析
通过的工作,自己在pb方面又懂得了一些知识,并且可以修改简单的错误,也可看明白一些简单的脚本结构,这对于我的测试工作是很有帮助的。从反馈的情况看,s6的结账库存更正功能还存问题,还需要加强测试。再有从售后服务的情况看,售后人员在财务方面的技术还需要加强。
三、工作计划 1、医院软件测试
2、书写医院软件的说明书 3、s6新增、修改功能的测试
总结人:姜波
日期:2007-09-28。
10欢迎下载
第3篇:软件开发报告
负载均衡器软件
开发报告
院系: 班级: 成员:
目录
1.可行性分析报告..........................................................................................................................1 1.1 项目背景..............................................................................................................................1 1.2产品分析...............................................................................................................................1 1.3 结论意见..............................................................................................................................2 2.项目开发计划..............................................................................................................................2 2.1 总体功能要求......................................................................................................................2 2.2 软件开发平台要求..............................................................................................................2 2.3 软件项目的开发实施过程管理要求...................................................................................2 3.软件开发......................................................................................................................................2 3.1 软件的需求分析..............................................................................................................3 3.3软件的详细设计...................................................................................................................4 3.4 软件的编码..........................................................................................................................5 3.5软件的测试.........................................................................................................................31 3.5.1测试计划.....................................................................................................................31 3.5.2 软件测试....................................................................................................................31 4.项目开发总结报告....................................................................................................................32
I
1.可行性分析报告
1.1 项目背景
面对庞大的数据流量,面对集中性的访问,是不是觉得网络服务器岌岌可危呢?不用怕,负载均衡器就能帮你缓解这个问题。负载均衡器通过虚拟IP地址方法,解决了轮流排程所面临的许多问题。使用了负载均衡器集群系统,在外部看来,像是具有一个IP地址的单一服务器一样,当然,这个IP地址是虚拟的,它映射了集群中的每一台机器的地址。所以,在某种程度上,负载均衡器是将整个集群的IP地址报漏给外部网络。
当请求到达负载均衡器时,它会重写该请求的头文件,并将之指定到集群中的机器上。如果某台机器被从集群中移除了,请求不会别发往已经不存在的服务器上,因为所有的机器表面上都具有同一个IP地址,即使集群中的某个节点被移除了,该地址也不会发生变化。而且,internet上缓存的DNS条目也不再是问题了。当返回一个应答时,客户端看到的只是从负载均衡器上所返回的结果。也就是说,客户端操作的对象是负载均衡器,对于其更后端的操作,对客户端来讲,是完全透明的。
1.2产品分析
服务器一致性负载均衡器读取客户端发出的每一个请求中所包含的cookies或url解释。基于所读出的这些信息,负载均衡器就可以重写报头并将请求发往集群中合适的节点上,该节点维护着相应客户端请求的会话信息。在HTTP通信中,负载均衡器可以提供服务器一致性,但并不是通过一个安全的途径(例如:HTTPS)来提供这种服务。当消息被加密后(SSL),负载均衡器就不能读出隐藏在其中的会话信息。
通过故障恢复机制获得高可靠性故障恢复发生在当集群中某个节点不能处理请求,需将请求重新导向到其他节点时。主要有两种故障恢复:
请求级故障恢复。当集群中的一个节点不能处理请求时(通常是由于down机),请求被发送到其他节点。当然,在导向到其他节点的同时,保存在原节点上的会话信息将会丢失。
透明会话故障恢复。当一个引用失败后,负载均衡器会将之发送到集群中其他的节点上,以完成操作,这一点对用户来说是透明的。由于透明会话故障恢复需要节点具备相应的操作信息,因此为了实现该功能,集群中的所有节点必须具有公共存储区域或通用数据库,存储会话信息数据,以提供每个节点在进行单独进程会话故障恢复时所需要的操作信息。
既然所有的Web应用请求都必须经过负载均衡系统,那么系统就可以确定活动会话的数量,在任何实例访问中的活动会话的数目,应答的次数,高峰负载
次数,以及在高峰期和低谷期的会话的数目,还有其他更多的。所有的这些统计信息都可以被很好的用来调整整个系统的性能。
1.3 结论意见
虽然此项目存在一定的技术难度和风险,但我们对项目要达到的目标十分清楚,对所要开发系统将要实现的功能也非常了解。而且有一些成品作为参考,并且在项目的实施过程中我们能够获得帮助,我认为只要我们能够认真思考、仔细规划、明确分工,我们可以承担此项目的开发。
2.项目开发计划
2.1 总体功能要求
1.扩展网络设备和服务器的带宽 2.增加吞吐量
3.加强网络数据处理能力 4.提高网络的灵活性和可用性
2.2 软件开发平台要求
Visual c++ 6.0 SQL Server 2008 C++ Builder 网络架构:
完全支持TCP/IP协议
2.3 软件项目的开发实施过程管理要求
3.软件开发
3.1 软件的需求分析
1.DNS负载均衡最早的负载均衡技术是通过DNS来实现的,在DNS中为多个地址配置同一个名字,因而查询这个名字的客户机将得到其中一个地址,从而使得不同的客户访问不同的服务器,达到负载均衡的目的。DNS负载均衡是一种简单而有效的方法,但是它不能区分服务器的差异,也不能反映服务器的当前运行状态。
2.代理服务器负载均衡 使用代理服务器,可以将请求转发给内部的服务器,使用这种加速模式显然可以提升静态网页的访问速度。然而,也可以考虑这样一种技术,使用代理服务器将请求均匀转发给多台服务器,从而达到负载均衡的目的。
3.地址转换网关负载均衡 支持负载均衡的地址转换网关,可以将一个外部IP地址映射为多个内部IP地址,对每次TCP连接请求动态使用其中一个内部地址,达到负载均衡的目的。
4.协议内部支持负载均衡除了这三种负载均衡方式之外,有的协议内部支持与负载均衡相关的功能,例如HTTP协议中的重定向能力等,HTTP运行于TCP连接的最高层。
5.NAT负载均衡NAT简单地说就是将一个IP地址转换为另一个IP地址,一般用于未经注册的内部地址与合法的、已获注册的Internet IP地址间进行转换。适用于解决Internet IP地址紧张、不想让网络外部知道内部网络结构等的场合下。
6.反向代理负载均衡普通代理方式是代理内部网络用户访问internet上服务器的连接请求,客户端必须指定代理服务器,并将本来要直接发送到internet上服务器的连接请求发送给代理服务器处理。反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。反向代理负载均衡技术是把将来自internet上的连接请求以反向代理的方式动态地转发给内部网络上的多台服务器进行处理,从而达到负载均衡的目的。
7.混合型负载均衡在有些大型网络,由于多个服务器群内硬件设备、各自的规模、提供的服务等的差异,可以考虑给每个服务器群采用最合适的负载均衡方式,然后又在这多个服务器群间再一次负载均衡或群集起来以一个整体向外界提供服务(即把这多个服务器群当做一个新的服务器群),从而达到最佳的性能。将这种方式称之为混合型负载均衡。此种方式有时也用于单台均衡设备的性能不能满足大量连接请求的情况下。
3.2软件的概要设计
软件负载均衡解决方案是指在一台或多台服务器相应的操作系统上安装一
个或多个附加软件来实现负载均衡,DNSLoadBalanceCheckPointFirewall-1 ConnectControl等,它的优点是基于特定环境,配置简单,使用灵活,成本低廉,可以满足一般的负载均衡需求。硬件负载均衡解决方案是直接在服务器和外部网络间安装负载均衡设备,这种设备通常称之为负载均衡器,由于专门的设备完成专门的任务,独立于操作系统,整体性能得到大量提高,加上多样化的负载均衡策略,智能化的流量管理,可达到最佳的负载均衡需求。
一般而言,硬件负载均衡在功能、性能上优于软件方式,不过成本昂贵。本地负载均衡能有效地解决数据流量过大、网络负荷过重的问题,并且不需花费昂贵开支购置性能卓越的服务器,充分利用现有设备,避免服务器单点故障造成数据流量的损失。其有灵活多样的均衡策略把数据流量合理地分配给服务器群内的服务器共同负担。即使是再给现有服务器扩充升级,也只是简单地增加一个新的服务器到服务群中,而不需改变现有网络结构、停止现有的服务。
全局负载均衡主要用于在一个多区域拥有自己服务器的站点,为了使全球用户只以一个IP地址或域名就能访问到离自己最近的服务器,从而获得最快的访问速度,也可用于子公司分散站点分布广的大公司通过企业内部互联网来达到资源统一合理分配的目的。
3.3软件的详细设计
1.轮转法:轮转算法是所有调度算法中最简单也最容易实现的一种方法。在一个任务队列里,队列的每个成员(节点)都具有相同的地位,轮转法简单的在这组成员中顺序轮转选择。在负载平衡环境中,均衡器将新的请求轮流发给节点队列中的下一节点,如此连续、周而复始,每个集群的节点都在相等的地位下被轮流选择。这个算法在DNS域名轮询中被广泛使用。
轮转法的活动是可预知的,每个节点被选择的机会是1/N,因此很容易计算出节点的负载分布。轮转法典型的适用于集群中所有节点的处理能力和性能均相同的情况,在实际应用中,一般将它与其他简单方法联合使用时比较有效。
2.散列法:散列法也叫哈希法(HASH),通过单射不可逆的HASH函数,按照某种规则将网络请求发往集群节点。哈希法在其他几类平衡算法不是很有效时会显示出特别的威力。例如,在前面提到的UDP会话的情况下,由于轮转法和其他几类基于连接信息的算法,无法识别出会话的起止标记,会引起应用混乱。
而采取基于数据包源地址的哈希映射可以在一定程度上解决这个问题:将具有相同源地址的数据包发给同一服务器节点,这使得基于高层会话的事务可以以适当的方式运行。相对称的是,基于目的地址的哈希调度算法可以用在Web Cache集群中,指向同一个目标站点的访问请求都被负载平衡器发送到同一个Cache服务节点上,以避免页面缺失而带来的更新Cache问题。
3.最少连接法:在最少连接法中,平衡器纪录目前所有活跃连接,把下一个新的请求发给当前含有最少连接数的节点。这种算法针对TCP连接进行,但由于
不同应用对系统资源的消耗可能差异很大,而连接数无法反映出真实的应用负载,因此在使用重型Web服务器作为集群节点服务时(例如Apache服务器),该算法在平衡负载的效果上要打个折扣。为了减少这个不利的影响,可以对每个节点设置最大的连接数上限(通过阈值设定体现)。
4.最低缺失法:在最低缺失法中,平衡器长期纪录到各节点的请求情况,把下个请求发给历史上处理请求最少的节点。与最少连接法不同的是,最低缺失记录过去的连接数而不是当前的连接数。
5.最快响应法:平衡器记录自身到每一个集群节点的网络响应时间,并将下一个到达的连接请求分配给响应时间最短的节点,这种方法要求使用ICMP包或基于UDP包的专用技术来主动探测各节点。
在大多数基于LAN的集群中,最快响应算法工作的并不是很好,因为LAN中的ICMP包基本上都在10ms内完成回应,体现不出节点之间的差异;如果在 WAN上进行平衡的话,响应时间对于用户就近选择服务器而言还是具有现实意义的;而且集群的拓扑越分散这种方法越能体现出效果来。这种方法是高级平衡基于拓扑结构重定向用到的主要方法。
6.加权法:加权方法只能与其他方法合用,是它们的一个很好的补充。加权算法根据节点的优先级或当前的负载状况(即权值)来构成负载平衡的多优先级队列,队列中的每个等待处理的连接都具有相同处理等级,这样在同一个队列里可以按照前面的轮转法或者最少连接法进行均衡,而队列之间按照优先级的先后顺序进行均衡处理。在这里权值是基于各节点能力的一个估计值。
3.4 软件的编码
#include #include #include #include "conn.h" #include "log.h" #include "fdwrapper.h"
conn::conn(){ m_srvfd =-1;m_clt_buf = new char[ BUF_SIZE ];if(!m_clt_buf){ throw std::exception();}
m_srv_buf = new char[ BUF_SIZE ];if(!m_srv_buf){ throw std::exception();} reset();}
conn::~conn(){ delete [] m_clt_buf;delete [] m_srv_buf;}
void conn::init_clt(int sockfd, const sockaddr_in& client_addr){ m_cltfd = sockfd;m_clt_addre = client_addr;}
void conn::init_srv(int sockfd, const sockaddr_in& server_addr){ m_srvfd = sockfd;m_srv_addre = server_addr;}
void conn::reset(){ m_clt_read_idx = 0;m_clt_write_idx = 0;m_srv_read_idx = 0;m_srv_write_idx = 0;m_srv_closed = false;m_cltfd =-1;memset(m_clt_buf, ' ', BUF_SIZE);memset(m_srv_buf, ' ', BUF_SIZE);}
RET_CODE conn::read_clt(){ int bytes_read = 0;while(true){ if(m_clt_read_idx >= BUF_SIZE){ log(LOG_ERR, __FILE__, __LINE__, "%s", "the client read buffer is full, let server write");return BUFFER_FULL;}
bytes_read = recv(m_cltfd, m_clt_buf + m_clt_read_idx, BUF_SIZEm_clt_write_idx)> 0)? OK : NOTHING;}
RET_CODE conn::read_srv(){ int bytes_read = 0;while(true){ if(m_srv_read_idx >= BUF_SIZE)
{ log(LOG_ERR, __FILE__, __LINE__, "%s", "the server read buffer is full, let client write");return BUFFER_FULL;}
bytes_read = recv(m_srvfd, m_srv_buf + m_srv_read_idx, BUF_SIZEm_srv_write_idx)> 0)? OK : NOTHING;}
RET_CODE conn::write_srv(){ int bytes_write = 0;while(true){ if(m_clt_read_idx
}
bytes_write = send(m_srvfd, m_clt_buf + m_clt_write_idx, m_clt_read_idxm_srv_write_idx, 0);if(bytes_write ==-1)
{ if(errno == EAGAIN || errno == EWOULDBLOCK){ return TRY_AGAIN;} log(LOG_ERR, __FILE__, __LINE__, "write client socket failed, %s", strerror(errno));return IOERR;} else if(bytes_write == 0){ return CLOSED;}
m_srv_write_idx += bytes_write;} } #ifndef FDWRAPPER_H #define FDWRAPPER_H
#include #include #include
int setnonblocking(int fd){ int old_option = fcntl(fd, F_GETFL);int new_option = old_option | O_NONBLOCK;fcntl(fd, F_SETFL, new_option);return old_option;}
void add_read_fd(int epollfd, int fd){ epoll_event event;
0 1
event.data.fd = fd;event.events = EPOLLIN | EPOLLET;epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);setnonblocking(fd);}
void add_write_fd(int epollfd, int fd){ epoll_event event;event.data.fd = fd;event.events = EPOLLOUT | EPOLLET;epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);setnonblocking(fd);}
void closefd(int epollfd, int fd){ epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, 0);close(fd);}
void removefd(int epollfd, int fd){ epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, 0);}
void modfd(int epollfd, int fd, int ev){ epoll_event event;event.data.fd = fd;event.events = ev | EPOLLET;epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &event);
} #endif #include #include #include #include "log.h"
static int level = LOG_INFO;static int LOG_BUFFER_SIZE = 2048;static const char* loglevels[] = { "emerge!", "alert!", "critical!", "error!", "warn!", "notice:", "info:", "debug:" };
void set_loglevel(int log_level){ level = log_level;}
void log(int log_level, const char* file_name, int line_num, const char* format,...){ if(log_level > level){ return;}
time_t tmp = time(NULL);struct tm* cur_time = localtime(&tmp);if(!cur_time){
2 1
return;}
char arg_buffer[ LOG_BUFFER_SIZE ];memset(arg_buffer, ' ', LOG_BUFFER_SIZE);strftime(arg_buffer, LOG_BUFFER_SIZELOG_EMERG ]);
va_list arg_list;va_start(arg_list, format);memset(arg_buffer, ' ', LOG_BUFFER_SIZE);vsnprintf(arg_buffer, LOG_BUFFER_SIZE-1, format, arg_list);printf("%sn", arg_buffer);fflush(stdout);va_end(arg_list);} #include #include #include #include #include #include #include #include #include #include #include #include #include #include
3 1
#include #include
#include "log.h" #include "conn.h" #include "mgr.h" #include "procepool.h"
using std::vector;
static const char* version = "1.0";
static void usage(const char* prog){ log(LOG_INFO, __FILE__, __LINE__, "usage: %s config_file]", prog);}
int main(int argc, char* argv[]){ char cfg_file[1024];memset(cfg_file, ' ', 100);int option;while((option = getopt(argc, argv, "f:xvh"))!=-1){ switch(option){ case 'x': { set_loglevel(LOG_DEBUG);break;}
1 4 [-v] [-h] [-f
case 'v': { log(LOG_INFO, __FILE__, __LINE__, "%s %s", argv[0], version);return 0;} case 'h': { usage(basename(argv[ 0 ]));return 0;} case 'f': { memcpy(cfg_file, optarg, strlen(optarg));break;} case '?': { log(LOG_ERR, __FILE__, __LINE__, "un-recognized option %c", option);usage(basename(argv[ 0 ]));return 1;} } }
if(cfg_file[0] == ' '){ log(LOG_ERR, __FILE__, __LINE__, "%s", "please specifiy the config file");return 1;} int cfg_fd = open(cfg_file, O_RDONLY);
5 1
if(!cfg_fd){ log(LOG_ERR, __FILE__, __LINE__, "read config file met error: %s", strerror(errno));return 1;} struct stat ret_stat;if(fstat(cfg_fd, &ret_stat)balance_srv;vector logical_srv;host tmp_host;memset(tmp_host.m_hostname, ' ', 1024);char* tmp_hostname;char* tmp_port;char* tmp_conncnt;bool opentag = false;char* tmp = buf;char* tmp2 = NULL;char* tmp3 = NULL;
6 met met
char* tmp4 = NULL;while(tmp2 = strpbrk(tmp, "n")){ *tmp2++ = ' ';if(strstr(tmp, "")){ if(opentag){ log(LOG_ERR, __FILE__, __LINE__, "%s", "parse config file failed");return 1;} opentag = true;} else if(strstr(tmp, "")){ if(!opentag){ log(LOG_ERR, __FILE__, __LINE__, "%s", "parse config file failed");return 1;} logical_srv.push_back(tmp_host);memset(tmp_host.m_hostname, ' ', 1024);opentag = false;} else if(tmp3 = strstr(tmp, "")){ tmp_hostname = tmp3 + 6;tmp4 = strstr(tmp_hostname, "");if(!tmp4){ log(LOG_ERR, __FILE__, __LINE__, "%s", "parse config
file failed");return 1;} *tmp4 = ' ';memcpy(tmp_host.m_hostname, strlen(tmp_hostname));} else if(tmp3 = strstr(tmp, "
")){ tmp_port = tmp3 + 6;tmp4 = strstr(tmp_port, "");if(!tmp4){ log(LOG_ERR, __FILE__, __LINE__, "%s", "parse config file failed");return 1;} *tmp4 = ' ';tmp_host.m_port = atoi(tmp_port);} else if(tmp3 = strstr(tmp, "")){ tmp_conncnt = tmp3 + 7;tmp4 = strstr(tmp_conncnt, "");if(!tmp4){ log(LOG_ERR, __FILE__, __LINE__, "%s", "parse config file failed");return 1;} *tmp4 = ' ';tmp_host.m_conncnt = atoi(tmp_conncnt);}
8 tmp_hostname,else if(tmp3 = strstr(tmp, "Listen")){ tmp_hostname = tmp3 + 6;tmp4 = strstr(tmp_hostname, ":");if(!tmp4){ log(LOG_ERR, __FILE__, __LINE__, "%s", "parse config file failed");return 1;} *tmp4++ = ' ';tmp_host.m_port = atoi(tmp4);memcpy(tmp_host.m_hostname, tmp3, strlen(tmp3));balance_srv.push_back(tmp_host);memset(tmp_host.m_hostname, ' ', 1024);} tmp = tmp2;}
if(balance_srv.size()== 0 || logical_srv.size()== 0){ log(LOG_ERR, __FILE__, __LINE__, "%s", "parse config file failed");return 1;} const char* ip = balance_srv[0].m_hostname;int port = balance_srv[0].m_port;
int listenfd = socket(PF_INET, SOCK_STREAM, 0);aert(listenfd >= 0);
int ret = 0;struct sockaddr_in addre;
9 1
bzero(&addre, sizeof(addre));addre.sin_family = AF_INET;inet_pton(AF_INET, ip, &addre.sin_addr);addre.sin_port = htons(port);
ret = bind(listenfd, sizeof(addre));aert(ret!=-1);
ret = listen(listenfd, 5);aert(ret!=-1);
//memset(cfg_host.m_hostname, ' ', 1024);//memcpy(cfg_host.m_hostname, "127.0.0.1", strlen("127.0.0.1"));//cfg_host.m_port = 54321;//cfg_host.m_conncnt = 5;procepool* pool = procepool::create(listenfd, logical_srv.size());if(pool){ pool->run(logical_srv);delete pool;}
close(listenfd);return 0;} #include #include #include #include #include #include
0
2(struct sockaddr*)&addre,#include #include #include #include #include #include #include #include #include
#include #include "log.h" #include "mgr.h"
using std::pair;
int mgr::m_epollfd =-1;int mgr::conn2srv(const sockaddr_in& addre){ int sockfd = socket(PF_INET, SOCK_STREAM, 0);if(sockfd
if(connect(sockfd,(struct
sockaddr* sizeof(addre))!= 0){ close(sockfd);return-1;} return sockfd;
2 1)&addre,}
mgr::mgr(int epollfd, const host& srv): m_logic_srv(srv){ m_epollfd = epollfd;int ret = 0;struct sockaddr_in addre;bzero(&addre, sizeof(addre));addre.sin_family = AF_INET;inet_pton(AF_INET, srv.m_hostname, &addre.sin_addr);addre.sin_port = htons(srv.m_port);log(LOG_INFO, __FILE__, __LINE__, "logcial srv host info:(%s, %d)", srv.m_hostname, srv.m_port);
for(int i = 0;i
2 2
{ close(sockfd);continue;} tmp->init_srv(sockfd, addre);m_conns.insert(pair(sockfd, tmp));} } }
mgr::~mgr(){ }
int mgr::get_used_conn_cnt(){ return m_used.size();}
conn* mgr::pick_conn(int cltfd){ if(m_conns.empty()){ log(LOG_ERR, __FILE__, __LINE__, "%s", "not connections to server");return NULL;}
map::iterator iter = m_conns.begin();int srvfd = iter->first;conn* tmp = iter->second;if(!tmp)
3 enough srv
{ log(LOG_ERR, __FILE__, __LINE__, "%s", "empty server connection object");return NULL;} m_conns.erase(iter);m_used.insert(pair(cltfd, tmp));m_used.insert(pair(srvfd, tmp));add_read_fd(m_epollfd, cltfd);add_read_fd(m_epollfd, srvfd);log(LOG_INFO, __FILE__, __LINE__, "bind client sock %d with server sock %d", cltfd, srvfd);return tmp;}
void mgr::free_conn(conn* connection){ int cltfd = connection->m_cltfd;int srvfd = connection->m_srvfd;closefd(m_epollfd, cltfd);closefd(m_epollfd, srvfd);m_used.erase(cltfd);m_used.erase(srvfd);connection->reset();m_freed.insert(pair(srvfd, connection));}
void mgr::recycle_conns(){ if(m_freed.empty()){ return;}
4 2
for(map::iterator iter = m_freed.begin();iter!= m_freed.end();iter++){ sleep(1);int srvfd = iter->first;conn* tmp = iter->second;srvfd = conn2srv(tmp->m_srv_addre);if(srvfd init_srv(srvfd, tmp->m_srv_addre);m_conns.insert(pair(srvfd, tmp));} } m_freed.clear();}
RET_CODE mgr::proce(int fd, OP_TYPE type){ conn* connection = m_used[ fd ];if(!connection){ return NOTHING;} if(connection->m_cltfd == fd){ int srvfd = connection->m_srvfd;
5 2
switch(type){ case READ: { RET_CODE res = connection->read_clt();switch(res){ case OK: { log(LOG_DEBUG, __FILE__, __LINE__, read from client: %s", connection->m_clt_buf);} case BUFFER_FULL: { modfd(m_epollfd, srvfd, EPOLLOUT);break;} case IOERR: case CLOSED: { free_conn(connection);return CLOSED;} default: break;} if(connection->m_srv_closed){ free_conn(connection);return CLOSED;} break;
6 "content
} case WRITE: { RET_CODE res = connection->write_clt();switch(res){ case TRY_AGAIN: { modfd(m_epollfd, fd, EPOLLOUT);break;} case BUFFER_EMPTY: { modfd(m_epollfd, srvfd, EPOLLIN);modfd(m_epollfd, fd, EPOLLIN);break;} case IOERR: case CLOSED: { free_conn(connection);return CLOSED;} default: break;} if(connection->m_srv_closed){ free_conn(connection);return CLOSED;} break;
7 2
} default: { log(LOG_ERR, __FILE__, __LINE__, "%s", "other operation not support yet");break;} } } else if(connection->m_srvfd == fd){ int cltfd = connection->m_cltfd;switch(type){ case READ: { RET_CODE res = connection->read_srv();switch(res){ case OK: { log(LOG_DEBUG, __FILE__, __LINE__, read from server: %s", connection->m_srv_buf);} case BUFFER_FULL: { modfd(m_epollfd, cltfd, EPOLLOUT);break;} case IOERR: case CLOSED: { modfd(m_epollfd, cltfd, EPOLLOUT);
8 "content
connection->m_srv_closed = true;break;} default: break;} break;} case WRITE: { RET_CODE res = connection->write_srv();switch(res){ case TRY_AGAIN: { modfd(m_epollfd, fd, EPOLLOUT);break;} case BUFFER_EMPTY: { modfd(m_epollfd, cltfd, EPOLLIN);modfd(m_epollfd, fd, EPOLLIN);break;} case IOERR: case CLOSED: { /* if(connection->m_srv_write_idx connection->m_srvread_idx){ free_conn(connection);
9 ==
} else { modfd(m_epollfd, cltfd, EPOLLOUT);} */ modfd(m_epollfd, cltfd, EPOLLOUT);connection->m_srv_closed = true;break;} default: break;} break;} default: { log(LOG_ERR, __FILE__, __LINE__, "%s", "other operation not support yet");break;} } } else { return NOTHING;} return OK;}
0 3
3.5软件的测试
3.5.1测试计划 功能部分将使用单元测试来确定其适合符合需求,性能部分将使用自动化测试来检验。主要测试为:
1 运行测试;
2 逻辑测试; 3 业务处理能力测试; 4 系统安全性测试; 5 性能测试; 6 高负荷下工作测试; 7 稳定性测试; 8 易用性测试;
3.5.2 软件测试 1.运行测试
在进行该项测试过程中,按照按照《用户操作手册》对软件进行了全面详细的操作测试,对软件所罗列出的所有功能模块进行了精细的操作,发现了一些容错和反馈信息方面的问题,以及部分功能模块无法实现或出错。2.逻辑测试
在进行该项测试过程中,主要对软件的逻辑设计方面进行了深入评判,检查软件设计是否在某些方面有悖于正常的逻辑思维,是否在实际情况相符。发现了一些诸如单个包间可容纳客人数无限制、同一服务员可服务客人数无限制等逻辑错误。
3.业务处理能力测试
在进行该项测试过程中,主要针对系统对业务的处理能力进行测试,检查了业务处理的连贯性、全面性和正确性,并检查业务处理结果是否满足客户需求。4.安全测试
在进行该项测试过程中,检查了系统的安全登录,查看了系统内资料的安全保密性,以及系统会不会有漏洞容易遭受外部的攻击。5.性能测试
在进行该项测试过程中,对于系统的运行速度、加载速度、业务处理速度等进行了测试。结果发现如果数据库中有大量数据,此时进行数据库访问,性能将会下降。
6.高负荷下工作测试
1 3
在进行该项测试过程中,对于当数据库有大量数据,并长时间运行时,软件的运行速度、性能和资源使用情况进行了检查。通过性能监视器分别对服务器的内存、CPU、硬盘的I/O速度等系统资源的使用情况进行观察,发现系统的资源使用有所提高,查询性能有所降低,但不影响正常使用。7.稳定性测试
在进行该项测试过程中,主要看软件是否会出现死机、操作系统或者网络瘫痪、程序崩溃等问题。8.易用性测试
在进行该项测试过程中,考察了本软件的界面设计布局是否合理,外形是否美观,操作是否简单无歧义,帮助文档是否简单易懂。
4.项目开发总结报告
在对该项目进行开发的过程中,我们遇到了很多的困难。在于我们对于市场的研究和可行性考量的过程中。虽然我们明确了设计的目的,但国内以及国际市场的广阔性使我们在对客户需求的分析中走入了迷雾中,因此耽误了很多时间。但是,幸好最后我们还是完成了该项目。而从对该项目的开发中,我们也学到了以下几点。
我们要尽量的让客户也参与到项目的开发团队中来,也就是说我们要使客户把自己也纳入到项目的开发团队中来。如此一来,我们掌握客户需求的真实性、可靠性就会大大的提高,也就不会为项目的后期功能开发埋下陷阱。
在项目确立后,我们就需要做好项目开发计划,需求调研用时,开发用时,测试用时,实施用时,维护用时。在我们做好了计划后,我们要随时的跟踪计划任务的完成进度,从而使我们的项目进度掌控在我们的开发周期范围之内,今日计划、行动,明日成功。
在其他行业中,人与人的之间的沟通是很重要的。项目开发也不例外,很好的沟通能够加快项目的进度,这就要求我们每一个开发人员要学会和善于沟通于客户和同事之间。在一个项目的开发过程中,我们与客户的沟通是一个不断交流和沟通的过程。在开发到一定的阶段,我们就需要和客户沟通已有功能,尽量的去避免一些隐藏的问题,及时的发现问题,解决问题,从而按时或者提前完成项目的开发。
2 3
3 3
第4篇:软件开发软件开发计划
XXXX公司
软件开发计划
1.引言
1-1编写目的(阐明编写软件计划的目的,指出读者对象。)
1-2 项目背景(可包括:(1)项目委托单位、开发单位和主管部门;(2)该软件系统与其他系统的关系。)
1-3 定义(列出本文档中用到的专门术语的定义和缩略词的原文。)
1-4参考资料
1-4-1项目经核准的计划任务书、合同或上级机关的批文;
1-4-2文档所引用的资料、规范等;列出资料的作者、标题、编号、发表日期、出版单位或资料来源。
2.项目概述
2-1工作内容(简要说明项目的各项主要工作,介绍所开发软件的功能 性能等.若不编写
可行性研究报告,则应在本节给出较详细的介绍。)
2-2条件与限制(阐明为完成项目应具备的条件 开发单位已具备的条件以及尚需创造的条件.必要时还应说明用户及分合同承包者承担的工作 完成期限及其它条件与限制。)
2-3产品
2-3-1程序(列出应交付的程序名称 使用的语言及存储形式。)
2-3-2文档(列出应交付的文档。)
2-3-3运行环境(应包括硬件环境 软件环境。)
2-3-4服务(阐明开发单位可向用户提供的服务.如人员培训 安装 保修 维护和其他运行支持。)
2-3-5验收标准
3.实施计划
3-1任务分解(任务的划分及各项任务的负责人。)
3-2 进度(按阶段完成的项目,用图表说明开始时间 完成时间。)
3-3预算
3-4关键问题(说明可能影响项目的关键问题,如设备条件 技术难点或其他风险因素,并说明对策。)
4.人员组织及分工
5.交付期限
6.专题计划要点(如测试计划 质量保证计划 配置管理计划 人员培训计划 系统安装计划等。)
编制人:
项目编号:XXXXX-1
XXXX公司
日期:
项目编号:XXXXX-2
版权声明:
1.大文斗范文网的资料来自互联网以及用户的投稿,用于非商业性学习目的免费阅览。
2.《软件开发述职报告(共4篇)》一文的著作权归原作者所有,仅供学习参考,转载或引用时请保留版权信息。
3.如果本网所转载内容不慎侵犯了您的权益,请联系我们,我们将会及时删除。
