【开发心得】筑梦上海:项目风云录(1)

前言

来到上海以后,从业这么多年,碰到和见到了很多人和事,一直想写个关于软件项目管理的长篇,不过人微言轻的缘故,估计写了也没人看,索性就一直忙于学习和工作。

现在经济状况不好了,似乎项目也没有之前那么多,正好趁这个机会,慢慢的写点儿东西出来,为了自己将来能够回忆一下当年的拼搏,也为了当年一起奋斗的兄弟和同事留个念想。

就从公交ERP这个项目开始吧。

项目之初的争论

这个项目是多年前就完成的,是涉及大型公交企业的ERP系统,当时.net平台刚刚推出,项目组就决定使用C#作为开发语言。

回想起来,这个风险是很高的,在那个foxpro流行的年代,直接用新的开发语言,开发一个默认领域的项目,如果现在让我选择是否做项目经理,大概是没有这个胆量的。

但在当时来说,几乎所有人都很乐观,尤其是年轻的组员,他们认为:

1、可以通过这个项目提升自己的从业经历;

2、又能够用到最新最流行的开发语言;

只这两点,就已经够大家兴奋了。后面他们的跳槽成功,也说明他们的兴奋是有道理的,当然我也从中得到了很多好处。

但当时,由于自己是项目负责人(当时分工没有那么精细,是现在产品经理+项目经理的复合体),只有我是比较担心的,虽然也看好上面的两点,但是更加重视下面两个问题:

1、新语言不熟悉,会拖慢项目进度;

2、缺少领域专家,对公交业务要从零开始学习,难度很高;

由于存在上面的顾虑,所以在项目之初,项目组内部进行了不少争论和吵架。包括组员也进行了不少变动,有组员被调到其他项目的,也有离职的。当然也有新招聘进来的,回头看,这些都是一个软件开发团队正常的变动,只是当时作为项目经理的我,感觉有点儿焦头烂额。

项目误区

再小的公司,也有办公室政治,在当时,虽然得到了直属领导和老板的信任,但由于项目成立之初的人员,并不是我挑选的,里面参杂了各个部门的精英。作为负责项目的我,一开始是很满意的,毕竟这么多牛叉的程序员都归我管。

只要大家一门心思的去开发,困难总是能解决的。不过事实发现,我想的太简单了。以下先说两个误区:

1、关于团结:比如团队里有两个比较要好的员工,平时他们除了睡觉,几乎形影不离,开始我认为是好事,但后来发现,一旦有什么要求不符合其中一人的口味,他们两个会团结起来反对我,造成我只能让步,严重影响了项目任务的分配和进度,也严重影响了我的权威。

2、关于工作气氛:项目之初,老板送给我3本书,名字不太记得了,但都是微软团队管理方面的书籍,我利用晚上的时间全部阅读了一遍。里面讲了很多调动团队气氛的方法,也就是“团建”。后来发现,国内团队应用最多的是“搓一顿”。因此,也经常请团队成员吃饭,甚至是自掏腰包。但并没有收到很好的效果,对项目的进展帮助不大。

造轮子

说了这么多非代码的事情,下面是关于开发上面的重点。

现在可能稍微有经验的程序员都知道,接触到一门新语言,开发一个新项目,最重要最紧急的事情就是赶紧造轮子。不过我这里说的造轮子可能还有一层含义,是项目管理的造轮子。

不过还是先说代码领域的造轮子吧。

记得当时又要学习新语言,还要跟着甲方学习业务,回到团队还要把任务分解安排好,并协调项目进度,有些心力憔悴,好在当时精力充沛,熬夜也扛得住。

前后团队共有2个程序员参与并编写了造轮子的工作,其中第一个员工还用他的名字拼音作为类库名称放在整个项目中,因为表现突出,我默许了。

前面忘记说了,当时BS结构还没有流行,浏览器也没有现在这么强大,考虑到业务的复杂性,最终采用了CS结构,所以轮子也集中在控件上,下面罗列一些古董级别的文本框代码欣赏一下吧:

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace Traffic.ControlLib
{
	/// <summary>
	/// CTextBox 的摘要说明。
	/// </summary>
	[ToolboxBitmap(typeof(TextBox))]
	public class CTextBox : System.Windows.Forms.TextBox, Traffic.ControlLib.IDataControl
	{
		/// <summary> 
		/// 必需的设计器变量。
		/// </summary>
		private System.ComponentModel.Container components = null;
		const int DEFAULT_COMPLETE_LENGTH = 0;
		private int m_CompleteLength = DEFAULT_COMPLETE_LENGTH;
		private Queue retQueue = null;

		public bool ValidateResult = true;

		public CTextBox()
		{
			// 该调用是 Windows.Forms 窗体设计器所必需的。
			InitializeComponent();
		}

		/// <summary> 
		/// 清理所有正在使用的资源。
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary> 
		/// 设计器支持所需的方法 - 不要使用代码编辑器 
		/// 修改此方法的内容。
		/// </summary>
		private void InitializeComponent()
		{
			// 
			// CTextBox
			// 
			this.Validated += new System.EventHandler(this.CTextBox_Validated);
			this.Enter += new System.EventHandler(this.CTextBox_Enter);

		}
		#endregion

		private String[] GetCustomList(Queue q)
		{
			if(q.Count!=0)
			{
				String[] retArray = new String[q.Count];
				q.CopyTo(retArray,0);
				return retArray;
			}
			return null;
		}

		private void CTextBox_Enter(object sender, System.EventArgs e)
		{
			if(retQueue == null||(retQueue.Count==0))return;
			// create an AutoComplete object
			ShellLib.ShellAutoComplete ac = new ShellLib.ShellAutoComplete();
		
			// set edit handle
			ac.EditHandle = this.Handle;

			// set options
			ac.ACOptions = ShellLib.ShellAutoComplete.AutoCompleteOptions.None;
			ac.ACOptions |= ShellLib.ShellAutoComplete.AutoCompleteOptions.AutoSuggest;
			ac.ACOptions |= ShellLib.ShellAutoComplete.AutoCompleteOptions.AutoAppend;
			ac.ACOptions |= ShellLib.ShellAutoComplete.AutoCompleteOptions.UpDownKeyDropsList;
		
			// set source
			ShellLib.SourceCustomList custom = new ShellLib.SourceCustomList();
		
			custom.StringList = GetCustomList(retQueue);
			ac.ListSource = custom;
		
			// activate AutoComplete
			ac.SetAutoComplete(true);
		}

		private void CTextBox_Validated(object sender, System.EventArgs e)
		{
			if(this.retQueue == null)return;
			if(this.retQueue.Count>=this.CompleteLength)this.retQueue.Dequeue();
			this.retQueue.TrimToSize();
			this.retQueue.Enqueue(this.Text.Trim());
			this.ValidateResult = true;
		}

		private void OnKeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
		{
			//MessageBox.Show("keydown");
		}

		[	
		Category("Custom"),
		Description("To set or get the ListDown length for auto complete."),
		DefaultValue(DEFAULT_COMPLETE_LENGTH)
		]
		public int CompleteLength
		{
			get
			{
				return  m_CompleteLength;
			}
			set
			{
				m_CompleteLength = value;
				if(m_CompleteLength != DEFAULT_COMPLETE_LENGTH)
				{
					retQueue = new Queue(m_CompleteLength);
				}
			}
		}

		[Category("Custom"),Description("To get or set the value of this control.")]
		public string DataValue
		{
			get
			{
				return this.Text.Trim();
			}
		}

		public bool PutEntityToValue()
		{
			try
			{
				this.Text = this.Tag.ToString().Trim();
				return true;
			}
			catch
			{
				this.Text = string.Empty;
				return false;
			}
		}

		public bool PutValueToEntity()
		{
			try
			{
				this.Tag = this.DataValue;
				return true;
			}
			catch
			{
				try
				{
					this.Tag = string.Empty;
					return false;
				}
				catch
				{
					this.Tag = 0;
					return false;
				}
			}
		}
	}
}

陆陆续续的,一共造成几十个各类轮子,给开发统一和快捷带来了极大的便利。这两位造轮子的同事,一直到现在都很欣赏他们,可惜后来各自都离开了公司,奔向了更大的前途空间。

未完待续。。。

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值