软件项目肯定离不了文档和管理工具,如果您的项目还没有它们,那么请从现在开始。我们需要哪些文档,工具和努力
软件项目肯定离不了文档和管理工具,如果您的项目还没有它们,那么请从现在开始。那么文档是不是越多越好呢?老话说的好,合适的才是最好的。小而精的文档和工具会让我们事半功倍,大而全的文档会让我们疲于奔命,最后迷失在文档的海洋中。
51CTO向您推荐上一篇系列文章:《我们如何开始对项目进行管理:需要什么样的人》
我们写代码的都知道,错误的注释比没有注释更可怕;同样的,没有及时得到更新的文档比没有文档更可怕,因为文档就是项目的注释。那么我们是否有必要去更新那些我们根本没有用到的文档呢?很显然,那是非常没有必要的,是对资源的浪费。文档说起来其实就是一个工具,是一个让我们开发时有依据,可以追溯开发过程以及记录开发结果的工具。我们只有用到它,它才有存在的必要。
那么文档过于少或者干脆没有文档,不是更简洁?我想说:不写代码不是更简洁?玩笑归玩笑,没有文档或者文档太少会导致的问题大家可能也都遇到过:那就是过程不可追溯,有些非常重要的逻辑没有记录,需要用到时团队成员各执一词,甚至需要重新找客户确认而是客户认为我们不够专业;有些非常重要的设计没有记录,导致代码维护困难,以至于维护人员破口大骂开发人员写的什么垃圾代码做的什么垃圾设计。有些设计非常的巧妙,非常的值得学习,然而就是因为没有留下记录而被初学者如我一样的人骂了N次。在反省自己不够聪明时,是否也该让写代码的人反省一下为什么没能留下点儿记录?
有一种观点是最好的设计就是代码,意思是代码就是设计,代码应该非常的优秀,可读性特别好,让人一看就明白,我完全同意。如果代码写到这种程度,那文档就真的没用了。那么请自问,您是这样吗?如果是,没文档,没问题;如果不是,请把重要的东西写下来。那么,哪些是重要的呢?
哪些是必须的, 哪些是Optional的。对于哪些文档更重要些,应该由项目的具体情况而定,特别是项目的大小,逻辑的复杂程度,人员的情况等等很多因素。在我做过的项目中,我个人认为最重要的一些文档和工具如下所述:
1, 功能说明书(Functional Specification)------按独立功能划分优先级,每一条记录都是一个可交付物,都是一个功能。整个文档就描述了整个项目的交付功能和优先级。项目中的所有人,都应该关注这个文档:测试用它来写测试用例;开发人员用它来决定先开发哪个功能;PM用它来查看功能的完成和验证状态。它通常不应该内容过多(由项目规模决定),我觉得最多两行字就可以描述一个独立工作的功能,至于对这个功能的理解,应该由负责它的程序员来完成。
2, 核心流程图。这个流程图可能描述了用户使用该系统的过程;也可能描述系统中数据的流转;也可能描述表单的流转。总之,它描述一个过程,这个过程对用户来说非常重要。这个图有时候也会被其它的图,如顺序图代替。
3, 部署文档。该文档描述了该系统应该如何部署,它不一定非要是一个word文档,也可能仅是一个bat文件而已。这个文档应该描述该项目如何部署,步骤是怎么样的,需要哪些文件,需要哪些硬件支持,以及需要注意什么。部署历来都不太被重视,大家觉得只要东西做出来了,部署不就是放上去吗?其实不然。在经历了一定周期的开发后,开发过程中积累的配置,对环境的要求,在真正部署的时候很多就忘了,所以部署可能会花费很多没必要的时间,我觉得这也是微软要做daily build的原因之一,每天都build一个可用的版本,当然部署就没有问题了。我们刚开始可能不需要每天都build一个版本,但最少要一周或者两周部署一个版本吧。每次部署都整理一个自动化的脚本或者文档,会让你最后上线的时候非常的从容。
4, 测试用例。我不是一个测试人员,测试也是我觉得一直没有做到位的地方。客观的说,我觉得用例应该花很大心思去编写,就像用户真正的在使用软件一样。项目应该在设计和开发的时候就以满足用例为目标,而不是开发完了才想起来用例,去测试,发现问题再修改,回头想想,这可能就是测试驱动开发产生的原因吧。我们知道用户发现错误修改的成本高于我们自己发现的错误;同样的,设计和开发阶段就解决的问题成本也远远小于测试阶段发现的。正是,问题发现的越早,解决起来就越容易,成本就越低。
5, Bug管理工具。这个管理工具可以是一个excel,当然,我并不推荐这么做,毕竟excel却是不那么自动化。但是,只要比excel自动化一点点儿的信息系统就可以了,它需要可以记录问题,可以传截图,这就够了。我推荐使用bug tracker,这是个dotnet开发的开源的bug管理工具,其实也可以管理需求,是非常实用的。
以上五个是我认为最重要的,我觉得是项目开始进行管理的阶段必不可少的;而下面几个,则是大家视情况可选的。
6, 核心类图。这个可能是可选的,因为有时候,类的关于没那么复杂,也就没有必要有这个图;相反,则需要进行记录。
7, 数据库设计。数据库设计文档可能在review的时候用到。
8, 系统间接口图。如果产品有若干个子系统,如web service等等,那么我认为需要一个描述系统间接口和交互关系的图,这个图应该在设计的早期就开发出来供大家使用并且随时保持更新和关注。
有了文档和工具,是不是就一切OK了呢?不对,就像大而全的文档并不能帮助我们成功一样,有了文档并不代表项目就能成功,如何维护和使用这些文档和工具是相当重要的。每个文档都应该有人去维护,那么谁去做这个事呢?我认为项目经理应该经常拿着功能说明书开会,它也可以被看做是WBS的初级版本,可以被标注状态和优先级;所有人都应该熟悉流程图,并随时提出对流程图进行检验和review;应该指定一个人负责构建,这并不需要花费很多时间,但是需要细心和一些完美主义精神;测试人员自然要维护好测试用例;每个人特别是开发人员,都应该有一种觉悟,那就是一旦想起了哪些重要的逻辑,不管是业务的逻辑还是系统的算法,都应该记录到bug管理工具上。Bug管理工具完全可以记录这些零散但却重要的东西,以便将来方便查询。
在这里我也是根据自己的经历简单的谈了一些我的看法,这并不是金科玉律,我还得说,合适你的才是最好的。
(四) 代码规范的选择
做开发不可避免的遇到代码规范,从上学时就会学习到一些规范,但是每个公司都不同,那么我们到底要遵守哪些规范呢?我个人认为,一个合格的程序员应该可以随时调整自己适应任何一种规范,这是一种职业素养和能力。而何时该遵循何种规范,这也有一定的原则。
1, 在现有系统(代码)基础上进行开发。这种情况下,我们应该尽量的去遵循原有系统的规范,不论是命名还是注释。因为如果这时你非要按照自己的习惯写,那么系统就会出现两种完全不同风格的代码,这对将来的维护是一种噩梦。但是,遵循原有规范不是迁就原有错误。如果发现原有的规范会造成一定的问题,就要立刻改正,不能装傻充愣假装看不见。
2, 新建团队开发新的系统。新建的团队中团队成员可能来自不同的环境,对规范的选择倾向一定是不完全一样的,此时要怎么做呢?这时,项目的领导者应该组织大家一起做一个决定,讨论如何定义变量,如何给控件取名等等。在出现意见不统一又谁都说服不了谁的情况时,项目经理应该做出明确的决定。此时选择一种规范远比同时迁就两个人要来的好,不然造成新系统中存在两种规范,同样是维护的噩梦。
3, 稳定团队开发新的系统。这种情况就容易得多,团队稳定后团队成员渐渐的了解了互相的习惯,互相学习后就更容易达成妥协。只要注意让新加入的成员适应就可以了。
有人可能觉得代码规范没什么大不了,功能正确没有bug不就行了?当然,如果没有bug那肯定没问题,然而一个系统运行到退休还没有bug,哪位见过呢?我做了一些运维工作之后才渐渐了解到,不同风格的代码读起来就像是一会儿在赤道,一会儿在南极,非常的痛苦,有时甚至会造成系统很多的不一致,大大增加了维护的工作量。我们的目标之一不就是增加系统的可维护性吗?
这种东西很多了,随便搜索一大堆:这是个学生成绩的!
#include <iostreamh>
#include <iomaniph>
#include <fstream>
#include <vector>
#include <malloch>
#include <stdlibh>
#include <string>
#include <processh>
#include <stdioh>
//#define NULL 0
int const Q=20;
#define LEN sizeof(struct student)
using namespace std;
int n=0; //定义一个全局变量统计学生人数
//——--------->定义一个学生考试信息的结构体
struct student
{
char name[Q]; //用来存放姓名的
char sex[Q]; //用来存放性别的
long int id; //用来存放准考证号的
int score[4]; //用来存放分数的
int total; //用来存放总分数的
struct student next;
};
//student向量容器
vector <student> stu;
//-------------->学生类
class Information
{
public:
Information() ; //构造函数
~Information() ; //析构函数
student creat();//建立链表函数。
void output(student head);
int count(student head);//定义函数count()统计考生总数
student insert(studenthead);//指针函数insert()用来添加考生信息
student cancel(student head,long int num);//指针函数cancel()用来删除考生信息
student find(student head,long int num); //指针函数find()用来查找考生信息
void inorder(student head);//定义inorder()函数将考生的总分从大到小排列并输出
void average( student head);//求学生成绩的平均分的函数
void save(student head);//保存函数
student Read();//读取函数
private:
student p1,p2,p3,head,st;
};
Information::Information()
{
cout<<" \n";
cout<<" ------------------------<<欢迎您使用学生成绩管理系统>>------------------------\n";
cout<<" \n\n";
}
Information::~Information()
{
cout<<" \n";
cout<<" ------------------------<<谢谢您使用学生成绩管理系统>>------------------------\n";
cout<<" \n";
}
student Information::creat(void)
{//定义一个指向struct student的结构体指针函数creat()用来增加考生信息
char ch[Q];n=0; //用来存放姓名的
p1=p2=(student )malloc(LEN);//调用malloc()函数用来开辟一个新的存储单元
cout<<" -------------<<请建立学生考试信息表,在姓名处键以 ! 结束输入。>>--------------"<<endl;
cout<<" 姓名:";
cin>>ch;
head=NULL; //给指针head赋初值
while (strcmp(ch,"!")!=0)
{//调用字符比较函数strcmp()用来判断是否继续输入
char str[10];
int flag=0;
p1=(student )malloc(LEN);//调用malloc()函数用来开辟一个新的存储单元
strcpy(p1->name,ch); //将循环结构前面输入的姓名复制到结构体名为p1的数组name中
cout<<" 性别:";
cin>>p1->sex;
cout<<" 准考证号(8位):";
do{
cin>>str;
if(atol(str)>99999999 || atol(str)<1)
cout<<"对不起,请正确输入!!!\n";
else
{
p1->id=atol(str); flag=1;
}
}while(flag==0);
flag=0;
cout<<" 计算机组成原理成绩:";
do{
cin>>str;
if(atoi(str)>100 || atoi(str)<1)
cout<<"对不起,请输入1-100之间的数字!!\n";
else
{
p1->score[0]=atoi(str); flag=1;
}
}while(flag==0);
flag=0;
cout<<" 概率统计成绩:";
do{
cin>>str;
if(atoi(str)>100 || atoi(str)<1)
cout<<"对不起,请输入1-100之间的数字!!\n";
else
{ p1->score[1]=atoi(str); flag=1;}
}while(flag==0);
flag=0;
cout<<" 英语成绩:";
do{
cin>>str;
if(atoi(str)>100 || atoi(str)<1)
cout<<"对不起,请输入1-100之间的数字!!\n";
else
{ p1->score[2]=atoi(str); flag=1;}
}while(flag==0);
flag=0;
cout<<" C++成绩:";
do{
cin>>str;
if(atoi(str)>100 || atoi(str)<1)
cout<<"对不起,请输入1-100之间的数字!!\n";
else
{ p1->score[3]=atoi(str); flag=1;}
}while(flag==0);
flag=0;
p1->total=p1->score[0]+p1->score[1]+p1->score[2]+p1->score[3];//计算总分
if(n==0)head=p1;//如果是输入第一组学生考试信息就将指针p1赋给指针head
else p2->next=p1;//否则将p1赋给p2所指结构体的next指针
p2=p1;//将指针p1赋给指针p2
n++; //将n的值加1
cout<<" 姓名:";
cin>>ch;//将输入的姓名存放到字符数组ch中
}
p2->next=NULL;//将p2所指结构体的next指针重新赋空值
return (head);//将输入的第一组学生考试信息返回
}
//--------------->定义output()函数将考生的信息从头指针所指内容开始输出
void Information::output(student head)
{
if(head==NULL) cout<<" 这是一个空表,请先输入考生成绩\n";
else{
cout<<"-------------------------------------------------------------------------------\n";
cout<<" 学生考试成绩信息表\n";
cout<<"-------------------------------------------------------------------------------\n";
cout<<"准考证号 姓 名 性别 计算机组成原理 概率统计 英语 C++ 平均分 总分\n";
cout<<"-------------------------------------------------------------------------------\n";
p1=head;//将头指针赋给p
do
{
cout<<setw(8)<<p1->id
<<setw(9)<<p1->name
<<setw(8)<<p1->sex
<<setw(13)<<p1->score[0]
<<setw(16)<<p1->score[1]
<<setw(10)<<p1->score[2]
<<setw(9)<<p1->score[3]
<<setw(6)<<p1->total/40
<<setw(11)<<p1->total<<endl;
cout<<"-------------------------------------------------------------------------------\n";
p1=p1->next;//将下一组考生信息的next指针赋给p
}while(p1!=NULL);//若指针p非空则继续,目的是把所有的考生信息都传给指针p然后输出
}
}
//------------>统计学生人数的函数
int Information::count(struct student head)//定义函数count()统计考生总数
{
if(head==NULL)
return(0);//若指针head为空返回值为0
else return(1+count(head->next));//函数的递归调用
}
//----------->插入学生的成绩的函数
student Information::insert( student head)
//插入新结点定义一个指向struct student的结构体指针函数insert()用来添加考生信息
{
char str[10];
int flag=0;
cout<<"\t----------------<<请输入新增学生成绩信息>>----------------\n"<<endl;
p1=(student )malloc(LEN); //使p1指向插入的新结点
cout<<" 姓名:";
cin>>p1->name; //将输入的姓名存放到结构体名为p1的数组name中
cout<<" 性别:";
cin>>p1->sex;
cout<<" 准考证号(8位):";
do{
cin>>str;
if(atol(str)>99999999 || atol(str)<1)
cout<<"对不起,请请正确输入!!!\n";
else
{p1->id=atol(str); flag=1; }
}while(flag==0);
flag=0;
cout<<" 计算机组成原理成绩:";
do{
cin>>str;
if(atoi(str)>100 || atoi(str)<1)
cout<<"对不起,请输入1-100之间的数字!!\n";
else
{ p1->score[0]=atoi(str); flag=1;}
}while(flag==0);
flag=0;
cout<<" 概率统计成绩:";
do{
cin>>str;
if(atoi(str)>100 || atoi(str)<1)
cout<<"对不起,请输入1-100之间的数字!!\n";
else
{ p1->score[1]=atoi(str); flag=1;}
}while(flag==0);
flag=0;
cout<<" 英语成绩:";
do{
cin>>str;
if(atoi(str)>100 || atoi(str)<1)
cout<<"对不起,请输入1-100之间的数字!!\n";
else
{ p1->score[2]=atoi(str); flag=1;}
}while(flag==0);
flag=0;
cout<<" C++成绩:";
do{
cin>>str;
if(atoi(str)>100 || atoi(str)<1)
cout<<"对不起,请输入1-100之间的数字!!\n";
else
{ p1->score[3]=atoi(str); flag=1;}
}while(flag==0);
flag=0;
p1->total=p1->score[0]+p1->score[1]+p1->score[2]+p1->score[3];//计算总分
p2=head;//将头指针赋给p2
if(head==NULL) //若没调用次函数以前的头指针head为空
{
head=p1;p1->next=NULL;
}//则将p1赋给头指针head并将p1所指结构体成员指针next赋空值
else
{
while((p1->id>p2->id)&&(p2->next!=NULL))
{
p3=p2;//p3指向原p2指向的结点
p2=p2->next;
}//p2后移一个结点
if(p1->id<=p2->id)
{
if(head==p2)
{
p1->next=head;
head=p1;
} //插入到第一个结点之前
else
{
p3->next=p1;
p1->next=p2;
} //插入到p3所指结点之后
}
else
{
p2->next=p1;
p1->next=NULL;
} //插入到尾结点之后
}
n++;//将学生人数加1
cout<<"\t你输入的学生信息已经成功插入"<<endl;
return (head);
}
//------------>删除函数
student Information::cancel(student head,long int num)//定义一个指向struct student的结构体指针函数delete()用来删除考生信息
{
if(head==NULL)//若调用次函数以前的头指针head为空
{
return(head);
}
else
{
p1=head;//否则将头指针赋给p1
while(num!=p1->id&&p1->next!=NULL)//寻找要删除的结点当p1所指的学生准考证号不是输入的学生准考证号并且p1所指的next指针不为空
{
p2=p1;
p1=p1->next;
}//p2指向原p1指向的结点p1后移一个结点
if(num==p1->id)//如果输入的学生准考证号是p1所指的学生准考证号//结点找到后删除
{
if(p1==head) head=p1->next;//如果head指针和p1指针相等则将下一个结点赋给指针head
else
p2->next=p1->next;//否则将p1所指结点赋给p2所指结点将要删除的学生信息跳过去
cout<<" 删除准考证号为"<<num<<"的学生\n";
n--;//将学生人数减1
}
return(head);//将头指针返回
}
}
//------------>查找函数
student Information::find(student head,long int num)
//定义一个指向struct student的结构体指针函数find()用来查找考生信息
{
if(head==NULL)//若调用次函数以前的头指针head为空
{
cout<<" 这是一个空表,请先输入考生成绩\n";
return(head);
}
else
{
p1=head;//否则将头指针赋给p1
while(num!=p1->id&&p1->next!=NULL)
//寻找结点当p1所指的学生准考证号不是输入的学生准考证号并且p1所指的next指针不为空
{
p1=p1->next;
}//p2指向原p1指向的结点p1后移一个结点
if(num==p1->id)//如果要查找的学生准考证号是p1所指的学生准考证号
{
cout<<"------------------------------------------------------------------------------\n";
cout<<"准考证号 姓名 性别 计算机组成原理 概率统计 英语 C++ 平均分 总分 \n";
cout<<"------------------------------------------------------------------------------\n";
cout<<setw(8)<<p1->id
<<setw(9)<<p1->name
<<setw(8)<<p1->sex
<<setw(13)<<p1->score[0]
<<setw(16)<<p1->score[1]
<<setw(10)<<p1->score[2]
<<setw(9)<<p1->score[3]
<<setw(6)<<p1->total/40
<<setw(11)<<p1->total<<endl;
cout<<"------------------------------------------------------------------------------\n";
}
else
cout<<" 没找到准考证号为"<<num<<"的学生\n"; //结点没找到
return(head);
}
}
//------------定义inorder()函数将考生的总分从大到小排列并输出
void Information::inorder(student head)
{
int i,k,m=0,j;
student p[Q];//定义一个指向struct student的结构体指针数组p
if(head!=NULL)//如果头指针是空则继续
{ m=count(head);
cout<<"------------------------------------------------------------------------------\n";
cout<<"学生考试成绩统计表\n";
cout<<"------------------------------------------------------------------------------\n";
cout<<"准考证号 姓 名 性别 计算机组成原理 概率统计 英语 C++ 平均分 总分 名次\n";
cout<<"------------------------------------------------------------------------------\n";
p1=head;
for(k=0;k<m;k++)
{
p[k]=p1;
p1=p1->next;
}
for(k=0;k<m-1;k++) //选择排序法
for(j=k+1;j<m;j++)
if(p[k]->total<p[j]->total)
{
p2=p[k];
p[k]=p[j];
p[j]=p2;
} //从大到小排列的指针
for(i=0;i<m;i++)
{
cout<<setw(8)<<p1->id
<<setw(9)<<p1->name
<<setw(8)<<p1->sex
<<setw(13)<<p1->score[0]
<<setw(16)<<p1->score[1]
<<setw(10)<<p1->score[2]
<<setw(9)<<p1->score[3]
<<setw(6)<<p1->total/40
<<setw(11)<<p1->total<<endl;
cout<<"------------------------------------------------------------------------------\n";
}
}
}
//------------>求各科平均分成绩的函数
void Information::average(student head)
{
int k,m;
float arg1=0,arg2=0,arg3=0,arg4=0;
if(head==NULL)//如果头指针是空则继续
{
cout<<" 这是一个空表,请先输入考生成绩\n";
}
else
{
m=count(head);
p1=head;
for(k=0;k<m;k++)
{
arg1+=p1->score[0];
arg2+=p1->score[1];
arg3+=p1->score[2];
arg4+=p1->score[3];
p1=p1->next;
}
arg1/=m;arg2/=m;arg3/=m;arg4/=m;
cout<<"全班单科成绩平均分\n";
cout<<"------------------------------------------------------------------------------\n";
cout<<" 计算机组成原理平均分:"<<setw(7)<<arg1
<<" 概率统计平均分:"<<setw(7)<<arg2
<<" 英语平均分:"<<setw(7)<<arg3
<<" C++平均分:"<<setw(7)<<arg4<<endl;
cout<<"------------------------------------------------------------------------------\n";
}
}
//------------------->保存函数
void Information::save(student head)
{
ofstream out("datatxt",ios::out);
out<<count(head)<<endl;
while(head!=NULL)
{ out<<head->name<<"\t"
<<head->id<<"\t"<<"\t"
<<head->sex<<"\t"
<<head->score[0]<<"\t"
<<head->score[1]<<"\t"
<<head->score[2]<<"\t"
<<head->score[3]<<"\t"
<<head->total<<endl;
head=head->next;
}
}
//———————————>读取函数的实现
student Information::Read()
{ int i=0;
p1=p2=( student )malloc(LEN);
head=NULL;
ifstream in("datatxt",ios::out);
in>>i;
if(i==0){cout<<" datatxt 文件中的数据为空,请先输入数据。"<<endl; return 0;}
else {
cout<<" …………………………………………………………………………………………"<<endl;
for(;i>0;i--)
{ p1=(student )malloc(LEN);
cin>>stname>>stid>>stsex
>>stscore[0]>>stscore[1]>>stscore[2]>>stscore[3]
>>sttotal;
strcpy(p1->name,stname);
p1->id=stid;
strcpy(p1->sex,stsex);
p1->score[0]=stscore[0];
p1->score[1]=stscore[1];
p1->score[2]=stscore[2];
p1->score[3]=stscore[3];
p1->total=sttotal;
if(n==0)head=p1;//如果是输入第一组学生考试信息就将指针p1赋给指针head
else p2->next=p1;//否则将p1赋给p2所指结构体的next指针
p2=p1;//将指针p1赋给指针p2
n++; //将n的值加1
//显示读入数据
cout<<" "<<p1->name<<"\t"
<<p1->id<<"\t"<<"\t"
<<p1->sex<<"\t"
<<p1->score[0]<<"\t"
<<p1->score[1]<<"\t"
<<p1->score[2]<<"\t"
<<p1->score[3]<<"\t"
<<p1->total<<endl;
cout<<" …………………………………………………………………………………………"<<endl;
//
}
cout<<" 数据已经成功读取完毕。"<<endl;
p2->next=NULL;
return (head);
}
}
//------------------------------>主函数
int main(void)
{
Information person;
student head=NULL;
char str[10];
int flag=0;
int choice;
long int i;
head=personRead();
do{
cout<<"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓";
cout<<"┃ 学生成绩管理系统主菜单界面 ┃";
cout<<"┃ 读取数据请输入数字零 ┃";
cout<<"┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫";
cout<<"┃ ①输入学生成绩 ┃";
cout<<"┃ ②显示学生成绩 ┃";
cout<<"┃ ③排序统计成绩 ┃";
cout<<"┃ ④查找学生成绩 ┃";
cout<<"┃ ⑤增加学生成绩 ┃";
cout<<"┃ ⑥删除学生成绩 ┃";
cout<<"┃ ⑦保存退出系统 ┃";
cout<<"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛";
cout<<"请输入您的选择(1--7):( )\b\b";
cin>>str;
if(atoi(str)>7 || atoi(str)<1)
cout<<"对不起,请输入1-7这几个数字!!\n";
else
{
choice=atoi(str);
switch(choice)
{
case 1:
head=personcreat();
break;
case 2:
personoutput(head);
break;
case 3:
personinorder(head);
personaverage(head);
cout<<" 参加考试的学生人数为:"<<personcount(head)<<"人\n";
break;
case 4:
cout<<" 请输入要查找的准考证号(8位):";
do{
cin>>str;
if(atol(str)>99999999 || atol(str)<1)
cout<<"对不起,请输入正确输入!!!\n";
else
{i=atol(str); flag=1; }
}while(flag==0);
flag=0;
personfind(head,i);
break;
case 5:
head=personinsert(head);
personoutput(head);
break;
case 6:
cout<<" 请输入要删除的准考证号(8位):";
do{
cin>>str;
if(atol(str)>99999999 || atol(str)<1)
cout<<"对不起,请输入正确输入!!!h\n";
else
{i=atol(str); flag=1; }
}while(flag==0);
flag=0;
head=personcancel(head,i);
personoutput(head);
break;
case 7:
personsave(head);
cout<<"文件已保存!可以安全退出!!!"<<endl;
break;
default :cout<<" 对不起,您的输入有误,请重新输入。\n";
break;
}
}
}while(choice!=7);
return 0;
}
你好,一般的web应用结构分为三层,采用经典的MVC设计模式,在程序的目录架构上有如下分层:数据库<->model->dao->service。分析:
1、数据库和model中的实体类是相互对应的,一个实体类,就对应这数据库中的一张表。
2、dao是一个service和model联系的桥梁,封装了 *** 作数据的具体实现,你可以在dao中使用jdbc,也可以使用hibernate。但是这些对service层都是透明的。
3、service层通过调用dao层,直接取得需要的数据或者要执行的 *** 作,并且加入相应的业务逻辑,如检查、判断。
4、当一个应用为web应用时,就可以在servlet中调用service层的方法,来完成不同的功能。常见的增删查改。
5、servlet处理完成后,就结果转发给视图层进行显示。
有上面可以看出:1、2就是M层,3、4就是C层,jsp、html就是V层。
一般按照以下步骤进行:
1 需求分析:
明确程序要实现的最终效果,需要哪些资源,并进行进度规划。
2 概要设计:
对程序进行模块化,确定各个模块功能,及各个模块间的交互。
3 详细设计:
对每个模块具体如何实现进行设计,确认模块实现方式,对内及对外接口定义。
4 代码实现:
按照设计规划,实现具体代码。
5 测试:
对各模块进行测试,最终测试整体。解决存在的问题,最终形成有效程序。
如果你参与了项目,最好写清楚参与的项目的时间,项目描述,自己在这个项目中的主要责任,以及在项目中用到的技术和自己在项目中学到的东西
完成了xxx部分编码/测试/设计,(在xxx时间内)实现了yyyy功能,使得项目获得了zzzz收益,获得dddd奖励。
可以在项目描述中谈谈自己在实现某项功能时用到了什么技术,如用MySQL的 limit语句实现分页功能
先介绍一下项目要实现的功能,在介绍下程序的结构划分(MVC),再谈下MVC各是用什么技术实现的(如View用了JSP、JSTL,Controller使用Struts2的过滤器。。。),然后介绍下实现主要功能时具体用了哪些技术(建议你多谈点对AJAX的理解)
测试嘛 ,需要的还是多沟通,不过测试人员与研发人员是不对外的,即不能与客户直接接触,所以需要仔细的看需求文档以及与项目经理沟通。
你现在需要拿到的是需求说明书,如果可以的话可以拿到研发的设计说明书,还有要问清楚相关人员此项目的相关事宜,如什么时候项目开始,什么时候项目结束,需不需要演示等事宜,有时候时间紧迫不一定需要你写测试用例的,还有。。。很蛋疼的就是有时候项目经理不是研发出身,这样设计出来的程序跟需求说明书差的好远。。
对于设计软件需求说明书,要看好里面的功能详细说明,性能详细说明,这样可以方便你编写测试用例。好的测试人员需要绝对的细心和耐心,一些界面的设计,如界面友好性,是否方便也要考虑在内。同时还要跟踪研发的进度,注意需求说明的变更,有没有新增需求,有没有需求的改变等。同时要配置好测试环境,不了解的时候多沟通。
同时,你们的产品要是跟硬件相关的话你还要了解硬件哦。一些参数如电源啊 ,测试温度的影响啊,接线什么的。不然搭建测试环境有的苦头吃了。
以上就是关于软件项目一般需要在哪些文档的哪些地方需要添加源代码全部的内容,包括:软件项目一般需要在哪些文档的哪些地方需要添加源代码、《C语言程序设计》项目设计、java 项目 框架 说明文档等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)