思考's profile释放自己PhotosBlogLists Tools Help

释放自己

建元 张

Occupation
Interests
追求简单的人。
黄山  
Photo 1 of 8

灏天BLOG

Loading...Loading...
hit counters
December 11

恭喜您成为推荐博客之星

:) 没想到自己也终于混上了博客之星了:)
 
标题:    恭喜您成为推荐博客之星
正文:
感谢您写了很多很好的博客,恭喜您成为推荐博客之星,希望您再接再励,写出更多更好的帖子,和JavaEye一起进步。
PS:能否请你设置一下个人介绍和个人头像,取代缺省设置。
谢谢!
JavaEye管理团队

关于交换编程的一些思考

关于交换编程,我也考虑过很多,在很久以前想想结对编程的时候,就考虑过,感觉上交换编程有一些问题不好解决:
1:每个人都要理解上一个人的思想,思路,这样的时间应该是比较耗费的,
2:每个人都有一定的思维惯式,交换的时候,缺少一个人在身边,这样很有可能这个人把上一个人的思维更改成自己的思维模式(比如文档,代码),这样很有可能给后面的人和原作者带来一定的困扰。
3:接手的人,是否会为上一人擦屁股,如果上一个人写的比较差的话,那么接手之后,如果接手得人没有责任心的话,那么可能就会让差的代码越发的差,这样可能发生代码腐烂的问题。我觉得人总是受环境的影响比较大,特别是一些没有特殊洁癖得人,比如一段代码写了注释,那么后来得人,可能接着写,如果前面的人就马马虎虎,凑合的话,那么后面的人会更凑合,就像Tom Demarco的那本《程序员修炼之道》中说得救火队员去救火的那个故事一样,如果屋子干净的话,队员都要扑上垫子,才敢进去救火。
当然了,如果上面的全部反过来的话,这个就是一个比较好的实践了:)

Spring中使用HSQLDB测试ibatis的dao

项目是用Spring+ibatis+jsp开发,一直再看敏捷开发方面的文章,虽然没有做到TDD,也没有做到事后测试,和每个方法都测试,但是也是在一直向这个方向努力,也在努力构建可测试的系统而努力。以前都是在测试一些工具类,现在努力在各个方面构建测试,努力做到自己的成果都是测试过的。 一直以来,数据库方面的测试都是比较困难的,特别是一些SQL语句是否正确,还有就是数据库中数据的不稳定性导致测试不可预见性。

从网上找了很多文章,都是HSQLDB测试Hibernate的 ,ibatis的找了很多都没有找到,只能自己一点点摸索,现在基本上稳定了,也可以了。写下来,经验共享一下,也让大家指点一下。废话少说,上代码。

结构Controller + logic(业务代码)+DAO(基本上只用一个工具类DAO)

先看DAO代码,基本上也没有做什么,只是继承了Spring的SqlMapClientDaoSupport
java 代码
  1. /**
  2. *数据访问类,所有对数据库访问的DAO都应继承这个抽象类,
  3. *可以利用其中一些公用方法
  4. */
  5. public class DefaultDAO extends SqlMapClientDaoSupport {

Logic基本上就是调用DAO进行一些操作,和一些业务代码,没有什么可介绍的。

下面介绍测试logic的测试基类

java 代码
java 代码
  1. import java.io.Reader;
  2. import junit.framework.TestCase;
  3. import org.springframework.jdbc.datasource.DriverManagerDataSource;
  4. import org.springframework.jdbc.datasource.SingleConnectionDataSource;
  5. import org.springframework.orm.ibatis.SqlMapClientFactoryBean;
  6. import propertity.config.SystemConfig;
  7. import com.ibatis.common.resources.Resources;
  8. import com.ibatis.sqlmap.client.SqlMapClient;
  9. import com.ibatis.sqlmap.client.SqlMapClientBuilder;
  10. public abstract class DefaultLogicTest extends TestCase {
  11. private SingleConnectionDataSource m_dataSource;
  12. private SqlMapClient m_sqlMapClient; // Actually initialized in superclass
  13. private DefaultDAO m_dao;
  14. protected void setUp() throws Exception {
  15. super.setUp();
  16. // 构造DataSource
  17. m_dataSource = new SingleConnectionDataSource();
  18. m_dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
  19. m_dataSource.setUrl("jdbc:hsqldb:file:"+ SystemConfig.WORKSPACE_PATH + getDBScriptPath());
  20. m_dataSource.setUsername("sa");
  21. m_dataSource.setPassword("");
  22. m_dataSource.getConnection().setAutoCommit(false);
  23. m_dataSource.setSuppressClose(false);
  24. // 构在SQLMapClient
  25. Reader reader = Resources.getResourceAsReader(SystemConfig.SQL_MAP_CONFIG_RESOURCE);
  26. m_sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);
  27. m_sqlMapClient.setUserConnection(m_dataSource.getConnection());
  28. // 构造默认的DAO
  29. m_dao = new DefaultDAO();
  30. m_dao.setDataSource(m_dataSource);
  31. m_dao.setSqlMapClient(m_sqlMapClient);
  32. }
  33. /**
  34. * 得到DAO
  35. * @return
  36. */
  37. protected DefaultDAO getDao() {
  38. return m_dao;
  39. }
  40. /**
  41. * 得到数据库的位置
  42. * @return
  43. */
  44. protected String getDBScriptPath() {
  45. return "/com/aaaa/bbbb/cccc/dddd/action/map/action";
  46. }
  47. /* (non-Javadoc)
  48. * @see junit.framework.TestCase#tearDown()
  49. */
  50. protected void tearDown() throws Exception {
  51. super.tearDown();
  52. m_sqlMapClient.setUserConnection(m_dataSource.getConnection());
  53. m_sqlMapClient.update("HsqlDB.shutdown", null);
  54. m_dataSource.getConnection().close();
  55. m_sqlMapClient.setUserConnection(null);
  56. }
  57. }

这个里面需要注意的就是那个得到数据库位置的方法,因为我为每个测试类指定不同的数据库内容,如果不写就默认的,需要写数据库文件后面的.script后缀。

还有就是那个tearDown中的【shutdown】sql,因为Hsqldb如果不调用这句话的话,就会改变Script里面的内容,这个让我困惑了一阵子:) ,还有就是Url中的SystemConfig.WORKSPACE_PATH 常量,主要是自己找了半天资料,也找不到相对路径的写法,于是就定义了一个常量

下面就是具体的测试类

java 代码
  1. public class UserLogicTest extends DefaultLogicTest {
  2. private UserLogic logic;
  3. protected void setUp() throws Exception {
  4. super.setUp();
  5. logic = new UserLogic();
  6. logic.setDefaultDao(super.getDao());
  7. }
  8. /**
  9. * 没有检索用户销售区域
  10. */
  11. public void testQueryUserByName() {
  12. User user = new User();
  13. user.setCorpID("1006");
  14. user.setUserID("PK116055807175866885");
  15. user.setLoginName("kaka");
  16. user.setPassword("1q");
  17. User userDB = logic.queryUserByName(user);
  18. assertNotNull("销售区域", userDB.getSaleAreaCls());
  19. }
  20. /**
  21. * 维护用户没有更新用户销售区域
  22. */
  23. public void testMaintenUser() throws Exception{
  24. User user = new User();
  25. user.setCorpID("1006");
  26. user.setUserID("PK116055807175866885");
  27. user.setPassword("password");
  28. user.setSaleAreaCls("0");
  29. logic.maintenUser(user);
  30. User userDB = logic.queryUserByID(user);
  31. assertEquals("销售区域", "0", userDB.getSaleAreaCls());
  32. }
  33. /**
  34. * 测试修改密码
  35. */
  36. public void testSaveUserPwd() throws Exception {
  37. User user = new User();
  38. user.setCorpID("1006");
  39. user.setUserID("PK116055807175866885");
  40. user.setPassword("password");
  41. // 插入前判断一下
  42. User userDB = logic.queryUserByID(user);
  43. assertFalse("密码开始", user.getPassword().equals(userDB.getPassword()));
  44. logic.saveUserPwd(user);
  45. userDB = logic.queryUserByID(user);
  46. assertEquals("密码结束", userDB.getPassword(), user.getPassword());
  47. }
  48. /**
  49. * 测试删除用户
  50. *
  51. */
  52. public void testDeleteUserByPK() throws Exception {
  53. User user = new User();
  54. user.setUserID("PK116055807175866884");
  55. logic.deleteUserByPK(user.getUserID());
  56. User userDB = logic.queryUserByID(user);
  57. assertNull("成功删除用户", userDB);
  58. super.getDao().getDataSource().getConnection().rollback();
  59. }
  60. public void testQueryUserRelationAndNotGroupListMap() {
  61. User user = new User();
  62. user.setUserID("PK116055807175866885");
  63. Map groupMap = logic.queryUserRelationAndNotGroupListMap(user.getUserID());
  64. List relationGroupList = (List)groupMap.get("RELATION");
  65. List notRelationGroupList = (List)groupMap.get("NOT_RELATION");
  66. // 关联的
  67. assertEquals("关联的是3个", 3, relationGroupList.size());
  68. // 顺序 1,2,test
  69. testSeq(new String[]{"1", "2", "test"}, relationGroupList);
  70. // 没有关联的
  71. assertEquals("没有关联的是4个", 4, notRelationGroupList.size());
  72. testSeq(new String[]{"原燃料供应商组", "综合供应商组", "销售客户组", "系统测试"}, notRelationGroupList);
  73. }
  74. private void testSeq(String[] seqNem, List groupList) {
  75. for (int i = 0; i < seqNem.length; i++) {
  76. UserGroup vo = (UserGroup)groupList.get(i);
  77. assertEquals("名称" + i,seqNem[i], vo.getUserGroupName());
  78. }
  79. }
  80. /**
  81. * 检查排序问题,大写字母的排在前面
  82. *
  83. */
  84. public void testQueryAllUsers() {
  85. List userList = logic.queryAllUsers("1006");
  86. User user = (User)userList.get(0);
  87. assertEquals("第一个不是大写", "kaka", user.getLoginName());
  88. }
  89. /**
  90. * 保存用户和用户组关联
  91. *
  92. */
  93. public void testSaveRelation() throws Exception {
  94. RelationGroupFormVO vo = new RelationGroupFormVO();
  95. vo.setUserID("PK116055807175866885");
  96. vo.setPk_corp("1006");
  97. vo.setRel_sel(new String[]{"PK116441420549454662", "PK116458716029826288"});
  98. logic.saveRelation(vo);
  99. Map groupMap = logic.queryUserRelationAndNotGroupListMap(vo.getUserID());
  100. List relationList = (List)groupMap.get("RELATION");
  101. assertEquals("长度", 2, relationList.size());
  102. if (relationList.size() <= 0) {
  103. return;
  104. }
  105. testSeq(new String[]{"综合供应商组", "销售客户组"}, relationList);
  106. }
  107. /* (non-Javadoc)
  108. * */
  109. protected String getDBScriptPath() {
  110. return "/com/ufida/cvms/basemanagement/usermanager/map/user";
  111. }
  112. }

还有就是数据库文件了

sql 代码
  1. CREATE TABLE BD_CUBASDOC(PK_CUBASDOC CHAR(20) NOT NULL,PK_CORP CHAR(4) NOT NULL,CUSTCODE VARCHAR(30) NOT NULL,CUSTNAME VARCHAR(100) NOT NULL,CUSTSHORTNAME VARCHAR(40) NOT NULL)
  2. CREATE TABLE CMS_DATADICT(PK_DATADICT CHAR(20) NOT NULL,VTYPE VARCHAR(20),IVALUE INTEGER,CLOCALE CHAR(5) DEFAULT 'zh_CN',VVALUEDESC VARCHAR(64),TS CHAR(19),DR INTEGER DEFAULT 0,VTYPENAME VARCHAR(30))
  3. CREATE TABLE BD_AREACL(PK_AREACL CHAR(20) NOT NULL,PK_CORP CHAR(4) NOT NULL,AREACLCODE VARCHAR(12) NOT NULL,AREACLNAME VARCHAR(20) NOT NULL,PK_FATHERAREA CHAR(20),TS CHAR(19),DR INTEGER,DEF1 VARCHAR(100),DEF2 VARCHAR(100),DEF3 VARCHAR(100),DEF4 VARCHAR(100),DEF5 VARCHAR(100),MNECODE VARCHAR(10))
  4. CREATE TABLE CMS_USER(PK_USER CHAR(20) NOT NULL,VLOGINNAME VARCHAR(28),VTRUENAME VARCHAR(32),VPASSWORD VARCHAR(30),VCERTCODE VARCHAR(50),VTEL VARCHAR(30),CCUBASID CHAR(20),CCUMANID CHAR(20),ISALEAREACLS INTEGER,VMOBILE VARCHAR(30),VFAX VARCHAR(30),VEMAIL VARCHAR(50),VMEMO VARCHAR(100),VCORPFULLNAME VARCHAR(128),VCORPSHORTNAME VARCHAR(64),VJURIDICAL VARCHAR(50),VCOUNTRY VARCHAR(64),CAREACLSID CHAR(20),VADDRESS VARCHAR(256),VPOSTALCODE CHAR(6),VTAXNO VARCHAR(32),VMASTERBUSS VARCHAR(128),VBANKNAME VARCHAR(256),VBANKACCOUNT VARCHAR(20),PK_CORP CHAR(4),DACTIVEDATE CHAR(10),DINVALIDATE CHAR(10),IUSERSTATUS INTEGER,DLASTLOGINDATE CHAR(19),IUSERTYPE INTEGER,TS CHAR(19),DR INTEGER)
  5. CREATE TABLE CMS_USERGROUP(PK_USERGROUP CHAR(20) NOT NULL,VGROUPCODE VARCHAR(28),VGROUPNAME VARCHAR(50),VGROUPDES VARCHAR(50),PK_CORP CHAR(4),TS CHAR(19),DR INTEGER DEFAULT 0)
  6. CREATE TABLE CMS_USER_GROUP_RELATION(PK_USERGROUP_B CHAR(20) NOT NULL,CUSERGROUPID CHAR(20),CUSERID CHAR(20),TS CHAR(19),DR INTEGER DEFAULT 0)
  7. CREATE USER SA PASSWORD "" ADMIN
  8. INSERT INTO BD_CUBASDOC VALUES('0001AA1000000003VQGO','0001','1101649','\u4e2d\u56fd\u77ff\u4ea7\u6709\u9650\u8d23\u4efb\u516c\u53f8','\u4e2d\u56fd\u77ff\u4ea7')
  9. INSERT INTO CMS_DATADICT VALUES('444 ','YHZT',2,'zh_CN','\u6b63\u5f0f\u7528\u6237','2006-10-17 11:22:26',0,'\u7528\u6237\u72b6\u6001')
  10. INSERT INTO BD_AREACL VALUES('dqda0000000000000002','0001','1101','\u5317\u4eac\u5e02\u533a','dqda0000000000000001','2002-12-18 00:00:00',0,NULL,NULL,NULL,NULL,NULL,NULL)
  11. INSERT INTO CMS_USER VALUES('PK116055807175866875','KZka','ABC','aaipjgbcboobnhbc','6666666','6666666666',NULL,NULL,0,'66666666666','11111111666','aaa@saf.com',NULL,'\u56db\u5927\u53d1\u9001\u996d','\u963f\u65af\u8482\u82ac','\u5b8c\u5168\u989d','\u5916\u8033\u5b8c\u5168\u989d','dqda0000000000000002','werewewr','666666','6666666666666','6666666666','66666666666','66666','1006',NULL,NULL,2,'2006-11-24 16:30:44',4,'2006-11-24 16:30:44',0)
  12. INSERT INTO CMS_USER VALUES('PK116055807175866885','kaka','zjy','aaipjgbcboobnhbc','6666666','6666666666',NULL,NULL,0,'66666666666','11111111666','aaa@saf.com',NULL,'\u56db\u5927\u53d1\u9001\u996d','\u963f\u65af\u8482\u82ac','\u5b8c\u5168\u989d','\u5916\u8033\u5b8c\u5168\u989d','dqda0000000000000002','werewewr','666666','6666666666666','6666666666','66666666666','66666','1006',NULL,NULL,2,'2006-11-24 16:30:44',4,'2006-11-24 16:30:44',0)
  13. INSERT INTO CMS_USERGROUP VALUES('PK116169875984005137','3','2','1','1006','2006-10-24 21:55:12',0)
  14. INSERT INTO CMS_USERGROUP VALUES('PK116433523110959947','1','1','1','1006','2006-11-24 10:30:07',0)
  15. INSERT INTO CMS_USERGROUP VALUES('PK116441420549454662','0003','\u7efc\u5408\u4f9b\u5e94\u5546\u7ec4',NULL,'1006','2006-11-25 09:23:02',0)
  16. INSERT INTO CMS_USERGROUP VALUES('PK116458716029826288','0011','\u9500\u552e\u5ba2\u6237\u7ec4',NULL,'1006','2006-11-27 09:25:45',0)
  17. INSERT INTO CMS_USERGROUP VALUES('PK116354770995805209','444','\u7cfb\u7edf\u6d4b\u8bd5','\u521d\u671f\u6d4b\u8bd5\u2015\u2015\u4fe1\u606f\u8bc4\u4ef7\u90e8','1006','2006-11-15 08:40:46',0)
  18. INSERT INTO CMS_USERGROUP VALUES('PK116354840433039098','0001','\u539f\u71c3\u6599\u4f9b\u5e94\u5546\u7ec4','\u539f\u71c3\u6599\u4f9b\u5e94\u5546','1006','2006-11-15 08:52:20',0)
  19. INSERT INTO CMS_USERGROUP VALUES('PK116354868037463911','test','test',NULL,'1006','2006-11-15 08:56:56',0)
  20. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116461221779950435','PK116433523110959947','PK116349434520962752','2006-11-27 15:25:44',0)
  21. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116461221779925183','PK116433523110959947','PK116349504077321401','2006-11-27 15:25:44',0)
  22. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116461221779908017','PK116433523110959947','PK116063874195957630','2006-11-27 15:25:44',0)
  23. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116461221779949238','PK116433523110959947','PK116229489004712130','2006-11-27 15:25:44',0)
  24. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116461221779916855','PK116433523110959947','PK116363778699299950','2006-11-27 15:25:44',0)
  25. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116441283966919281','PK116354840433039098','PK116424362932510299','2006-11-25 09:00:16',0)
  26. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116458717250926033','PK116458716029826288','PK116458688918253943','2006-11-27 09:25:57',0)
  27. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116354777072528935','PK116354770995805209','PK116349423878288523','2006-11-15 08:41:46',0)
  28. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116354777072528436','PK116354770995805209','PK116349434520962752','2006-11-15 08:41:46',0)
  29. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116354851343863279','PK116169875984005137','PK116349504077321401','2006-11-15 08:54:09',0)
  30. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116424456759089179','PK116354868037463911','PK116349434520962752','2006-11-23 10:15:34',0)
  31. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116424456759059525','PK116354868037463911','PK116424376929524473','2006-11-23 10:15:34',0)
  32. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116424456759049917','PK116354868037463911','PK116219721663024806','2006-11-23 10:15:34',0)
  33. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116424456759090900','PK116354868037463911','PK116349504077321401','2006-11-23 10:15:34',0)
  34. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116424456759076081','PK116354868037463911','PK116063874195957630','2006-11-23 10:15:34',0)
  35. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116424456759075198','PK116354868037463911','PK116229489004712130','2006-11-23 10:15:34',0)
  36. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116424456759033542','PK116354868037463911','PK116349423878288523','2006-11-23 10:15:34',0)
  37. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116424456759085854','PK116354868037463911','PK116055807175866885','2006-11-23 10:15:34',0)
  38. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116354851343860249','PK116169875984005137','PK116055807175866885','2006-11-15 08:54:09',0)
  39. INSERT INTO CMS_USER_GROUP_RELATION VALUES('PK116461221779999473','PK116433523110959947','PK116055807175866885','2006-11-27 15:25:44',0)

HSQLDB就是从这个*.script文件里面读入表和数据,然后就可以调用各种方法测试里面的数据。需要注意的是,测试类找不到WEB-INF下面的Sql_Map_Config文件,所以拷贝了一份,放到了测试源文件的包根目录下。

大体上就是这些了,写下来,记录一下,也为这段时间的辛勤劳作一个小小的表彰:)

November 14

关于项目管理方面的一些思考

       最近一直有所思考项目管理方面的事情,也是在心中考虑一些,正好今天得空,写一下,以防自己忘记,也巩固一下自己的思考成果^_^。
       对于项目leader或者项目经理,对于一个项目来说最大的事情,莫过于管理,管理管理有管有理,不能放任自流,也不能过于不信任自己的队员。项目重要的事情就是要有一个目标,一个先期目标,也就是要达到什么。想想也是废话,不过仔细考虑一下这个就不是废话了,很多项目上来就是你作吧,别的什么都不说,做成什么样子,要搞成什么样子也都没说。这个我觉得还不算大问题,只要在后面管上加以动作的话,那么就应该没问题,如果后面管还没有的话,那么时间质量效果上,可能都是问题。
        有了目标,那么剩下的就是要生成计划,一个粗略地计划,和一个近期短暂的计划,来保证项目前进。粗略的计划为纲,细的计划为一个里程碑,最好是一个礼拜为一个点,来划分,如果心中明确的话,最好做出一周细的同时,把下一周粗的也给制定出来。制定出来计划后,就要及时检查,及时调整,如果有时间的话,最好一天一次检查,没有时间的话,至少要在一周结束的时候,检查一下。《程序员修炼之道》里面有句话,很符合项目的,项目进展就像是开车,你需要不停的得到路面的反馈,得到眼睛给与的反馈,进行调整方向,速度。大体是这个意思,我觉得项目确实是这样,不能制定了目标,就闭着眼睛开车,速度方向放任自流,这样车早晚开到沟里面去。
         项目三个要素,速度,质量,频率都要把握好,速度要有,质量要把握,同时频率也要把握好。不是车一直开大油门就好,短时间是可以的,长了,车就毁了,一定要把握好频率,该休息休息,该工作工作,要让项目最大的成本(人)维护好,只要这样,才能更好的发展。过一段时间,需要让组员释放一下心情,释放一些积怨,让组员休息好,才能工作好。只有积极调动了组员的积极性,才能事半功倍。并且,千万不要打消组员的积极性,那绝对是事倍工一点啊!科技以人为本......
         测试,这一点是我一直在思考的地方,也是我一直在努力做的地方,现在还没有做到TDD,也没有做到全面的测试,这点一直是我的一个遗憾,我觉得一个项目如果想要成功的话,还是需要一个专职的测试人员,如果进行TDD的话,如果首次,还需要一个测试辅导人员,我一直在这方面努力,现在只是稍微有些小的成果,但是时间和精力问题还是进展缓慢,这点只能在后面自己一点点的努力。
         现在说说管理的事情,项目需要管,需要对项目管方向,频率,质量,人员等,还需要对项目理,需要理顺项目的各种复杂因素,政治的,其他等等,需要理一下,项目的问题,不能盲目的管,需要不停的整理自己的管的方针,策略等等,及时调整自己的方案。
          作为管理者,不需要事无巨细的什么都过问,但是关键的时候,一定要做出一些抉择,不能让组员总是摇摆不定,这样的话,会耽误时间和打消组员的积极性的。管理者,关键就在于管理上,想想唐僧,我终于明白他为什么是师傅了,他的责任就是领导。他的技术在某些方面是最差的(打怪),但是管理却是一顶一的好手啊,可以把三个个性鲜明的人物管理的井井有条,这个就是管理才能啊。。。
        
November 01

一条快乐的泥鳅

       记得看过这样一个故事,说鱼商需要把鱼运到远方去,到了目的地总是死很多的鱼,这样使的成本总是居高不下,后来发现在里面发一条泥鳅的话,那么就会少死很多鱼,因为泥鳅总是动来动去的,让鱼也跟着动,这样就会让水有了氧气。(故事大概是这样的)
       现在感觉自己在项目中就像那条泥鳅,同事都说我有【洁癖】,我倒是不觉得,就像我现在的MSN签名一样,【我不是一个伟大的程序员,我只是拥有很多良好的习惯】,有时候,我总是有些太极端,不能放下,要求比较严格,看到不太满意的,就觉得浑身难受,就要Refactor,就要改。虽然同事都不是很赞同吧,自己也思考了一下,觉得一个项目,还是需要一个像我这样的泥鳅,时刻提醒着,没事动来动去的,能够使大家整体的要求也会提升一些。不会像温水煮蛤蟆一样,在不知不觉中死掉。
        可能这都是我的一些自我感觉,也是我关于项目管理方面的一些思考,一个项目不能全都是为了进度而工作的,还需要一些为了质量而要求的人,项目的三个元素,时间,质量,频率。三个都平衡好了,才能使项目良性发展,一个项目如果从开始就不要求质量的话,后面也不会要求质量。就像纽约的【破窗户】理论一样,一个城市,如果有一个破窗户不去管理的话,那么这个城市就会迅速沦落成为暴力和犯罪率占据的城市。项目也是一样,自己的代码烂,那么别人会感觉更烂的,那么软件自由越来越烂。
        当然,事无完美,不能无限度的追求质量,什么都有一个度,当超过一定的度的时候,就会得不偿失了。不管最什么都一样,什么都需要考虑一下成本,和自己的可接受程度。
       希望我自己是我说想象的那条让水有活力的泥鳅。
 
No list items have been added yet.