2007年8月8日星期三

80%完美的程序员

如果你有一个王葆的宝葫芦,你会向他许什么愿?变形金刚的电影票?100个IPHONE?

也许吧……不过如果是我,会请他给我一个80%完美的程序员。只所以不要一个100%完美的,是因为我害怕我需要写一份100%完美的需求文档,宝葫芦才能100%完美的理解什么是100%完美的程序员。

首先一点,我希望他来面试的时候,技术笔试能答80分以上。当年我找工作的时候,看到一个考官把不合格的试卷全部撕掉,觉得他这样是对应聘者的污辱,所以我不会这样做,我只是会把不入流的试卷和答卷人的简历拿来做草稿纸——最近草稿纸越来越多,让我觉得很对不起我国脆弱的生态环境。真的,大部份技术笔试的题目,都是非常简单的,而且很多时候出试卷的人偷懒从网上找题。所以,面试之前能充分准备一下,其实80分是很容易的。

其次,我希望他的简历至少是诚实的,分的清楚“精通”,“熟悉”,“了解”。我问过很多精通TCP/IP的人,TCP和IP是什么意思,大部份的人回答不知道。这让我觉得就好像一位自称大师的厨子告诉我他不知道猪肉是猪身上的牛肉是牛身上的人肉是人身上的。

然后,我希望他至少真的“精通”某一个方面,可以和我侃侃而谈,主导一次面试的过程,省我在他回答不出问题的时候老逼着自己想编问题,以避免“这么快就结束是不是会太挫伤他的积极性”的出现。

接下来,我喜欢可以和我谈一点抽像的东西的人。这是我的个人倾向,但当每一个面试的人都说“我很喜欢做程序员”,却又说:“我没看过什么深一点的相关书籍”时,我不得不怀疑“程序员”这份工作对他来说只是混口饭吃。我所认识真正喜欢这一行的人,无不是喜欢看一些“稀奇古怪”的计算机读物打发时间,经常头发蓬松,衣冠不整的家伙。(后两条可选,面试的时候不必刻意)

还有,英文阅读能力要好一点,遇到问题的时候可以到用英文查资料;搜索问题答案的能力强一点,因为很多时候别人没空教你;打字的能力强一点,至少不用二龙戏珠那么痛苦。

面试其实有点像谈恋爱,面试官的主观好恶有很大成份在里面;不过就像漂亮女生人人爱一样,达到80%的程序员,我想大部份人还是会喜欢上的。
在.NET 2.0应用程序中使用BackgroundWorker组件

年7月3日

BackgroundWorker可以让窗体异步地完成一个操作。在我们需要执行诸如『数据库事务』或者『图片下载』之类的操作时,这个功能非常有 用。此时,我们的可以让用户界面停止响应(或者隐藏起来直到操作结束)。在这篇文章中,我会一步一步教会你如何在.NET 2.0程序中使用BackgroundWorker组件以便处理较耗时的操作。示例程序使用C#编写。

与往常一样,我们创建一个测试工程,取名为"TestBGW",使之只包含一个窗体("FormBGW"):



图1.

我们将使用BackgroundWorker完成一些数据库的事务操作(比如,获取一些DataTable)。首先拖一个BackgroundWorker组件到我们窗体上。

图2.

我们将用DataTable来设置DataGridView1的DataSource属性。我们还应该刷新我们的用户界面,并告诉用户:所有的操作已经全部“OK”,他/她不用再操心啦。因此,我们还要需要一个StatusStrip和一个Timer.


图3.

为了让用户看到我们的处理过程正在运行之中,我们将用到toolStripProgressBar1:

图4.

用toolStripStatusLabel1和toolStripStatusLabelTime是来向用户显示处理过程的状态和已经花费的时间。

我们窗体看上去是这样子的:


图5.

为了模拟数据库的事务操作,我们将用到 GetData.dll(当然你也可以连接到一个真实的数据库;这个模拟的目的只是为了测试而已)。出于这个目的,我们把GetData.dll添加到引用中,然后写因getDataTable方法:

private DataTable getDataTable(int Rows)

{

GetData.GetDataHelp getData = new GetData.GetDataHelp();

return (getData.getDataSetCities(Rows).Tables[0]);

}


我们调用RunWokerAsync方法开始我们的异步操作:


private void FormBGW_Activated(object sender, EventArgs e)

{

backgroundWorker1.RunWorkerAsync();

}


BackGroundWorker组件有三个事件:

图6.


DoWork事件发生在RunWokerAsync方法被调用时。在这个事件的处理函数中,我们“完成”那些的耗时的工作(我们载入至少100000行数据以便使我们的处理过程变得“耗时”),并通知用户载入工作正在进行中,最后将我们的DataTable置为我们的异步操作的结果。


private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

{

DataTable dt;

toolStripStatusLabel1.Text = "Loading ... " + "Thanks for your patience";

dt = getDataTable(1000000);

e.Result = dt;

}


就我们面对的情况而言(我是指真实的情况,即从数据库获得一些DataTable的情况),我们没办法“插入”处理过程以“追踪”已获取的数据行数量(一行接一行)。当然,我们同样也没有办法知道,根据我们的请求最终可以从数据库获得多少数据行。所以呢,我们不会用DoWorkEventArgs(译注:应为BackgroudWorker的笔误)的ReportProgress 方法来触发ProgressChanged事件。我们将用Timer1,向用户显示处理过程正在进行中(我们将把 toolStripProgressBar1“增加”到最大程度,然后再从最短长度继续开始;就是说,我们会制造一些循环)。因此我们给 timer1_Tick加上下面的代码:

if (toolStripProgressBar1.Value == toolStripProgressBar1.Maximum)

{

toolStripProgressBar1.Value = 0;

}


为了让用户知道加载已经花费了多长时间,我们还得给这个方法加上一点代码,比如这个样子:

string sTime =" ..." + ts.Minutes.ToString("00") +

":" + ts.Seconds.ToString("00") +

":" + ts.Milliseconds.ToString("000");

toolStripStatusLabelTime.Text = sTime;


其中ts指现在的时间(参见下面完整的代码)。

顺便说一句,如果仅仅为了测试ReportProgress如何工作,你可以给backgroundWorker1_DoWork方法加上下面的代码:

//-------to try percentage ...

int iMax = 100000;

for (int i = 0; i < iMax; i++)

{

backgroundWorker1.ReportProgress((i * 100) / (iMax - 1));

}


然后把这些代码加入到backgroundWorker1_ProgressChanged :

private void backgroundWorker1_ProgressChanged(object sender,ProgressChangedEventArgs e)

{

//-------to try percentage ...

toolStripProgressBar1.Value = e.ProgressPercentage;

toolStripStatusLabel1.Text = "Loading ... " +

e.ProgressPercentage.ToString() + "%";

//-------------------------

}


RunWorkerCompleted事件发生在后台操作完成的时候。此时我们将“关闭”所有的关于加载的提示信息,并且把通过使用事件的参数RunWorkerComletedEventArgs,把dataGridViewCites绑定到dataTable:

dataGridViewCities.DataSource = e.Result;

FormBGW.cs的全部代码如下:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace TestBGW

{

public partial class FormBGW : Form

{

public FormBGW()

{

InitializeComponent();

////to try percentage ...

//backgroundWorker1.WorkerReportsProgress = true;

}

#region "forClass"

DateTime startDate = DateTime.Now;

#endregion

private void FormBGW_Activated(object sender, EventArgs e)

{

backgroundWorker1.RunWorkerAsync();

timer1.Start();

}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

{

DataTable dt;

toolStripStatusLabel1.Text = "Loading ... " +

"Thanks for your patience";

dt = getDataTable(1000000);

////-------to try percentage ...

//int iMax = 100000;

//for (int i = 0; i < iMax; i++)

//{

// backgroundWorker1.ReportProgress

// ((i * 100) / (iMax - 1));

//}

////-------------------------

e.Result = dt;

toolStripStatusLabel1.Text = "Please, wait ...";

}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)

{

////-------to try percentage ...

//toolStripProgressBar1.Value = e.ProgressPercentage;

//toolStripStatusLabel1.Text = "Loading ... " +

// e.ProgressPercentage.ToString() + "%";

////-------------------------

}

private void backgroundWorker1_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)

{

toolStripProgressBar1.Value = 100;

dataGridViewCities.DataSource = e.Result;

toolStripStatusLabel1.Text = "";

toolStripProgressBar1.Value = 0;

timer1.Stop();

toolStripStatusLabelTime.Text = "";

}

private DataTable getDataTable(int Rows)

{

GetData.GetDataHelp getData = new GetData.GetDataHelp();

return (getData.getDataSetCities(Rows).Tables[0]);

}

private void timer1_Tick(object sender, EventArgs e)

{

TimeSpan ts = DateTime.Now.Subtract(startDate);

string sTime =" ..." + ts.Minutes.ToString("00") +

":" + ts.Seconds.ToString("00") +

":" + ts.Milliseconds.ToString("000");

toolStripStatusLabelTime.Text = sTime;

if (toolStripProgressBar1.Value ==

toolStripProgressBar1.Maximum)

{

toolStripProgressBar1.Value = 0;

}

toolStripProgressBar1.PerformStep();

}

}

}


现在,如果我们运行我们的工程,我们会看到:


图7.


加载结束之后:


图8.


结论


我希望这篇文中可以帮助你在你的.NET 2.0程序中使用BakcgroundWorker组件以便执行一些耗时的操作。


祝好运与编程同在!


--------------

译者的话,这是我在译言翻译的第一篇。从我的角度讲,我是不赞同一个看不懂这篇文章原文的人做程序员的。不过我天生不爱放弃,既然接下了翻译任务,就完成了它吧。

作者超喜欢用we/our,我酌情删去了一些,不过还是有太多的“我们”。

2007年3月6日星期二

Do u like coding?

Recently I am thinking about the meaning of my current job. I like coding and I like studying new things in my job. When I see my ideas realized in our production, I always feel happy.

But sometimes when I compare my program with these of top level companies in this area, I can clearly see that what I have made was very clumsier than theirs. And I can often see these ideas that I created had already been used in other programs years ago.

If something I was not best in the world and if there nothing new in it, what's the meaning of my job?

People write programs having the same functions again and again, why do they do that? Isn't it a waste of time and life?

2007年3月5日星期一

Once upon a time, I had a design.

At the end of last year, I was planning to use turbogears in a really huge product, but now it's impossible. But still I thought my ideas are not bad. That's it:






Device Server would take in charge of manage all the devices. And Web Server is in charge of giving both the CS and BS User Interface.

The most import idea is how 2 physical servers communicate with each other and form a single system for the user. Sharing the load but giving an seamless to the user was our g

That's easy. Web Server 1 would behave just like a Client Software and do what ever the user want.

And I think it's really easy for our friend companies to create their own Client!

But it is all over, my boss doesn't like anything he could not understand.

TIPs for using utf-8 in TurboGears

I first posted this at http://docs.turbogears.org/1.0/UnicodeTips
------------------
Hi all, I'm from China and have recently been studying turbogears. I hope this will help people from countries where languages other than English are spoken. Please point out any mistakes. Each message will be short, but I will keep replying to this thread frequently.

TIP 1.

Better use utf-8 in kid files.

TIP 2.

If a column might contain non utf-8 characters, define it like this in model.py:

UnicodeCol(dbEncoding = "gb2312")

TIP 3.

You want to use standard widgets but you find it doesn't work with Chinese! Then you should:

  1. Add this at the top of your code: # -*- coding: utf-8 -*-
  2. Convert your source file to utf-8
  3. Add a u before any string that contains a Chinese character. (this third one is a must!)

TIP 4.

Something interesting. If you have ever tried the 20 minutes wiki tutorial, run it and type something like this in your browser's address box.:

http://localhost:8080/一些中文字符

Press Enter. As the page does not exist, you will reach the Edit page. Input some text and then save.

Oops! Something wrong happened but if you check the database you will see a new page has been added. This might be a bug, I will see if I have time to fix it.

TIP 5.

If you are using MySQL on windows, use MySQL-python.exe-1.2.2b1.win32-py2.4.exe or you will encounter big problems when you want to execute some SQL containing Unicode.

TIP 6.

If you are using mysql, change your dburi to this form:

sqlobject.dburi="mysql://username:password@hostname:port/databasename?charset=utf8&sqlobject_encoding=utf8

The first encoding tells MySQLdb what charset mysql should use, the second one tells sqlobject how to give MySQLdb a unicoded sql.

TIP 7.

Remarks on TIP 6.

When you're using mysql, you have to use byXXX functions like this:

user = User.byName(u'UserName'.encode('gb2312'))

Unicode strings are not accepted. That's why you need to include sqlobject in your dburi.

That's definitely a bug of sqlobject.

If you want a fixed version, you should use CVS to get the latest version.

2007年3月4日星期日

My skills

Skills

  1. Grasp C language; 2 years of practical coding experience in C. Comprehend python and familiar with many famous open source projects based on python.
  2. Familiar with Windows application development with C# and Object-oriented programming. Know design pattern in C#.
  3. Familiar with VOIP (Voice over IP) and SIP (Session Initial Protocol).
  4. Familiar with LINUX environment, worked under Cygwin and Linux. Know VSS, CVS, and Clearcase mechanism;
  5. Familiar with common used Object-Relational DBMS, such as MS SQL Server, MySQL, Sqlite, and PostGresSql.
  6. Familiar with popular GIS and Web GIS development tools.
  7. Familiar with popular Rapid Web Development frameworks and open source web UI libraries.
  8. Quite familiar with VIM.

Current Position

Project Manager, lead a group of 7 programmers, participate in developing a really large IP surveillance system base on SIP, in charge of the Client Development.

Daily Work

  1. Resolve technique problems, both the entire design and practical programming problems.
  2. Project management: make plan, watch over the progress, training freshman.
  3. Give technique advice for other groups and products.
  4. Many general affairs, such as reporting to our Product Manager, communicate with customers, and so on.
  5. Think about future plans of our product.

Computer is never wrong.

Yesterday, one of my co-workers told me, "Peter, there is something wrong with my computer. It's very very weird. I am sure my code is correct, but it doesn't work!"

I check his code and found that he misspelled a variable.

After that, I made some comment. "In my experience, computer is never wrong. It's always people who made mistakes. And that's why I decided to major in computer science. I thought the world is a unfair place, but in computer, 1 plus 1 is always equal to 2."