??xml version="1.0" encoding="utf-8" standalone="yes"?>
首先Q我觉得开发h员遇到这L(fng)郁闷是因为控刉求变更功夫没有做뀂原因有几点Q?br />1.涉及(qing)需求变更的东西不应该由最l用的用户和一U开发h员来沟通,q样的沟通费时费力而且不具有权威性?br />2.开发h员直接向客户汇报的工作量往(xin)往(xin)比实际工作量要低Q而且低的比较多。原因很单:(x)客户问开发h员(sh)个功能是否困隄时候,一般技术h员往(xin)往(xin)只考虑?jin)单功能的复杂度,而可能对q个需求变更对整个pȝ的工作量估计不Q比如美工的工作量、该功能引发的管理功能的工作量、测试工作量{等Q?br />q种情况?x)对目产生多个负面影响Qa.向客h供一个低于实际值的工作量,D客户期望高,而实际无法按时完成导致客户失望大Q降低用h意度。b.因ؓ(f)客户从开发h员口中听到的工作量L比从目l理口中听到的工作量低,造成客户寚w目组内部不一_(d)沟通不的感觉。c.因ؓ(f)客户从开发h员口中听到的工作量L比从目l理口中听到的工作量低,引诱客户喜欢直接向开发h员提出需求变_(d)造成恶性@环,直接D?jin)项目组没法按时拿到奖金Q士气下降?br />
所以对于客h出的需求变_(d)一般技术h员最好的处理方式是:(x)委婉的告诉客Pq个问题需要项目经理来评估。哪怕用L(fng)?xi)衅、教训的语气和你讲这个功能如何简单,如何如何可以实玎ͼ你都不能告诉他是否可以接受这个变_(d)更不能说实现需要多长时间?br />拒绝?jin)客户之后ƈ不是大功告成Q你最好能够早于客户通知自己的项目经理,客户惌行怎样的需求变_(d)你自己对工作量的评估是怎么L(fng)。这样可以给目l理一个准备时_(d)来完善的考虑需求变更的影响?br />
对于目l理Q尤其是从开发一U{向做目l理的兄弟,应该d的从目全局来考虑一个变更的影响Q而不是单U从技术角度考虑。最好能按照公司的规范和制度以及(qing)目实际情况q累一份check listQ以免在考虑需求变更时遗漏一些事V作为开发方更要强化对于需求变更的控制?br />控制需求变更最理想的办法当然是由客h、开发方的项目经理和需求顾问共同组lCCB(变更控制委员?sh)?
Q文档化所有需求变_(d)双方{֭然后归档需求变更。不q这h较难以实现。但是最L(fng)的要求是Q必ȝ客户斚w目经理(也就是甲Ҏ(gu)l用户需要把需求变更汇L告给甲方目l理Q向开发方目l理提出需求变_(d)开发方目l理评估工作量,q文化需求变_(d)在与客户方负责h充分沟通后Q用正式方式将沟通结果(最好是打印出来l甲方签字,最L(fng)是要求回执的?sh)子邮gQ通知客户。必要的时候需要业务h员协助,比如要求{v附加合同或者新开一个项目等{?br />
从我做项目几q的l验来看Q蛮不讲理的客户不是没有Q但是是极少敎ͼ大多数客P其是客h目l理都是通情辄的h。所以,只要你言之有理,Ҏ(gu)都有可能接纳?img src ="http://m.tkk7.com/iceboundrock/aggbug/85619.html" width = "1" height = "1" />
C++
中,cȝ使用者决定了(jin)cȝ实例内存?sh)(x)如何分配,分配在堆上还是栈上。我们先看一D例子程序:(x)
#include
"stdio.h"
class
Demo{
public
:
(tng) (tng) (tng)
int i;
(tng) (tng) (tng)
char* objName;
(tng) (tng) (tng) Demo(){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) objName = "Default object.";
(tng) (tng) (tng) (tng) (tng) (tng) (tng) printf("%s, objName = %s\r\n", "Enter Demo default ctor. method.", objName);
(tng) (tng) (tng) (tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) i = 1000;
(tng) (tng) (tng) }
(tng) (tng) (tng) Demo(int ival, char* name){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) printf("%s,i = %d, objName = %s\r\n", "Enter Demo(int ival) ctor method", ival, name);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) i = ival;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) objName = name;
(tng) (tng) (tng) }
(tng) (tng) (tng) Demo(const Demo& d){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) printf("%s\r\n", "Enter Demo copy ctor method.");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) i = d.i;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) objName = "copied d";
(tng) (tng) (tng) }
(tng) (tng) (tng) ~Demo(){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) printf("%s, i = %d, objName = %s\r\n", "Enter Demo dector. method" , i, objName);
(tng) (tng) (tng) }
};
Demo& testMethod0(){
(tng) (tng) (tng) printf("%s\r\n", "Enter testMethod0.");
(tng) (tng) (tng) Demo d(0, "d in testMethod0");
(tng) (tng) (tng) printf("%s\r\n", "Exit testMethod0.");
(tng) (tng) (tng)
return d;
}
Demo testMethod1(){
(tng) (tng) (tng) printf("%s\r\n", "Enter testMethod1.");
(tng) (tng) (tng) Demo d(1, "d in testMethod1");
(tng) (tng) (tng) printf("%s\r\n", "Exit testMethod1.");
(tng) (tng) (tng)
return d;
}
Demo* testMethod2(){
(tng) (tng) (tng) printf("%s\r\n", "Enter testMethod2.");
(tng) (tng) (tng) Demo *d = new Demo(2, "d in testMethod2");
(tng) (tng) (tng) printf("%s\r\n", "Exit testMethod2.");
(tng) (tng) (tng)
return d;
}
int
main(int argc, _TCHAR* argv[])
{
(tng) (tng) (tng) Demo d;
(tng) (tng) (tng) d = testMethod1();
(tng) (tng) (tng) Demo& d1 = testMethod0();
(tng) (tng) (tng) Demo d2(999, "d1");
(tng) (tng) (tng) Demo* d3 = testMethod2();
(tng) (tng) (tng) printf("d.i = %d\r\n", d.i);
(tng) (tng) (tng) printf("d1.i = %d\r\n", d1.i);
(tng) (tng) (tng) printf("d2.i = %d\r\n", d2.i);
(tng) (tng) (tng) printf("d3.i = %d\r\n", d3->i);
(tng) (tng) (tng)
delete d3;
(tng) (tng) (tng)
return 0;
}
Output
Q?/span>
Enter Demo default ctor. method., objName = Default object.
Enter testMethod1.
Enter Demo(int ival) ctor method,i = 1, objName = d in testMethod1
Exit testMethod1.
Enter Demo copy ctor method.
Enter Demo dector. method, i = 1, objName = d in testMethod1
Enter Demo dector. method, i = 1, objName = copied d
Enter testMethod0.
Enter Demo(int ival) ctor method,i = 0, objName = d in testMethod0
Exit testMethod0.
Enter Demo dector. method, i = 0, objName = d in testMethod0
Enter Demo(int ival) ctor method,i = 999, objName = d1
Enter testMethod2
Enter Demo(int ival) ctor method,i = 2, objName = d in testMethod2
Exit testMethod2.
d.i = 1
d1.i = -2
d2.i = 999
d3.i = 2
Enter Demo dector. method, i = 2, objName = d in testMethod2
Enter Demo dector. method, i = 999, objName = d1
Enter Demo dector. method, i = 1, objName = copied d
?/span>
C#
不同Q在
C++
中,对象声明的时候就已经执行?jin)构造函敎ͼ比如上面例子?/span>
main
函数中的W一行,
Demo d
Q从屏幕上的输出来看Q这个时?/span>
Demo class
的默认构造函C(x)被调用?/span>
接下来的一行代码调用,引出?jin)很有趣的情况,当然也隐藏着不小的问题。这行代码造成?jin)一ơ构造函数调用,一ơ拷贝构造函数调用和两次析构函数调用。让我们来具体分析一下:(x)W一ơ调用构造函数很Ҏ(gu)理解Q因为在
testMethod1
中我们声明了(jin)
Demo d(0)
Q退?/span>
testMethod1
Q函数的q回D赋值给变量
d2
Q这个时候,
d2
被拷贝构造函数重新构造了(jin)一ơ。接着
testMethod1
中构造的局部变量被析构Q然后,居然拯构造函数构造的对象也被析构Q等{,看完所有输出,我们发现Q?/span>
objName = copied d
的对象被析构两次Q?/span>
objName = Default obj
的对象被构造出之后没有被析构,q里隐藏?jin)很严重的问题,有可能导致内存泄漏、句柄不能被正确关闭{等。另外,拯构造函数的执行可能D潜在的效率问题,考虑一个包含巨大矩늚对象Q?/span>
copy
q个对象?x)怎么P
接下来的一行代码,
testMethod0
q回一个对象的引用Q当然不?x)导致拷贝构造函数被调用Q但是,q样也是有问题的Q在函数中声明的局部变量在函数执行完成的时候会(x)被析构,那么直接q回局部变量就可能?x)出现问题?/span>
testMethod0
退Z后,他内部的
Demo
对象׃(x)自动析构Q外面对它的引用当然也无法指向正的对象?jin),所以后面程序打?/span>
d.i
的时候,输出?jin)一个莫名其妙的
-2
?/span>
效率最好的Ҏ(gu)当数q回指针?jin),它不会(x)导致对象复Ӟ如果使用得当Q也不会(x)D内存泄漏或者句柄泄漏?/span>
testMethod2
演示?jin)这U情况,当然Q你需要手工删除在
testMethod2
中创建的对象?/span>
下面一D늮单的E序Q演CZ(jin)const变量Qconst指针的奇妙关p?/p>
(tng)
最单最清晰的const使用Ҏ(gu)是声明const变量?jin),变量需要在生命的地方立卛_始化Q初始化完成之后׃能再改了(jin)?/p>
如果你用同样的思\来看待const指针Q你?x)发C错的很严重,你看Q这个constIntPoint换了(jin)几个目标依然生龙z虎Q编译器很愉快的接受?jin)这D代码,q个warn都没有?br />原来const指针是指向const变量的指针,而不是说指针本n是const的。无
okQconst变量不能直接修改Q难道我取到他的地址Q再来修攚w不行么?不行Q编译器?x)直接告诉你Q无法把一个const的指针{换成普通指针,
Error (tng)1 (tng)error C2440: '=' : cannot convert from 'const int *__w64 ' to 'int *' (tng)
Z个变量原来是否被声明成constQ你用一个const指针指向它,然后使用*q算W号取出q个变量试图q行修改的操作都是不允许的,参考代码中被注释掉的Error2?br />
Error (tng)2 (tng)error C3892: 'constIntPoint' : you cannot assign to a variable that is const (tng)
1.
?/span>
ph
2.
安装
apache
3.
安装
MySQL5
4.
备䆾?/span>
Apache Group\Apache2\conf
”文件夹
5.
?/span>
MySQL
|站下蝲
MySQL Connector/PHP
的文Ӟ下蝲
mysql extension (PH
下面说一下如何配|?/span>
1. (tng) (tng) (tng) (tng) (tng) (tng) 加入 PHPIniDir 变量Q设定加?/span> php5 模块的\径;讑֮ .php 文gcd的处理方式。具体代码如下:(x)
#php config
LoadModule php5_module "d:/php/php5apache2.dll"
AddType application/x-httpd-php .php
PHPIniDir "D:/php/"
2. (tng) (tng) (tng) (tng) (tng) (tng) ?/span> index.php 加入 DirectoryIndex 变量中。具体代码如下:(x)
DirectoryIndex index.html index.html.var index.php
解压 MySQL Connector/PHP 压羃包到 D:\php Qƈ?/span> php_mysql.dll 拯?/span> D:\php\ext
1Q?span style="FONT: 7pt 'Times New Roman'"> (tng)
修改 include_path = ".;d:\php\PEAR"2Q?span style="FONT: 7pt 'Times New Roman'"> (tng)
修改 extension_dir = "D:\php\ext"3Q?span style="FONT: 7pt 'Times New Roman'"> (tng)
取消 extension=php_mysql.dll 前面的分?/span>4Q?span style="FONT: 7pt 'Times New Roman'"> (tng)
取消 extension=php_gd2.dll 前面的分?/span>
配置到这里就完成?jin),Z(jin)试效果Q可以在?/span> Apache Group\Apache2\htdocs ”文件夹中徏立一个名?/span> phpinfo.php 的文Ӟ内容如下Q?/span>
<?php
$link=mysql_connect('localhost','test','test'); //
用户和密?/span>
,
h据你自己的情冉|?/span>
if(!$link) echo "fail";
else echo "success";
mysql_close();
echo phpinfo();
?>
然后讉K http://localhost/phpinfo.php Q如果页面最端上打印出 success Q说明设定成功,否则可以Ҏ(gu) phpinfo 的结果看看问题所在?/span>
(tng)