career’s funs – 1

ome fun warning stickers for use in software industry! 😀 We have tons of these kind of software, especially on Windoze. They make me remember a trial some years ago, in which a company had admitted that its optimization software does nothing at all but just slow down the installing machine a bit!

Warning: bloat-ware! This software will eat up half your hard drive. This software comes loaded with all sorts of fancy screens which require tons of bitmapped graphics. Of course we could have used simpler screens, but the the product wouldn’t look as good in the advertising brochure.
Warning: ad-ware! This product contains advertisements for all of our other products. The software you paid for is 20% software and 80% multi-media presentations designed to get you to buy our upgrade. Some of our best programmers worked on these demos so you’d better take a look at them.
Warning: version numbers ends in .0! The version number of this software ends with a .0. That means that we’ve added a lot of new features and tested none of them. If you really want software that works, wait for the maintenance release due out in about three months.
Warning: fritter-ware inside! This software has thousands of options allowing you to customize it extensively. In fact, without much trying, you can spend all your time customizing the software and none doing real work.
Warning: nag-ware! If you don’t register this program, it will nag you every five minutes until you do.
Warning: air-ware! This box contains a single floppy, a two page manual and 352 cubic inches of air. The reason the box is so big is that we wanted you to feel good about shelling out $250 for this product.
Warning: manual written by engineer! The manual has been written by our engineering staff. Our engineers understand lots of languages such as C, Java, C++ and FORTRAN. Unfortunately one of the ones the don’t understand is English. But we let them write manuals anyway. They’ve created a master work containing a lengthy description of the theory of operation, the algorithms design, the data structures, and the new technology used. Oh, and at the last minute they’ve even added a few pages at back on how to use the thing.
Warning: nothing-ware! We don’t guarantee that this software will do anything. When you pay us money you don’t even get a copy of the software to own. Instead you get a single license to use it. If it fails to work, crashes, or wipes out data, we absolve ourselves of any responsibility. Basically, we have all the rights, you have no rights, and you pay us money.

signals and slots

C makes U hang yourself;
C++ even gives U a rope object to hang;
C# scourges U using a rope wrapper!

rarely talk about programming unless it comes to some new idea or something fun. However, in this article, I’m going to summarize a part of experiences in my career, about important concepts that I’ve learned and used: signals and slots. First appear and remain as fundamental concepts in the Qt library (“Qt” pronounced “cute” – which is so cute as a cross-platform application framework), the concepts has been adapted and developed into some other libraries (such as boost) and are being proposed as next standards for C++ language.

Please note that we’re talking C/C++ here, although signals & slots has been brought to many other languages (Java, Python, Ruby, JavaScript, etc.) Every coin has two sides and C/C++ is no exception, it has its own advantages and disadvantages (depend on types of applications). But the thing I like about C/C++ is that its half – civilized nature made it a strong language: the balance between abstraction and comprehensiveness has always been considered as core factor.

Noone want to build general applications using Assembly, and noone want to write lengthy code just for some simple features. To adhere the doctrine, strong – abstraction concepts must be introduced to capture grammar of the language, and simple, clear syntax that would make the code concise and comprehensive.

I came to signals & slots as solution to problems I’ve met when leading the CMS project, a DVRs managing software (client & server) with complicated GUI: a few screens, each screen can have a dozen tabs, each tabs can have hundreds of controls. Events on one control can affect other controls on other tab or screen, events can be user inputs as well as various signals come from dozens of (managed) network client machines.

The overwhelmingly – complicated communications surpass every MPM (message passing method), then signals & slots appeared as a saviour solution. To be simple, signals & slots is a very efficient mean of interaction between objects within a process space. I personally think it would be the next metaphor extension added to C/C++ language. Structure of this post would be as follow:

1. Introduction to signals & slots, from raw to abstract concepts.

2. ISO C++ compliant and cross – compiler, cross – flatform problems (would discuss about delegate and how function pointer has evolved from C to C++).

3. Different implementations of signals & slots: Qt, boost, sigslot, libsigc++


Flow of code is no more than a series of function call, and to perform asynchronous function call, traditional C programming use callback. A callback is a pointer to a function, so if you want a processing function to notify you about some event, you pass a pointer to another function (the callback) to the processing function. Callbacks have two fundamental flaws: firstly, they are not type-safe, we can never be certain that the processing function will call the callback with the correct arguments. Secondly, the callback is strongly coupled to the processing function since the processing function must know which callback to call. In C, to define function pointer, you would write something like this:

float (*my_func_ptr)(int, char *);
typedef float (*MyFuncPtrType)(int, char *);
MyFuncPtrType my_func_ptr;

When move to C++, things are a bit more complicated (note the weird syntax ->* to call a member function through pointer).

float (SomeClass::*my_memfunc_ptr)(int, char *);
my_memfunc_ptr = &SomeClass::some_member_func;
SomeClass *x = new SomeClass;
(x->*my_memfunc_ptr)(6, "Another Arbitrary Parameter");

Though a very strong concept in C, function pointer add little to the language C++. The only two uses of member function pointer in C++ are:

  • Demonstrate the tricky syntax of the language.

  • Help in implementation of delegate.

Now, imagine slots as invisible communication channels, every object can register to listen to some channels by providing delegates (pointer to a member function). The delegate would be invoked when slot is “filled” with a signal. The signals and slots mechanism is type safe: signature of a signal must match signature of the receiving slot. Signals and slots are loosely coupled: a class which emits a signal neither knows nor cares which slots receive the signal. To summarize the benifits:

  • Syntactically neater: signals & slots make for very readable code: you define the signals, you define the slots, then you wire them up.

  • Inherently robust: when either end of a signal/slot connection is destroyed, the connection is automatically removed. It is therefore impossible to emit a signal and have it arrive at a class that has already been deleted. Best of all, you don’t need to write any cleanup code.

  • Easier code reuse: since the thing that has to type-agree is the signal and the slot, not the whole class interface, it is much easier to plug together disparate classes that had never initially been intended to work in that way.


To summarize section 1: pointer is the root of all evils. Function pointer is the physical of callback method traditionally used in C programming. When evolved to C++, the C++ standard committee failed to address how to define function pointer to a single C++ object. With common-sense knowledge, we know that it take two elements to represent the thing: first is the address of the object itself (the implicit pointer this), second is pointer to the object’s member functions. The undefined land leads to different implementations across various compilers.

Contrary to common belief, the actual physical storage of pointer differs between various compilers, and even differs between types of pointer, e.g: pointer to a single – inheritance object, an multiple – inheritance one or virtual inheritance. The table below shows how many bytes it take to store pointers on different compilers (just make use of the operator sizeof). Then to calculate the actual member function’s address, each compiler uses one kind or another of offset:

struct BorlandMFP
        CODEPTR m_func_address;
        int delta, vindex;
if (vindex==0) adjustedthis = this + delta;
else adjustedthis = *(this + vindex –1) + delta;
MS VC++ 4 4 4 8 12
GNU G++ 4 4 8 8 8
Borland C++ 4 4 12 12 12

So, delegate is just the new name for pointer to (an object’s) member function. The hard part really is that: since each compiler stores different type of pointers differently, there’s need for a way to store delegate in a universal manner: cross compilers and cross flatforms. Various techniques have been proposed by excellent programmers. Please refer to the articles below for specific techniques. I personally would prefer the method of Quynh Nguyen, an engineer at Global Cybersoft (Vietnam) Ltd.


To make those obscured concepts above clearer, I would go into some detailed implementations of signals & slots with the emphasize on the sigslot library, for this is really a compact lib: everything is contained in just one header file. Suppose you have a server that would receive some signal from network (tcp socket), then parse the received data and trigger some processing (display on GUI, store to disk…). We would define the “network signal” as follow (please note any number of parameters can be defined, we use an int and a char* here just for the example):

// the temmplate ‘signal2’ denote for
// a signal with 2 parameters

signal2<int, char*>m_netSig;

Then, at the place you want to process that event, e.g some class CDisplayForm, you would need to provide a function to process the signal:

DisplayForm::OnNetSig (int cmd, char* data)
  // the delegate would be invoked
  // when the signal is recieved


Please note that multiple objects can register to a same signal slot (and vice versa), e.g some class CRecordThread would also need to log that event to database. Then the listening objects would just register with the signal slot using a connect function:

// we pass the function pointer
// here to be called later

m_netSig.connect (this, &CDisplayForm::OnNetSig);

When the network signal arrive, e.g in some class CAsyncSocket, we would fire the signal and get it populated to all connected objects:

// emit the signal with it’s data
m_netSig.emit (NETSIG_DATA_RECEIVE, xmlStr);

Then the CDisplayForm and CRecordThread object would both receive the signal. Please note that when either end of the communication channel go out of scope, the connection is automatically removed, you don’t have to write any cleanup code. Just define the signal, the slot and wire them up! Any unrelated classes can be wired up in this type-safe manner without any pre-defined relation within them.

Speaking as an ex-hardware designer, I’d like software components to have pins around their edges, like ICs, so they can be ‘wired up’, but otherwise should be well behaved… I don’t want to know how that pin is wired internally – I just want to know that it will work when I send a signal into it.
(Sarah Thompson – sigslot library)

ipix fish-eye camera

the dome camera and it’s Nikon fish-eye lens

Image above: Ipix’s raw format (spherical image). Click to try the Ipix static image viewer in a separate window, which helps to view a single Ipix’s frame, wrapping from raw format to normal rectangular format (not the video).

his is among the most interesting things I’ve ever worked on: Ipix’s CommandView™: fish-eye cameras which provide a 360° x 180° field of vision. This camera and it’s technology were very special and advanced at the time, about 3, 4 years ago, it were so new that the manufacturer could not survive the small market share and went bankruptcy. However, the technology has now revired at The camera came with some totally new concepts, patents and technologies. Some information on Ipix:

Ceiling or wall-mounted, with thick hard steel cover, the camera is designed to operate indoor or outdoor, and can withstand a temperature range from -40°C to 60°C. It costs about $2100 at the current time, and about $5000 when it first appeared. CommandView™ Dome is an IP camera, having a small Linux computer inside, once plugged onto LAN or WAN, the camera turns into a video server and can stream video in many protocols: http, ftp, rtp, or multicast. There’re 3 ways to control the camera: ssh to the Linux machine, access to it’s web-server or programatically use the XML-RPC interface. The product has a very matured and solid development flatform.

CommandView™ Dome is a mega-pixel camera (2 MB, 3 MB). The unique feature of this product is that it provides a 360° x 180° field of view with no moving parts. See the image beside (on the left – click to view a mega-pixel version), every details in the room is captured on a parabolic sphere (called wrapped image). To have a normal view, a region on the sphere is dewrapped (by software) into usual rectangular plane.

Since a whole 360° space is captured, PTZ (pan / tilt / zoom) is just a matter of dewrapping, there’s no need to motorize the camera for different sighting fields. This special camera has broadened the definition of ‘panorama’ and has many applications in security surveillance as well as photography. I myself found it very interesting to apply the concepts and softwares to demonstration and show-case purposes (search for ‘ipix’, the name has gone far beyond just a type of camera).

CMS 2.0 released

Some typical UI features:

Data & input validation using XPath

Custom-drawn combobox (with check-box item)

Custom-drawn grid with tens of thousand cells

Simple vector object editing

Custom-draw tree with loading effect

he CMS project, in which I’m the team leader, has come to it’s second phase, with major features completed. Although I felt tired with the on-going work, it’s my most beloved product. CMS (short for Central Management System) serves as a gateway through which clients manage the DVR Servers (Digital Video Recorder). The product demonstrates many technologies & programming techniques, just to name a few:

  • IOCP (IO completion port): the multi-threaded IOCP server has proved to be very efficient, hundreds of concurrent connections won’t rise CPU usage to higher than 5%. However, the connections are stateless, it’s best that we would add a state-machine to better control the traffic.

  • TCP + XML communication: we devise a draft protocol like XML-RPC or SOAP, which bases on TCP rather than HTTP.

  • XML data storage: all network command & data is presented in XML. With version-numbered XML, we hope to solve the backward compatibility problem ever existed with so many releases of our main DVR products.

  • XML processing is made easy thank to the wonderful TinyXML and TinyXPath libraries. I must emphasize that XPath makes XML processing much more feasible, it greatly reduces the number of LOC (line of code) and procedural complexity.

  • A sophisticated client MFC GUI demonstrates various GUI programming techniques, almost every tricks with MFC GUI has been gathered in this product: heavy custom-draw controls, flicker-freed rendering, advanced input validation…

  • Some borrowed concepts from other flatforms: the elegant “signal & slot” are added to handle complicated interaction between GUI’s elements (in addition to MFC’s message queue mechanism).

I have some lessons learned after the project:

  • It’s a MUST that you have a team with members of the same professional level. This would make sure the members would easily understand each others and share a common culture.

  • C/C++ is still a MUST for real time programming tasks (it’s “half-civilized nature” makes it a strong language). And the use of some matured flat-form: boost, wxWidget… would greatly help the developing process.

  • It’s only by the desire for creation & creativity that programmer would offer an excellent product. The culture of a developing team is somewhat like honey-bees, who collect pollen little by little to make honey and wax.

I’ve been involved in many projects, some is more interesting, some is more difficult than this one. But this is the first one that I’d made, everything from A to Z. It’s now time to leave I3 but I must say this is the project that I loved and two years at I3 was a special time in my career! Looking at the screenshots below, you would see that CMS is very rich in it’s designs about information presentation.

a Japan that can fail

ave you ever asked yourself why 80 percent of software projects fails, why there’s so much argues and debates in our IT community? If you have the courage to look deeply into yourself, to see our nature and the nature of the IT field, you would figure out things quite easily. Pity that most people can not do this. I read the article below for quite some times. It’s idea is quite straight-forward, however, I made a Vietnamese translation for one who still can not get it.

Bạn thân của bạn muốn nói với bạn một số điều mà anh ta biết có thể làm bạn đau. Cả hai cùng đến một câu lạc bộ riêng tư nào đó, nơi không ai khác nghe thấy được. Anh ta không muốn nói một chút nào, nhưng là một người bạn tốt anh ta phải nói. Sau một vài ly, câu chuyện sau đây được kể.


Đối diện những đe dọa đau đớn của sự hủy diệt, các nền văn hóa thường từ chối tự nhận chân chính mình. Họ rút lui vào một xó xỉnh nào đó, bày tỏ thái độ bàng quan, và tìm kiếm an ủi trong những huy hoàng của dĩ vãng. – Fouad Ajami – The New Republic 8/91.

Sau chiến tranh thế giới lần thứ 2, nước Mỹ thống trị kinh tế toàn cầu, hơn bất kỳ thế lực nào khác đã (thậm chí là sẽ) làm được. Dù cho các doanh nghiệp Mỹ tin rằng điều này sẽ kéo dài mãi mãi, đó thực sự là một trạng thái không tự nhiên, các doanh nghiệp ngày càng trở nên nặng nề và lười biếng.

Lấy thí dụ điển hình là công nghiệp ôtô. Vào lúc người Nhật bắt đầu xâm nhập và cạnh tranh trên trị trường này ở Mỹ, thì các doanh nghiệp Mỹ đã trở nên quá thiếu hiệu quả và ngại thay đổi. Điều này khiến người Nhật nhanh chóng chiếm lĩnh những phân khúc lớn của thị trường. Các công ty Mỹ đã quên kỹ năng cạnh tranh trong một thời gian.

Tuy vậy, người Nhật phát triển được nền kinh tế siêu cường của họ, phần lớn dựa vào các ưu điểm của văn hóa Nhật Bản hơn là dựa vào thực tế công nghiệp sản xuất ôtô Mỹ lúc đó đã quá cồng kềnh và kém hiệu quả. Và người Nhật cũng bắt đầu tin rằng sự thống trị của họ trong một số ngành công nghiệp là tự nhiên và sẽ kéo dài mãi.

Còn nguy hiểm hơn, họ cho rằng, áp dụng các phương pháp, công thức Nhật Bản vào các ngành công nghiệp khác sẽ mang đến thành công tương tự. Cuộc sống sẽ là quá dễ dàng nếu chỉ là như thế. Hầu hết doanh nghiệp Nhật Bản còn tin chắc rằng cứ kiên trì phương pháp của mình, sớm hay muộn họ sẽ thành công.

Đây là khởi đầu cho câu chuyện nước Nhật có thể thất bại. Lấy ví dụ trong các sản phẩm mang tính nghệ thuật (phim, đĩa nhạc, phần mềm…) nước Nhật không đóng một vai trò đáng kể nào. Các công ty Nhật có thể mua lại các công ty Mỹ, và thuê người Mỹ làm ra các sản phẩm Mỹ, để bán trên toàn thế giới, nhưng thực sự số lượng sản phẩm xuất khẩu này rất ít. Nhật Bản không thực sự là một tay chơi lớn trên loại thị trường này.

Vấn đề không phải là người Nhật đã không thử. Hầu hết đều nhận ra là làm phần mềm có lãi hơn là phần cứng. Trong thời đại kinh tế thông tin, lãi sinh ra từ các băng đĩa VCR thì ít, mà từ các phim ảnh ghi trên đó thì nhiều.

Vấn đề cũng không phải là họ thiếu những con người tài năng. Một đất nước sản sinh ra được những Yukio Mishima và Akira Kurosawa là đã có đủ những nguyên liệu thô cần thiết để sản sinh những tài năng xuất chúng của thế giới. Nhưng liệu những người như thế có làm việc cho các công ty Nhật không, hay các công ty Nhật có thuê những người đó hay không? Ngày nay, không có chỗ cho Soichiro Honda, người chưa từng tốt nghiệp trung học giữa những nhân sự tất cả đều tốt nghiệp đại học Tokyo và cũng xin vào một vị trí thử việc.

Vấn đề thực sự ở đây là người Nhật xem phần mềm như một ngành kỹ nghệ. Hầu hết các công ty lớn của Mỹ cũng mắc phải sai lầm này, đó là lý do chỉ một số ít công ty lớn của Mỹ thành công về phần mềm (trừ trường hợp của Microsoft, những công ty thành công là những công ty vừa và nhỏ về nhân sự).

Phát triển phần mềm có hai đặc trưng cơ bản khiến nó có tính nghệ thuật hơn là khoa học. Thứ nhất là quá trình thiết kế phần mềm. Phần mềm sẽ tương tác với người dùng như thế nào, và làm sao làm được điều đó? Quá trình thiết kế vừa tiếp diễn, vừa tập trung tại mọi công đoạn. Ngày hôm qua là thiết kế trên nền DOS, hôm nay đã là Windows. Từng ngày một trong quá trình phát triển đều có những quyết định mang tính thiết kế, dù nhỏ, dù to. Bạn không thiết kế phần mềm để rồi sau đó viết một cuốn sách về nó.

Cũng giống như làm phim, bạn không thiết kế đến từng chi tiết rồi sau đó tiến hành. Đạo diễn, người quan trọng nhất của một cuốn phim không thực sự làm việc cho đến khi bắt đầu bấm máy. Đến lúc đó, từng diễn viên mang phần đóng góp trên vai của mình vào cuốn phim, và quá trình thiết kế tương tác và tiếp tục suốt quá trình làm phim. Chỉ một diễn viên, hay đạo diễn tồi có thể làm hỏng bộ phim, cũng như cách một lập trình viên kém làm hỏng toàn dự án.

Đặc tính thứ hai của phát triển phần mềm là: quá trình giải quyết vấn đề cần đến những cải tiến liên tục. Mỗi ngày lại có một lập trình viên nào đó có một cách tốt hơn để giải quyết vấn đề. Nếu bạn cứ phụ thuộc vào những phương pháp cũ, phần mềm của bạn sẽ lạc hậu rất nhanh chóng. Một đối tượng hiển thị phông chữ cố định (fixed font) sẽ không được dùng (cho dù bạn test nó nhiều như thế nào) nếu mọi người đều muốn dùng phông chữ tỉ lệ (proportional font). Máy tính cũ hơn 5 năm sẽ bị vất đi ở Mỹ cùng với các phần mềm đi kèm với nó.

Và điều quan trọng là: cải tiến và sáng tạo không xảy ra trên dây chuyền sản xuất. Nó không xảy ra vào một giờ cố định trong ngày. Nó không xảy ra khi lệnh và sự vâng lời được xem trọng hơn là ham muốn tạo ra một sản phẩm nổi bật.


Khi tự tin thoái lui, ngờ vực ngự trị. Khi ngại khó, “ti mít” chiếm thượng phong, thì trí tượng tượng, sự chủ động mà mọi công ty cần có để giữ vững tốc độ tăng trưởng bị thách thức bởi những xoi mói, phê bình ác ý. Đây là nguyên nhân khiến cho các công ty trở nên tê liệt và thụ động, ngay cả khi đã có được đồng thuận về vấn đề, về những hành động cần có, và ngay cả về những thay đổi cần thiết. Khi đó, một đề nghị thay đổi sẽ bị kẹt cứng trong một mạng lưới (web) bằng thép không rỉ, cơ hội tồn tại của nó trước những kẻ bàng quan thờ ơ thật quá xa vời. – John Walker – The Final Days, Autodesk, Inc. Information Letter #14

Các công ty Nhật Bản cần phải tự thay đổi. Câu hỏi không phải là phát triền phần mềm theo cách nào?. Không có câu trả lời tường minh nào cho điều đó, tuy vậy, chỉ cần có một thay đổi toàn diện và triệt để trong cách quản lý công ty. Tôi không muốn lặp lại những gì đã viết trước đây (bài Software Design, tháng 11, 1991). Điều quan trọng là vất bỏ phương pháp công xưởng, nhà máy ra khỏi quá trình phát triển phần mềm. Thay vào đó, bạn tạo các nhóm nhỏ độc lập, mỗi nhóm có cách của riêng mình. Bạn sẽ chọn lọc và thay thế các cách cũ bằng những cách tốt hơn. Và mỗi nhóm được tự do đi theo cách của riêng mình, miễn là nó hiệu quả.

Những quy luật cũ, dù tường minh hay ngấm ngầm đều phải được bỏ đi. Cá nhân là quan trọng hơn nhóm, nhóm là quan trọng hơn cả công ty. Mỗi cá nhân đều được khuyến khích SÁNG TẠO. Khi mỗi cá nhân đi lệch một chút trên hướng đi của họ, ý tưởng mới sẽ nãy sinh. Và mỗi người giải quyết một mảnh của vấn đề, công việc được giải quyết theo một cách mới và tốt hơn.

Các công ty Nhật vẫn có thể là những tay chơi lớn vì dù xu hướng cá nhân trong văn hóa Mỹ rất mạnh, điều đó lại không phổ biến trong lĩnh vực phần mềm này. Tôi đã gặp một vài lập trình viên Nhật Bản, khi đi phỏng vấn ở Nhật và ở MSKK (chi nhánh Nhật của Microsoft). Hầu hết những người này, nếu xét riêng, cũng giỏi như những nhân sự giỏi nhất ở Mỹ. Họ đáng được cho những cơ hội được làm việc như những lập trình viên, vì với những người đó, sáng tạo là một phần thưởng cá nhân quan trọng hơn nhiều so với phải làm việc trong một môi trường nhà máy.

Cũng như các công ty ôtô Nhật đã nhận ra rằng nhân sự Mỹ thật sự tốt và đã mở các nhà máy ở Mỹ, các công ty phần mềm Mỹ cũng sẽ nhận ra những tài năng tiềm ẩn trong những nhân sự Nhật Bản và mở những trung tâm phát triển phần mềm ở đây.

Tuy vậy, ngồi không mà không làm gì tiềm ẩn những hiểm họa lớn. Nhật Bản sẽ vẫn còn phụ thuộc Mỹ ở những công nghệ phần cứng cốt lõi nhất. Giải quyết những vấn đề này sẽ phải vi phạm một vài nguyên tắc cơ bản nhất của văn hóa Nhật. Với một số người, cái chết là lựa chọn tốt hơn so với việc đánh mất danh dự.

Nghệ thuật cũng phy lý tính như là âm nhạc. Nó điên khùng trong vẻ đẹp riêng của nó – George Jean Nathan (1882-1958)


Kết thúc những lời này, người bạn tốt nhìn vào chính bạn. Anh ta hy vọng là những lời nói dữ dội này không ảnh hưởng đến tình bạn giữa hai người. Điều quan trọng là anh ta hy vọng bạn sẽ nhìn nhận sự thật này trước khi quá muộn. Vì thường thì khi vẫn đề đã trở nên rõ ràng không chối cái được nữa, thì cũng là lúc đã quá muộn để sửa chữa.


Your best friend needs to tell you something that he knows will pain you greatly. The two of you go to your private club and you sit where no one else can hear you. While your friend’s greatest wish is to not talk about this, he knows that as a true friend he must tell you what he believes. So over drinks he tells you of a problem that he thinks affects your entire future. This is what he tells you.


On pain of extinction, cultures often stubbornly refuse to look into themselves. They retreat into the nooks and crannies of their perceived history, offer up the standard evasions, fall back on the consolations they know. – Fouad Ajami in The New Republic 8/91.

Shortly after World War II, the United States dominated the world economy more than any other country ever has (or probably ever will). Although businessmen in America came to believe that it would continue indefinitely, this was an unnatural state of events and many of our industries became fat and lazy.

The American automobile industry is a prime example. By the time Japanese companies started competing in America, the American companies were so inefficient and resistant to change that the Japanese companies quickly captured a large segment of the market. The American companies had forgotten how to compete.

Japan took its economic accomplishments as a sign of its superior culture rather than a sign of fiercely competitive companies taking on some rigidly structured, inefficient American car manufacturers. As with America after WW II, Japan is starting to believe that its dominance in certain industries is a natural state of events that will continue indefinitely.

Even more dangerous, many Japanese believe that by applying the Japanese method to any industry, they will be able to dominate it too. Life would be so easy if it were so. Unfortunately, when the Japanese method is applied to industries like software it fails. Even more unfortunate, most Japanese companies convince themselves that if they continue to use the same old methods, sooner or later they will succeed.

This is the Japan that can fail. In the world markets for artistic products (movies, records, software, etc.), Japan isn’t even a player. Yes, Japanese companies can buy American companies that hire American workers in America to create American products that sell all over the world; including Japan. However, I doubt that Japan’s exports for these types of products are greater than that of any single European country. This is a market that America totally and unequivocally dominates and Japan isn’t even a player.

This isn’t for lack of trying. Most Japanese companies realize that its more profitable to write software than to build hardware. In the information age, economic power won’t come from building the VCR. It comes from producing the movies on the tapes.

The problem isn’t for lack of qualified people. A country that produced a Yukio Mishima and Akira Kurosawa has the raw talent to produce some of the greatest artistic efforts in the world. However, does anyone think either of these people could ever have worked for a modern Japanese company? Or that a Japanese company would hire them? Where is there room for a Soichiro Honda who never graduated from high school among all of the graduates from Tokyo University competing for entry level jobs?

The major problem is that Japanese companies treat software development as engineering. (Most large American companies make this same mistake which is why you see very few large companies even in America successfully producing software.) Unfortunately, object-oriented programming gives the factory approach a whole new way to become even less efficient. Software companies can now produce object after object and document each one so that someone else can find it and use it.

The problem is that people are now spending a lot of their time documenting their objects and searching for other objects. And when you do find an object, it usually turns out that it’s not quite what you wanted anyway. And finally, even when objects give you what you want, your core problems haven’t been eliminated.

Software development has two basic characteristics that make it an art. The first is the design process. How is the software going to interact with the user and what will it do? This design process is ongoing and occurs at every stage of development. Two years ago programs were written for DOS. Now they are written for Windows, which requires a totally different design. Virtually every day of programming includes design decisions; some big, some small. You do not design and then write a book.

You do not design to the last detail and then shoot a movie. The director of a movie is considered to be the single most important contributor to a movie yet they are generally not involved until the shooting arts. Each actor & actress brings their own interpretation of their character to the movie, creating an ongoing design of the movie. In the same way, just as a bad actor or director can ruin an otherwise great movie, one bad programmer can ruin an otherwise good program.

The second basic characteristic is that problem solving requires constant innovation. Every day some developer somewhere comes up with a better way to solve a problem. If you continue to depend on existing methods, pretty soon your software is so outdated that no one will use it. An object that only displays a fixed font is of no use, no matter how well tested, in a world that now requires proportional fonts. Computers that are five years old are being thrown out in America as useless and the same should be happening with almost all code written that long ago.

Constant innovation and creativity don’t happen on an assembly line. They don’t happen during certain hours of the day. They don’t happen when concensus and order are more important than creating an exceptional product.


When self-confidence fails, caution rules. When timidity and unrestrained risk-aversion gain the upper hand, the kind of imaginative and bold initiatives that companies must make in order to sustain their rapid growth are forced to run a gauntlet of analysis and criticism that no suggestion, no venture not already proven successful, has a chance of surviving. This is the source of paralysis, why companies fail to act even when there is, within the company, a broad concensus that problems exist, action is needed, and even agreement on the nature of the changes required. Even then, each specific recommendation finds itself stuck in a stainless-steel web; the chances of it surviving all the individual sign-offs needed to be implemented are remote. – John Walker in The Final Days, Autodesk, Inc. Information Letter #14.

The world is changing today. Russia has become one of the greatest capitalists of all with its offer to sell the Kurile Islands back. Who would ever have thought that Russia wouldn’t care if Japan gets the islands back as long as they get as much money as possible for them. For the last quarter, Microsoft’s profits were almost as great as those of IBM; a company with 40 times the number of employees. What worked yesterday is no guarantee for tomorrow.

Japanese companies need to change too. The answer isn’t to find a Japanese way to develop software, its to use they way that works – steal it from America. There is no great secret to how to effectively develop software, however, it does require a complete change in how Japanese companies manage software development.

I don’t want to repeat what I have written earlier (see the article in the November 91 issue of Software Design) but essentially the factory needs to be thrown out of the software development process. To replace it, you create small independent teams that will each develop in their own way. You will replace one method with many methods. And each group is totally free to try any way they want – as long as it works.

The old rules, both explicit and implicit must be cast off. The stainless-steel web must be destroyed. Concensus and deliberation no longer dominate. The individual becomes more important than the group. The group becomes more important than the company. Each individual is encouraged to CREATE. And as each developer goes off in their own direction something wonderful starts to happen – new ideas come in. As people solve each part of a problem, it’s done in new and better ways.

Japanese companies can be a major player in the world software market. While the American culture has an advantage with its emphasis on individuality, it’s not an overwhelming one. I met a number of Japanese programmers, both when I was interviewed for a job managing developers in Japan and developers from MSKK (Microsoft’s Japanese subsidiary). Most of these are people who, if let loose, could be the equal of the best in America. Moreover, these people should be given the opportunity to be developers. For most people, creating is much more rewarding personally than working in a factory environment.

Just as Japanese car companies discovered that there is nothing wrong with the American worker and opened plants in America, American software companies will discover the talent hidden in Japanese developers and open software development centers in Japan.

The risks of not acting are great. Japan will be dependant upon American companies for the brains in their hardware. Solving this problem requires violating some basic tenets of Japanese culture. To some, death may be preferable to dishonor.

Great art is as irrational as great music. It is mad with its own loveliness. – George Jean Nathan (1882-1958)


After he has finished your friend looks at you. He is hoping that speaking this bluntly did not hurt your friendship. More importantly, he hopes that you will see the truth before it’s too late. Because by the time a problem is inescapably obvious, it’s usually too late to rectify it.

how to be a good programmer?

fter a while, too tired and indisposed with parts of our commnunity, I try to figure out what I’m expecting myself and others to behave, what are the characteristics that this career requires. Then I found out this how-to document. We’ve seen too many how-to on the web: how to setup Apache with SSL, how to date a girl, how to build your own business … But this is a real how-to, in a programmer’s usual style, concised, practical, and shows a right attitude towards our job. I’ve made a Vietnamese translation of this document. Let taste our career as serious and gentle as it could be.


Lập trình viên là một nghề khó khăn và cao quý. Phần khó nhất có lẽ là làm việc với các đồng nghiệp và khách hàng. Viết chương trình khéo là một kỹ năng lớn, nhưng chỉ là trò trẻ so với những thứ khác mà một lập trình viên phải làm để một hệ thống phần mềm thành công. Trong tài liệu này, tôi tóm tắt ngắn gọn những điều tôi ước có ai đó chỉ cho tôi lúc tôi 21 tuổi. Những điều viết ra đây chỉ mang tính chất cá nhân, và phần nào bảo thủ. Một số vấn đề khá chung nên có thể nghe nhàm chán. Nhưng tôi hy vọng chúng sẽ có ích.

Chào mừng đến với cộng đồng !




Debug là nền móng của công việc lập trình. Nghĩa đầu tiên của động từ debug là sửa lỗi, nhưng nghĩa thực sự cần hiểu là: xem xét quá trình thực thi của một chương trình. Một lập trình viên không biết debug thì xem như bị mù trong nghề của mình vậy.

Những người có cái nhìn lý tưởng về nghề lập trình thường xem lập trình bao gồm thiết kế, phân tích, các lý thuyết về độ phức tạp, vân vân… Nhưng thực sự những điều đó không phảI là những nền móng của nghề này. Chúng ta không sống trong thế giới lý tưởng và ngay cả khi bạn cảm thấy mình là lý tưởng và hoàn hảo thì những điều xung quanh bạn cũng không phải vậy. Phần lớn các mã nguồn đều không hoàn hảo, và tài liệu của chúng càng như vậy. Thiếu cái nhìn vào bên trong quá trình thực thi của một đoạn mã đến lúc sẽ gây rắc rối cho bạn.

Nhiều gói phần mềm được mua từ các hãng thứ ba, và bạn không có cơ hội xem mã nguồn của chúng. Nhiều đoạn mã nguồn thực thi không đúng như tài liệu kỹ thuật của chúng. Nhiều khi bạn viết một đoạn code có lỗi mà vẫn không hiểu vì sao nó gây lỗi (điều này thường là vì bạn đã ngầm định một số điều kiện nào đó, nhưng thực tế những điều đó không xảy ra). Đôi khi đọc kỹ càng từng dòng code một sẽ tìm được lỗi, nhưng nhiều khi không thể phát hiện được chúng bằng cách này. Khi đó thì phải debug thôi.

Những cách debug thông thường:

  • Dùng một công cụ debug
  • In ra từng dòng một
  • Log

Các công cụ debug rất tuyệt nếu chúng ổn định. Công cụ debug của một ngôn ngữ thường phát triển chậm hơn ngôn ngữ đó, nhiều khi bạn không thể tìm được một công cụ debug tốt. Hơn nữa, trong quá trình debug, các công cụ này có thể đã thay đổi quá trình thực thi của chương trình. Nên các công cụ sau là quan trọng hơn.

Nhiều người mới vào nghề thường sợ sửa code khi debug. Nhưng debug cũng như phẫu thuật vậy, bạn phải loay hoay trong đống code với nhiều thử nghiệm khác nhau. Nếu bạn sợ việc này thì tốt nhất hãy tìm sự giúp đỡ ở một người có nhiều kinh nghiệm hơn bạn.


Đầu tiên debug là một công việc thú vị. Nó giống như bạn đi thám hiểm, một không gian bạn nghĩ nó phải như thế này nhưng thực sự nó không giống như vậy. Debug đòi hỏi tính sáng tạo. Và nếu có chìa khóa nào cần biết để debug thì đó là dùng kỹ thuật chia để trị (devide to conquer).

Ví dụ như một đoạn code làm 10 công việc. Bạn viết xong, thế rồi nó crash, mà bạn không viết nó để nó crash. Thế là bạn phải debug, nhìn trên màn hình output, bạn thấy 7 việc đầu tiên vẫn bình thường, như vậy nghi ngờ của bạn là nó có thể crash ở việc #7, #8 hay #9. Như vậy không gian tìm kiếm đã thu hẹp lại. Và luôn có trong đầu một vùng để nghi ngờ như vậy sẽ giúp bạn tìm ra chỗ sai. Rất nhiều khi, một nhóm lập trình viên tập trung cho một lỗi được phát hiện, dưới sức ép của deadline đang đến gần, nhưng dưới sức ép đấy, không ai giữ được sự tập trung trong không gian tìm kiếm của mình, hoặc không biết cách chia xẻ không gian đấy với nhau.

Nó cũng giống như việc thiết kế thuật toán: nếu bạn biết cách chia nhỏ không gian tìm kiếm thì thực sự bạn sẽ không phải chia nhỏ nó quá nhiều lần. Và luôn giữ sự tập trung vào một miền không gian nào đó. Nhưng đâu là miền không gian bạn cần phải tập trung? Đây là vấn đề của kinh nghiệm và sự sáng tạo.

Với người mới vào nghề thì dường như lỗi có thể ở mọi nơi: bạn không có được cái nhìn về các phương diện (dimension) khác nhau của chương trình: các dòng mã, cấu trúc dữ liệu, quản lý bộ nhớ, tương tác với các thư viện bên ngoài… Với người có kinh nghiệm, chính những chiều khác nhau này tạo nên cái mô hình không hoàn hảo nhưng lại có ích để biết được chỗ sai có thể nằm ở đâu. Và nắm bắt được mô hình này sẽ giúp cho việc định hướng trong không gian tìm kiếm.

Không phải khi nào bạn cũng có thể thu hẹp được không gian tìm kiếm đến một dòng mã code nào đó, và nếu như thế thì bạn may mắn. Thường thì lỗi không nằm tại một dòng mã, hay một đoạn mã, mà có thể có tình huống như: “trong đồ thị đó (cấu trúc dữ liệu) có con trỏ nào trỏ sai không?”, và bạn cần viết một chương trình khác để kiểm tra điều này.


Khi bạn đã tìm ra lỗi, tiếp theo là việc sửa nó. Hãy làm theo cách nào đòi hỏi ít thay đổi nhất. Cũng có khi bạn phát hiện ra nhiều thứ khác cần cải tiến, nhưng hãy chỉ làm một việc tại một thời điểm thôi. Nhiều khi có nhiều lỗi trông giống như nhau, hãy định nghĩa từng lỗi riêng biệt và sửa từng cái một. Đôi khi bạn không rõ đoạn mã đó làm gì hay ý tác giả ban đầu như thế nào. Khi đó cần phải thử nghiệm và phán đoán để quyết định ý nghĩa của đoạn mã đó. Đây là một kỹ năng không phải của người mới vào nghề, và thường là khó hơn cả việc viết chúng lúc ban đầu. Nhưng thế giới thực là như vậy, bạn phải sửa nó vì bạn không thể tạo ra nó.


Log khác với việc in ra từng kết quả một tạm thời. Người mới vào nghề cần log vì kinh nghiệm của họ hạn chế. Kiến trúc sư hệ thống cần log vì hệ thống thực phức tạp. Tốt nhất là bạn có thể cấu hình mức độ ít nhiều thông tin trong log-file ngay khi chương trình đang chạy. Log có những lợi điểm sau:

  • Log lưu thông tin về các lỗi khó lập lại (reproduce), nhất là những lỗi chỉ xuất hiện trong hệ thống thực mà không xuất hiện ở các hệ thống test.
  • Log có thể cho các con số thống kê về hiện suất của hệ thống (thời gian thực thi các tác vụ…)
  • Khi có thể cấu hình được, log cho phép bạn sửa những lỗi mới mà không phải sửa hay xem xét lại nhiều các đoạn code chỉ để đối phó với một dạng lỗi ấy.

Quá nhiều thông tin trong log-file sẽ gây rối việc tìm kiếm, quá ít sẽ không có điều bạn cần tìm. Vậy nên cần phải tạo log-file sao cho có thể cấu hình tính nhiều/ít thông tin này được. Mỗi record trong log-file thường có: vị trí trong mã nguồn, thread nào đang thực thi, thời gian thực thi, giá trị của các biến, lượng bộ nhớ còn trống… Những đoạn mã ghi ra log-file có thể ở khắp nơi, cần nhất là ở những chức năng quan trọng và các đoạn mã nguy hiểm (có khả năng gây nhiều lỗi). Mỗi đoạn mã ghi log-file cần được gán một mức độ quan trọng, và bạn điều chỉnh cái gì cần ghi ra bằng cách thay đổi mức độ quan trọng này. Log được thiết kế cho các vấn đề mà bạn lường trước, và luôn lường trước vấn đề hiệu suất của hệ thống.


Vấn đề hiệu suất của hệ thống cũng có cùng lý do như việc debug. Ngay cả khi bạn hiểu một đoạn code đủ rõ, thì không có nghĩa là nó sẽ chạy tốt, đôi khi nó gọi hàm từ một thư viện bên ngoài nào đó, mà bạn thì không kiểm soát được thư viện này. Thực tế thì vấn đề hiệu suất cũng không khác và không dễ hơn việc debug. Nếu hệ thống quá chậm, bạn cần xác định do đâu mà nó chậm, và do đó cần xây dựng một mô hình về vấn đề này. Có câu châm ngôn nổi tiếng là: 90% thời gian được chi trên 10% lượng mã nguồn. Theo kinh nghiệm của tôi, phần lớn thời gian chậm là chi vào các thao tác nhập xuất (I/O) theo cách này hay cách khác.

Có nhiều lý do khác ảnh hưởng đến hiệu suất hệ thống. Nhưng đầu tiên là hãy đo thời gian thực thi của các đoạn mã. Log lại điều này rất quan trọng vì đôi khi chúng cho ta biết tình huống mà các kỹ thuật profiling khác không phát hiện được. Đôi khi một hàm thực thi chậm hơn vài giây so với khi bạn đã sửa chúng, nhưng thực sự thì vẫn tốt hơn vì có thể các chi phí khác (bộ nhớ, băng thông, cơ sở dữ liệu…) sẽ đắt hơn khi đưa hệ thống vào chạy thực.

Các tài nguyên chia xẻ không được đồng bộ hóa đúng có thể dẫn đến deadlock, hay starvation. Nếu có thể hãy lường trước các vấn đề này từ lúc bắt đầu dự án.


Chọn các giải pháp đơn giản và nhanh chóng dưới sức ép của thời gian là một việc làm khôn ngoan. Nhưng hiệu suất là một phần của sản phẩm, và do đó phải cân nhắc vấn đề này kỹ lưỡng. Chìa khóa là: biết các cổ chai (bottleneck) của hệ thống nằm ở đâu, hay chỗ nào tiêu thụ nhiều tài nguyên nhất. Việc tối ưu một hàm chạy nhanh hơn 1% thực sự chẳng có mấy ý nghĩa, và bạn chỉ nên làm điều này khi bạn nghĩ bạn có thể làm cho hệ thống chạy nhanh gấp đôi so với trước. Cân nhắc các chi phí testing và QA đối với những thay đổi này. Ngay cả khi bạn đã làm cho hệ thống chạy nhanh gấp đôi, hãy phân tích lại để tìm ra những bottleneck còn lại, để có thể làm cho hệ thống chạy nhanh thêm gấp đôi nữa.

Thường thì việc tìm các bottleneck sẽ giống như việc đếm bò bằng cách đếm số chân rồi chia cho 4 thay vì đơn giản hơn bạn có thể đếm số đầu. Ví dụ như: không làm chỉ mục cho một trường sử dụng rất nhiều lần trong cơ sở dữ liệu có thể làm cơ sở dữ liệu đó chạy chậm hơn 20 lần. Những cải tiến dạng này thường được gọi là low-hanging fruit, có thể dễ dàng hái chúng để có được lợi ích. Khi những quả ở thấp đã hết, bạn sẽ phải leo lên cao hơn. Bạn có thể cần cù làm những cải tiến nhỏ trên cao này, hoặc bạn có thể thiết kế lại toàn bộ hệ thống. Đây là cơ hội để chứng tỏ bạn là một lập trình viên thực thụ, nhưng chỉ làm thế khi đề nghị của bạn có thể làm cho tình huống 5 hay 10 lần tốt hơn.


Đôi khi bạn gặp một vòng lặp tạo nên bottleneck của hệ thống. Trước khi tìm cách cải tiến vòng lặp cho nó nhanh hơn một chút, hãy cân nhắc xem có cần đến vòng lặp này không đã: có thuật toán nào khác không cần đến lặp, hay thực sự thông tin đã được tính toán đâu đó rồi? Nếu không làm được vậy thì việc tối ưu hóa vòng lặp cần đến hiểu biết về các chi phí của từng lệnh cụ thể, một số gợi ý:

  • Tránh các phép tính dấu chấm động (floating point operation).
  • Không cấp phát bộ nhớ một cách không cần thiết.
  • Ghép các hằng số lại với nhau.
  • Đem các thao tác I/O vào một bộ đệm (buffer)
  • Tránh các phép chia
  • Tránh ép kiểu
  • Dùng con trỏ thay vì tính toán lại chỉ mục

Chi phí của những việc cụ thể này còn phụ thuộc hệ thống. Một số trình biên dịch và phần cứng làm những việc tối ưu này cho bạn. Nhưng dù sao mã hiệu quả vẫn tốt hơn.


Thường thì CPU nhanh hơn các thiết bị ngoại vi như đĩa, mạng, database… Nên việc tối ưu hệ thống thường không phải là việc tối ưu một vài vòng lặp, mà tối ưu các thao tác nhập xuất. Có hai kỹ thuật cơ bản:

  • Caching: tránh các thao tác I/O không cần thiết bằng cách lưu các giá trị thường truy cập ở một nơi nào đó. Có điều nguy hiểm với việc caching là các bản lưu này đôi khi không được cập nhật với bản gốc.
  • Representation: tìm cách biểu diễn data hiệu quả hơn. Nhưng cũng cần xem xét đến các yêu cầu khác: rõ ràng với người đọc, có thể dễ dàng chuyển đổi qua các dạng khác… Kinh nghiệm cho thấy việc biểu diễn có thể được tối ưu 2 hay 3 lần so với phiên bản biểu diễn đầu tiên. Kỹ thuật: biểu diễn nhị phân đi kèm với một từ điển các ký hiệu (để không phải mã hóa các ký hiệu quá dài), các thuật toán nén như mã hóa Huffman…

Một kỹ thuật thứ ba có thể được dùng: vị trí giải quyết vấn đề, nếu bạn cần một tính toán đơn giản trên một số data từ database (như một phép cộng), tốt hơn hãy nhờ đến database làm điều đó.


Bộ nhớ là tài nguyên quý giá không thể để cạn kiệt. Bạn có thể lơ vấn đề này một lúc, nhưng cuối cùng cũng phải nghĩ đến việc quản lý nó. Tùy vào hệ thống, có hệ thống bạn cần hủy bộ nhớ đã cấp phát một cách tường minh. Có hệ thống có thiết kế một “bộ phận thu nhặt rác” (garbage collector – GC), bộ phận này sẽ tự động giải phóng các phần bộ nhớ không cần đến mà không cần đến thao tác nào từ lập trình viên. Các GC rất có ích, dùng chúng bất cứ lúc nào có thể.

Tuy vậy, bạn có thễ vẫn để rác trong bộ nhớ. Một lỗi cổ điển như: dùng bảng băm và quên giải phóng các tham chiếu trong bảng băm đó, vùng nhớ vẫn còn tham chiếu đến mặc dù đã hết sử dụng. Vấn đề này gọi là rò rỉ bộ nhớ (memory leak). Bạn phải để ý vấn đề này từ sớm, một số hệ thống không cho thấy vấn đề bộ nhớ nào lúc test, nhưng sẽ nãy sinh vấn đề trong môi trường sử dụng thật.
Nếu bạn có thể định nghĩa một chặn trên (upper bound) cho các đối tượng (cùng kích thước) cần cấp phát, bạn nên cấp phát cả một vùng đệm (buffer) một lúc để lưu chúng. Nếu có thể, hãy cấp phát và giải phóng các đối tượng bên trong vùng đệm này theo kiểu xoay vòng (ring-buffer). Điều này thường nhanh hơn là cấp phát trong heap.

Đôi khi bạn cần phải giải phóng tường minh một đối tượng (để cấp phát lại chẳng hạn) và không thể nhờ đến GC. Hãy cẩn thận, hãy chắc chắn rằng tương ứng với một lệnh cấp phát là một lệnh giải phóng. Điều này thường rất khó, thường thì lập trình viên sử dụng một dạng GC đơn giản nào đó (như đếm tham chiếu – reference counting) để làm việc này.


Có những lỗi thực sự là ác mộng, chúng lúc nắng lúc mưa, ít xảy ra đến độ dường như không nắm bắt được, và không thể debug vì không biết chúng ở đâu. Dường như chúng chỉ xảy ra sau 8 giờ làm việc, khi bạn bắt đầu nghi ngờ chúng có tồn tại hay không. Điều làm cho chúng khó nhận ra là bạn không biết chúng xảy ra trong điều kiện nào: tìm cách ghi nhận tình huống xảy ra, hoặc cũng có thể lỗi chỉ xảy ra với một dạng đặc biệt nào đó của dữ liệu, ví dụ như “nó chỉ xảy ra khi có từ wyoming trong dữ liệu nhập vào”. Sau hết, nếu không phải là các nguyên nhân này, hãy nghĩ đến lỗi đồng bộ hóa tiến trình.

Nếu không thể lặp lại lỗi (reproduce), hãy tìm cách bẫy nó. Bố trí lại hệ thống log theo các hướng bạn phán đoán. Đôi khi điều này cũng không đem lại kết quả gì ngoài việc bạn biết cách cải tiến hệ thống log tốt hơn, và điều đó có thể giúp bạn bẫy được những lỗi này về sau.

Lỗi ngu ngốc nhất tôi từng gặp phải là trong một chương trình có nhiều tiến trình, tôi đã kiểm tra kỹ lưỡng việc đồng bộ hóa các tiến trình nhưng quên đồng bộ hóa GC. Hệ thống kết thúc tốt đẹp mọi tác vụ trước khi lỗi xảy ra, và điều ngu ngốc hơn nữa là tôi lúc đó đã bắt đầu nghi ngờ phần cứng có vấn đề trước khi biết được lỗi là do phần tôi.


Để học cách thiết kế, hãy quan sát các hành động của người làm điều đó. Sau đó xem xét các gói phần mềm viết tốt, và có thể đọc một vài cuốn sách mới nhất về vấn đề này. Sau đó thì hãy tự bạn làm, khởi đầu với các dự án nhỏ. Sau khi thành công hay thất bại, tìm cách hiểu xem bạn đã ly khai khỏi các ý tưởng sơ khởi như thế nào. Sau đó làm các dự án lớn hơn, với nhiều người thiết kế hơn. Thiết kế là kỹ năng đánh giá chỉ có được sau nhiều năm. Một lập trình viên có thể học các điều cơ sở chỉ sau vài tháng và cứ thế tiến bộ. Nhưng thiết kế thì khác, nó là vấn đề nghệ thuật hơn là khoa học, và những người viết sách về vấn đề này thường cố trình bày như chúng rất là khoa học, nhưng cũng đừng tin một cách giáo điều, võ đoán theo những sách đấy.


Edsger Dijkstra đã hùng hồn giải thích rằng khoa học máy tính (CS) không phải là một khoa học thực nghiệm và không phụ thuộc vào các máy tính điện tử, ông ta nói những điều này vào những năm 1960:

Tội ác đã hoàn tất! Khoa học này đã được gọi bằng cái tên: Khoa học Máy tính, theo cùng một cách như bạn gọi Giải phẫu học là Khoa học Con dao, và điều đó khiến cho mọi người nghĩ rằng khoa học máy tính là về các máy móc cũng như các thiết bị ngoại vi của chúng. Do đó lập trình cũng không thuộc về khoa học thực nghiệm.

Nhưng phần lớn lập trình viên không có được cái xa xỉ mà Dijkstra nói đến. Chúng ta làm việc trong một lĩnh vực cũng giống như một số nhà vật lý học (thực hành) làm vậy. Nếu như trong vòng 30 năm nữa mà lập trình không còn cần đến thử nghiệm nào thì đó là một thành tựu lớn lao của Khoa học Máy tính. Những dạng thử nghiệm cần tiến hành bao gồm:

  • Test các hệ thống với các ví dụ nhỏ để kiểm chứng nó có chạy đúng như tài liệu nói không, hay để hiểu các tác vụ của chúng khi không có tài liệu.
  • Test các thay đổi để xem chúng có thực sự sửa được lỗi không.
  • Đo hiệu suất của hệ thống dưới các điều kiện khác nhau vì không biết các đặc điểm về hiệu suất này.
  • Kiểm tra tính toàn vẹn của dữ liệu.
  • Thu thập số liệu thống kê để tìm giải pháp cho các vấn đề khó.

Tôi có hai lời khuyên cho việc này:

  • Hãy làm cho các giả thiết của bạn rõ ràng, nếu có thể, viết chúng ra giấy.
  • Bạn thường tiến hành các thí nghiệm dựa trên kết quả của thí nghiệm trước. Do đó hãy thiết kế các thí nghiệm (các bài test – ND) làm sao để nó có thể cung cấp nhiều thông tin nhất. Và cân bằng với yêu cầu đơn giản của thí nghiệm là một kinh nghiệm bạn chỉ có được với thời gian.




Một dự án phần mềm không chỉ bao gồm việc coding mà còn thiết kế, làm tài liệu, testing, và các công việc kinh doanh… Nếu không đoán trước được tiến độ phát triển, sẽ không thể có kế hoạch hiệu quả được.

Ước lượng tốt giúp dự đoán tốt. Những nhà quản lý thích điều đó, và họ cũng nên làm điều đó. Thực tế là, trên cả phương diện lý thuyết lẫn thực hành, không thể dự đoán chính xác thời gian cũng như chí phí để làm tất cả những công việc đó. Chúng ta được đòi hỏi làm những điều có thể làm được, do đó thật không hay khi thú nhận không thể làm được chúng. Có rất nhiều chuyện hiểu lầm trong việc ước lượng, ví như thường thì người ta, thật ngạc nhiên, có xu hướng hiểu câu sau một cách khôn ngoan:

Tôi ước lượng rằng, nếu tôi thật sự hiểu vấn đề, thì khoảng 50% chắc chắn là chúng ta sẽ xong việc đó trong vòng 5 tuần (nếu không ai quấy rầy chúng ta suốt thời gian đó).

Như sau:

Tôi hứa sẽ làm xong tất cả trong vòng 5 tuần kể từ bây giờ.

Những kiểu diễn dịch này đòi hỏi bạn phải thảo luận rõ ràng tất cả những ước lượng đó nghĩa là gì, với ông chủ cũng như với khách hàng, cứ như họ là những người ngu ngốc. Và lặp đi lặp lại điều đó cho dù họ có tỏ ra như thế nào.


Ước lượng cần phải được thực tập, và nó cũng tốn nhiều công sức. Và nó tố nhiều công sức đến nỗi chúng ta cần ước lượng thời gian chúng ta cần để ước lượng thời gian làm công việc thực sự, nhất là khi bạn được yêu cầu làm một khối lượng công việc lớn. Nếu phải ước lượng một điều gì lớn, điều lương thiện nhất bạn cần làm là trì hoãn. Sẽ có nhiều lập trình viên khác thông cảm cho điều này. Dĩ nhiên sẽ có người không hài lòng vì điều đó, nhưng một ước lượng tức thì có thể sẽ không chính xác. Trong lúc trì hoãn, bạn có thể tìm cách làm hoặc phác thảo việc cần làm. Và nếu bầu không khí tại nơi làm việc cho phép, đây là cách tốt nhất để ước lượng, hơn nữa, nó cũng đóng góp vào tiến độ thực sự.

Nếu không thể trì hoãn, bạn cần trước nhất phát biểu ước đoán của mình thật rõ ràng. Viết lại phần ước đoán của mình ở cuối phần văn bản viết, và trong phần kế hoạch viết, chia nhỏ các công việc sao cho các công việc con chỉ cần tối đa 1 ngày để hoàn thành. Điều quan trọng nhất là không để sót điều gì, ví dụ như: phần viết tài liệu, phần testing, thời gian lên kế hoạch, thời gian tương tác với các nhóm khác, và cả thời gian nghĩ. Nếu mỗi ngày, bạn cảm thấy cần nhiều thời gian hơn vì phải làm việc với những kẻ ngu đần thì gộp cả thời gian đó vào trong kế hoạch. Những điều này cho phép ông chủ biết bạn ít nhất đang làm gì, vì thực sự bạn sẽ cần nhiều thời gian hơn. Tôi biết có những kỹ sư lập trình tốt, những người ngầm tính thêm một khoảng thời gian vào thời gian đã ước lượng. Nhưng tôi khuyên bạn không nên làm vậy, vì sự tin tưởng ở nơi bạn có thể bị giảm sút. Ví dụ một lập trình viên ước lượng 3 ngày cho một công việc anh ta có thể làm trong 1 ngày, và 2 ngày dư ra, anh ta có thể chỉ ngồi viết tài liệu hay làm việc khác. Nếu việc ấy bị phát hiện, sẽ có ý kiến cho rằng bạn lười nhác hay ước lượng quá. Tốt hơn là bạn cho phép Người ta nhìn rõ vào tiến trình bạn làm việc.

Thay vì như vậy, bạn có thể tính thêm một khoảng thời gian một cách công khai. Ví dụ như công việc mất một ngày, nhưng cũng có thể 10 ngày nếu cách tiếp cận không đúng, thì hãy ghi điều đó vào ước lượng của bạn, hay ít nhất tính trung bình trên các ước lượng khác của bạn. Bất kỳ yếu tố rủi ro nào cũng cần được xác định và đưa vào lịch làm việc. Nếu công ty có những khóa học bắt buộc thì cũng phải thêm thời gian đó vào. Dĩ nhiên vẫn sẽ còn lại những thứ không thể xác định, hay nghĩa là không thể được xác định bởi một cá nhân. Tạo thêm một mục cho điều này và làm cách nào đó để sếp của bạn biết, và làm sao cho sếp bạn phải biết, vì rất dễ sau đó ước lượng sẽ trở thành kế hoạch. Trong một nhóm, bạn cũng sẽ cần những người làm các công việc cụ thể có ước lượng của mình, và bạn cũng sẽ cần sự nhất trí của các nhóm khác. Mọi người rất khác nhau về kỹ năng, kinh nghiệm, mức độ sẵn sàng, tính tự tin… Tai họa đến khi một lập trình viên giỏi ước lượng theo khả năng của anh ta sau đó giao công việc cho một lập trình viên kém. Việc có được sự đồng ý của mỗi thành viên trong nhóm trên mỗi dòng của bản ước lượng sẽ giúp cả nhóm hiểu, đó cũng là cơ hội để có thể có được sự phân chia tốt nhất.

Nếu có những rủi ro chưa thể lượng giá, thì bạn phải gào lên làm sao cho giám đốc của bạn không ủy thác điều gì trong nhiệm vụ đó và sẽ không ngạc nhiên, bối rối khi nó xảy ra. May thay, thường trong những trường hợp đó, tất cả những gì có thể làm sẽ được làm để giảm thiểu rủi ro. Nếu bạn có thể thuyết phục công ty bạn dùng Extreme Programming, thì bạn sẽ chỉ cần ước lượng các việc tương đối bình thường, và sẽ có được hiệu suất tốt hơn.


Bản chất của vấn đề bạn cần biết xác định cách bạn sẽ tìm chúng. Nếu bạn cần thông tin về các đối tượng cụ thể, dễ xác định (như bản vá sau cùng của một sản phẩm), thì chỉ cần hỏi ai đó, tìm trên internet, hay gởi bài trong các diễn đàn thảo luận. Nếu bạn có được kiến thức chung về những thứ đã có chủ đề, thì hãy tìm nó ở thư viện. Nếu bạn cần biết cách làm một điều gì đó khó, thì thường cần đọc 2, 3 cuốn sách về chủ đề đó, những thứ dễ đã có trên internet. Nhưng bạn rất dễ tốn nhiều thời gian chỉ để tìm kiếm, và sắp xếp những thứ kiếm được, và tìm hiểu về nguồn gốc của chúng, hơn là thực sự nắm bắt những điểm quan trọng trong đó.

Nếu bạn cần thông tin về những thứ mà bạn không nghĩ sẽ có ai khác biết, đầu tiên vẫn cần tìm trên internet, ở thư viện, và nếu đều không có kết quả thì phải thăm dò vấn đề đó bằng những thí nghiệm. Nếu bạn cần những đánh giá chuyên môn, tốt nhất là bạn có được những chuyên gia.

Nếu bạn cần quyết định những chuyện cá nhân chỉ có bạn quyết định được, ví như có nên làm công ty riêng hay không, thì hãy viết một danh sách những điều nên, và không nên. Nếu điều này cũng không giúp gì, thì hãy xem xét việc tin vào chiêm tinh bói toán. Và nếu bạn đã hỏi ý kiến tất cả các thiên thần, đã suy xét tất cả hệ quả, những điều thuận lợi và khó khăn mà vẫn chưa quyết định được, thì hãy bảo đầu bạn câm mồm lại và nghe theo con tim bạn. Tất cả các dạng chiêm tinh bói toán đều có tác dụng xác định các ước mơ nửa thức nửa ngủ của bạn, vì mỗi ước ao đại diện cho một mẫu tình cờ và mơ hồ mà tiềm thức của bạn sẽ tự gán cho nó những ý nghĩa.


Hãy tôn trọng thời gian của người khác và tìm cách cân bằng nó với của bạn. Hỏi người khác một câu thì sẽ được nhiều hơn là một câu trả lời. Bạn sẽ biết về người khác theo một cách nào đó, và thường thì điều đó quan trọng hơn câu hỏi. Nhưng thường thì những giá trí này càng ít đi nếu bạn càng làm nhiều nó. Thời gian bạn cần nói chuyện với các đồng nghiệp tùy thuộc vào vai trò của họ (hơn là vị trí của họ). Bạn nên nói chuyện với những người cao hơn bạn, ít nhất là một lần một tháng. Quy luật rất đơn giản: mọi người có lợi khi nói chuyện với nhau, nhưng nói càng nhiều thì lợi càng ít, do đó cần phải cân đối với chi phí (là thời gian bạn trò chuyện). Nếu nói chuyện với ai đó có thể tiết kiệm thời gian của bạn thì bạn nên trò chuyện với người đó, trừ khi bạn nghĩ là thời gian của người đó quý giá hơn của bạn.


Cuộc đời quá ngắn để viết những thứ tào lao không ai đọc. Nên chỉ cần một it tài liệu tốt vẫn tốt hơn. Những người làm quản lý thường không hiểu điều này, vì những tài liệu tệ đã làm họ quá chán với những thứ lập trình viên viết ra. Nếu ai đó khăng khăng đòi bạn viết những thứ tài liệu tào lao, giả tạo, thì cứ nói và sau đó yên lặng tìm một công việc khác tốt hơn. Thực tế thì thật là lạnh lẽo: làm tài liệu, cũng như testing, hay coding thường cần nhiều thời gian hơn dự tính.

Để viết tài liệu tốt, dĩ nhiên đầu tiên là viết tốt. Nhưng nếu bạn viết kém thì có một quy luật vàng: làm cho người khác đúng như cách người ấy sẽ làm với bạn. Dành thời gian suy nghĩ về ai sẽ là người đọc, họ cần biết điều gì từ tài liệu, và bạn có thể diễn đạt điều đó như thế nào. Nếu bạn làm được như vậy, thì chắc chắn bạn đã hơn một người viết tài liệu trung bình, và dĩ nhiên là một lập trình viên tốt.

Những lập trình viên tốt nhất tôi được biết có một đức tính chung: viết giải thích ngay trong code và chỉ viết tài liệu những nơi mà cần thiết. Như vậy có hai cái lợi: một là ai cần hiểu hệ thống sẽ có cơ hội đọc code, hai là như vậy thì code và tài liệu sẽ không có chỗ mâu thuẫn nhau. Cùng lắm thì code rối hoặc sai cũng chẳng sao, nhưng tài liệu mà sai thì nhiều lần tệ hơn. Nhưng giải thích trong code là sao:

  • Viết những mã mà biết chắc rằng có ai đó sẽ đọc nó.
  • Dùng luật vàng đã nói trên.
  • Chọn giải pháp dễ hiểu nhất, ngay cả khi bạn có một giải pháp nhanh hơn.
  • Bỏ những cải tiến nhỏ làm rối code.
  • Hãy nghĩ một chút về người đọc, và bỏ thêm thời gian làm những gì bạn viết dễ đọc hơn, và
  • Đừng bao giờ dùng những tên hàm như: foo, bar hay doIt.


Bạn sẽ rất thường gặp code ai đó viết rất tệ. Đừng nghĩ nhiều về điều đó, vì đôi khi bạn cũng sẽ như vậy, họ có thể đã làm việc rất nhanh để kịp tiến độ. Dù sao để làm việc với những code không rõ ràng, bạn cũng phải hiểu chúng, và điều đó tốn thời gian. Bạn sẽ phải đọc code, và đây là lúc để làm tài liệu. Có thể chỉ là để làm cho chính bạn thôi, nhưng điều này sẽ giúp bạn hiểu các khía cạnh khác của vấn đề, và tài liệu viết được sẽ đến lúc có ích. Bạn cũng có thể nghĩ đến việc viết lại toàn bộ hay một phần code, nhưng cần cân nhắc khi nào điều này.

Điều quan trọng cần nhớ là abstraction và encapsulation, là hai công cụ tốt nhất của lập trình viên, và cũng là cách trị code tệ hại. Vì bạn không thể thiết kế lại một khối code lớn, nhưng bạn có thể gói chúng vào một lớp trừu tượng nào đó và như vậy bạn cũng có thể có được một thiết kế chút ít tốt hơn mà không phải làm việc lại với toàn bộ code, hơn nữa, có thể cô lập một số code thực sự tệ để thiết kế lại riêng sau.


Các hệ thống kiểm soát phiên bản code là không thể thiếu được, ngay cả khi bạn làm việc đơn độc: nó theo dõi tất cả các thay đổi, không có sửa chữa nào mất đi, những code debug và code “vất đi” vẫn có thể được viết thoải mái và không ảnh hưởng đến nhánh code chính thức. Có thể hình dung một hệ thống như thế này một quần thể có tiến hóa, có nhiều thay đổi nhỏ và liên tục. Một lỗi lầm liên quan đến kiểm soát code làm ảnh hưởng đến toàn nhóm là một điều cấm kỵ.


Unit test là một phần của việc coding. Cũng như một phần của việc thiết kế code là thiết kế công việc test. Bạn nên viết xuống một kế hoạch test, ngay cả khi chỉ có một dòng. Đôi khi unit-test rất đơn giản: “cái nút nhìn có đẹp không?”, đôi khi lại là phức tạp: “thuật toán so sánh mẫu có trả về những phép so sánh đúng không?”

Dùng assertion và test driver bất kỳ lúc nào có thể. Điều này không chỉ bắt các lỗi sớm, mà còn ngăn chặn các “lỗi bí ẩn” về sau. Các lập trình viên của Extreme Programming có những bài viết rất hay về unit-test.


Khi bạn rối trí, tốt nhất hãy nghỉ một lát. Tôi thường trầm tư khoảng 15 phút khi rối trí và thường thì vấn đề được giải quyết sau đó. Nhưng toàn diện hơn cả là một giấc ngủ đủ. Hay bạn cũng có thể chuyển qua một công việc hay hoạt động khác.


Lập trình là một hoạt động, và là một văn hóa. Nhưng không may, văn hóa đó không tôn trọng sức khỏe tinh thần và thể xác lắm. Lập trình viên thường bị làm việc quá mức, 60 giờ một tuần là phổ biến. Đây là vấn đề nghiêm trọng của lập trình viên, người có trách nhiệm không chỉ với anh ta mà với cả nhóm. Bạn cần biết khi nào phải về nhà, và đôi khi cũng nên đề nghị người khác về nhà. 60 giờ một tuần là quá mức với tôi, và tôi chỉ có thể chịu được như vậy trong khoảng 1 tuần. Thực tế đáng buồn là lập trình viên thường bị đòi hỏi làm việc nhiều chỉ để trình diễn cho ai khác xem, như là giám đốc muốn chứng tỏ cho ủy viên hội đồng quản trị xem. Mà lập trình viên thì thường không giỏi nói Không. Có bốn cách chống lại điều này:

  • Giao tiếp với mọi người trong công ty để không ai có thể lợi dụng một cơ hội như vậy.
  • Học cách ước lượng và lập lịch có phòng bị rõ ràng và cho mọi người xem điều đó.
  • Học cách nói Không, và cả nhóm nói Không, và
  • Cứ về nếu bạn phải thế

Lập trình viên thương thích làm nhiều việc, nhưng có một sức ỳ tâm lý trong lúc khởi động lúc giải quyết một vấn đề, và lúc bị chìm sâu vào vấn đề đó. Đa số các lập trình viên cảm thấy họ cần có một khoảng thời gian dài, không ngắt quảng để khởi động và tập trung. Nhưng ai cũng phải ngủ, và còn nhiều việc khác. Mỗi người cần tìm cách thỏa mãn cả nhịp điệu sinh học và nhịp điệu làm việc của mình, và tạo được giai đoạn làm việc hiệu quả.

Khi tôi có con, tôi đã thử ở với con về đêm, vì nhịp điệu làm việc hiệu quả của tôi là một ngày rất dài, và ngủ tại ngay văn phòng, chiều hôm sau thì về nhà sớm với các con trước khi chúng đi ngủ. Thực tôi cũng không thoải mái khi phải như vậy, nhưng mà đó là cách thỏa hiệp tốt nhất của tôi. Bạn cần phải về nhà nếu bạn đang mang bệnh có thể lây. Về nhà ngay khi bạn có ý nghĩ tự sát. Bạn cũng nên về nhà khi thoáng có ý nghĩ phải giết ai đó trong đầu. Bạn cũng nên ép ai đó về nhà nếu người ấy có biểu hiện tâm thần không bình thường hơn là chỉ chán nản mệt mỏi. Nếu bạn có những ý nghĩ không tốt vì mệt mà thường bạn không có, bạn cũng nên nghỉ. Đừng dùng thuốc an thần và đừng nghiện cà phê.


Bạn có thể sẽ gặp những người khó tính, hoặc chính bạn cũng có thể là người khó tính. Nếu bạn là kiểu người có nhiều mâu thuẫn với đồng nghiệp hay các nhân vật có quyền lực, bạn phải tự vui với sự độc lập mà cá tính bạn mang lại, và tìm cách làm việc với nhiều người mà không phải hy sinh các nguyên tắc và suy nghĩ của mình.

Điều này có thể rất phiền toái với một số lập trình viên, những người ít kinh nghiệm với kiểu người khó tính, và cuộc sống của họ có những kiểu cách không hợp lắm với không gian công việc Những người khó tính thường là người quen với những ý kiến bất đồng và ít bị ảnh hưởng bởi áp lực xã hội hơn những người khác. Chìa khóa ở đây là tôn trọng họ đúng mức: nhiều hơn bạn muốn, nhưng không nhiều như họ muốn.

Lập trình viên làm việc theo nhóm, và khi có bất đồng, không nên để lâu. Người khó tính thường lại là những người rất thông minh và họ có những cách rất hiệu quả. Điều rất quan trọng là bạn lắng nghe những người này mà không có định kiến gì. Tìm cách trao đổi một cách trầm tĩnh và chân thành, đừng mắc vào những cớ gây mâu thuẫn lớn hơn. Sau khi đã tìm cách hiểu hãy quyết định.

Đừng nghe theo sức ép của những kẻ bắt nạt. Nếu bạn là team-leader, làm điều bạn nghĩ là tốt nhất. Đừng quyết định vì lý do cá nhân, và chuẩn bị để giải thích quyết định của mình. Nếu cùng nhóm với một người khó tính, đừng để leader phải quyết định mang tính chất cá nhân, và nếu không đi con đường của bạn được thì đi con đường kia một cách thành tâm.

Những người khó tính vẫn có thay đổi và cải thiện. Tôi đã thấy, nhưng điều đó hiếm. Ai cũng có những lúc lên, xuống tạm thời. Và điều khó khăn, nhất là leader phải làm là làm sao cho những người khó tính bận bịu. Họ thiên về các công việc họ yêu thích và phản ứng tiêu cực hơn những người khác.






Điều ngạc nhiên và kỳ diệu trong giới lập trình viên là họ luôn bị thúc đẩy bởi mong muốn tạo ra những sự vật đẹp, có ích, thuận tiện. Điều này khá phổ biến trong giới lập trình viên và do đó phân biệt họ với những người khác, trong những vai trò khác.

Điều này có những hệ quả quan trọng và thực tế. Nếu bắt lập trình viên làm việc gì không đẹp, không ích lợi, họ sẽ cảm thấy miễn cưỡng khi làm. Làm những việc xấu xí, ngu ngốc, nhàm chán thì có nhiều tiền, nhưng tôi tin rằng, cuối cùng làm những việc vui vẻ sẽ mang lại nhiều lợi ích cho công ty nhất. Có những điều rất riêng biệt cho các lập trình viên giỏi:

  • Dùng ngôn ngữ tốt nhất cho công việc.
  • Tìm cơ hội áp dụng các kỹ thuật, công nghệ mới.
  • Tìm cách học hay dạy những điều mới, cho dù nhỏ.
  • Cuối cùng, tự quan sát công việc của mình dưới các khía cạnh khác. Ví dụ như khi tôi fix bug, số các bug fix được chẳng bao giờ làm tôi vui, vì nó chẳng nghĩa lý gì so với số bug còn phải fix, và chẳng đóng góp gì mấy về phía công ty. Nhưng với một bug nào đó, sự hài lòng của khách hàng cũng là một phần thưởng.


Đầu tiên phải có mặt. Nếu chẳng ai thấy bạn thì không ai tin bạn được. Có những phản hồi nhiều thông tin với người khác. Nhiều khi người khác sẽ làm phiền bạn với sự tin cậy này, và có những đòi hỏi vô lý, khi đó hãy giải thích cho họ hiểu bạn phải bỏ điều gì khi phải đáp ứng họ. Đừng giả vời biết những điều bạn không biết. Với những người không ở trong nhóm của bạn, đôi khi phải phân biệt rõ giữa không thể biết được ngaydù sao cũng không có cách nào biết được.


Bạn có thể làm một lập trình viên giỏi mà không cần phải qua đại học. Nhưng một người có trình độ trung bình trong nghề này phải biết những kiến thức căn bản, như là lý thuyết độ phức tạp của tính toán chẳng hạn. Bạn không cần phải biết big O notation là gì, nhưng bạn cần phân biệt được tuyến tính với thời gian, n log n, và n bình phương khác nhau như thế nào. Bạn cũng vẫn có thể biết cách cân bằng giữa không gian và thời gian, nhưng cũng khó để giao tiếp với đồng nghiệp nếu như bạn không biết những điều trên.

Cải tiến việc cân bằng giữa không gian (bộ nhớ) và thời gian (thời gian chạy CPU) có thể thay đổi nhiều điều một cách ngoạn mục. Nhưng đầu tiên, cần phải xem có cần phải cải tiến không. Vì cải tiến một cái không phải là vấn đề thực sự chẳng làm nên điều khác biệt nào, ngoài việc tạo thêm một khối lượng test. Bộ nhớ máy tính càng ngày càng rẻ, và việc tiêu phí nó không dễ thấy như là thời gian của CPU, cho đến khi chi phí đụng trần, và tai họa xảy đến. Cần cân nhắc khi bạn bán không gian để mua thời gian (tốc độ).


Stress test là thử nghiệm hệ thống với tải. Thực tế, rất nhiều khi hệ thống làm việc tốt với một tải nhất định, và chỉ bắt đầu có vấn đề với một tải trọng nào đó, tức hệ thống đụng trần (hit the wall). Và stress test thực sự là để tìm ra xem cái trần này là ở đâu, và tìm xem có cách nào dỡ trần lên cao hơn không.

Kế hoạch cho việc stress test cần phải được làm ở giai đoạn đầu của dự án, vì như vậy cũng là xác định chúng ta mong đợi đến chừng nào ở sản phẩm: 2 giây cho việc một yêu cầu một trang web có phải là một thất bại hay không hay là một thành công rực rỡ?. Kế đến, stress test cần được thực hiện trong một môi trường đủ gần với môi trường thực.

Khi tiến hành stress test, bắt đầu với tải nhẹ, và nâng dần tải trọng lên theo một số chiều nào đó, cho đến khi bạn đụng trần. Và nếu trần quá thấp thì bạn gặp phải vấn đề về hiệu suất hệ thống, nghĩa là thường thì có một bottleneck ở đâu đó. Sau đó thì bạn tìm cách nâng dần trần lên, nhưng nhớ rằng một hệ thống chịu được tải nặng không có nghĩa là hệ thống đó chạy tốt với tải nhẹ. Sau đó thì làm test trên các chiều khác nữa. Có nhiều kỹ thuật khác nhau, như các hệ thống log thường cho biết nhiều điều về thời gian dùng CPU, nhưng ít khi cho được cái nhìn đúng về tình trạng bộ nhớ. Trong các hệ thống hiện đại, nhiều phần mềm và nhiều máy tính có thể cùng tương tác, khi bạn đụng trần đâu đó thì các hệ thống khác cũng bị ảnh hưởng theo, do đó theo dõi tất cả các máy cũng sẽ rút được nhiều thông tin.

Cuối cùng, biết được trần ở đâu không có nghĩa là phải nâng trần lên, chỉ là để có cái nhìn mang tính dự đoán để giúp cho mặt kinh doanh của sản phẩm.


Trừu tượng hóa là chìa khóa của lập trình. Nhưng bạn cần cân nhắc mức độ trừu tượng hóa, người mới vào nghề thường trừu tượng vấn đề nhiều hơn cần thiết. Dấu hiệu nhận biết điều này là tạo nhiều lớp không thực sự chứa đoạn mã nào và chỉ để phục vụ cho việc trừu tượng hóa một điều gì đó. Dĩ nhiên điều này là hấp dẫn, nhưng bạn cũng cần đến tính khúc chiết, ngắn gọn trong code.

Đôi khi, chúng ta thấy những lỗi lầm của những người nhiệt thành và lý tưởng: tại giai đoạn sơ khởi của dự án, nhiều lớp được định nghĩa cho thấy viễn cảnh có thể xử lý mọi tình huống có thể xảy ra. Sau đó thì phần thân của các hàm càng ngày càng dài, code càng ngày càng hỗn độn, và nhiều lớp trống không được viết tài liệu vì mọi người đều rất bận. Kết cục đó có thể tránh được nếu để dành công sức cho sự trừu tượng hóa này vào việc giữ mọi thứ ngắn gọn và đơn giản. Tôi đề nghị đọc Succinctness is Power của Paul Graham.

Có một số giáo điều với các kỹ thuật như che giấu thông tin (information hiding) hay lập trình hướng đối tượng (object oriented programming). Những kỹ thuật này giúp lập trình viên code những đoạn mã có tính trừu tượng cao và thích nghi với thay đổi. Nhưng, theo cá nhân tôi, bạn không nên viết quá nhiều code như thế.


Học các kỹ năng mới, nhất là các kỹ năng không phải là kỹ thuật là điều thú vị nhất. Phần nhiều các công ty sẽ có chính sách tốt hơn nếu họ hiểu những lập trình viên muốn điều này như thế nào. Đọc sách, dự các khóa học cũng là một cách, nhưng thực sự bạn có thể kính trọng một lập trình viên nếu như anh ta chưa viết một chương trình nào không? Nhưng để học một kỹ năng, bạn phải tự đặt mình vào cái vị thế đáng thương nơi bạn có thể thực tập kỹ năng đó. Một cố vấn kinh nghiệm thường tốt hơn sách vở nhiều, nhưng điều đó cũng không thay thế được việc bạn tự học. Tìm cách bắt sếp cho bạn học các lớp chính thức nhiều hơn, nhưng cũng nên hiểu rằng điều đó cũng chẳng tốt hơn việc bạn từ mày mò là bao nhiêu. Vì thường là đòi có lớp học thì dễ hơn đòi được nghĩ xả hơi, còn lớp học thì nhiều khi là những bài giảng ngái ngủ để đợi đến giờ ăn.

Nếu bạn lãnh đạo người khác, hãy hiểu họ học như thế nào và khuyến khích bằng cách giao những việc đúng tầm và đúng kỹ năng. Nhớ rằng các kỹ năng quan trọng lại không phải là các kỹ năng kỹ thuật và để mọi người có cơ hội giao tiếp, và nâng cao tình bằng hữu và sự mạnh dạn trong công việc.


Đây là kỹ năng trung cấp, vì viết code thường khó và thường bạn không đủ thời gian để gõ những gì bạn nghĩ. Và trong công việc, càng ngày bạn càng viết lách nhiều hơn (mà ít phải gõ code hơn). Giai thoại kể lại rằng khi Michael Tiemann ở MCC, người đứng ngoài cửa có thể nghe được tiếng vo ve của các phím bấm, nhanh đến nỗi chẳng phân biệt được các phím với nhau.


Intergration testing (IntT) là khi bạn tích hợp tất cả các phần khác nhau của hệ thống đã được unit-test. IntT thường tốn kém, và bạn phải tính thời gian làm điều này trong lịch làm việc của bạn. Tốt nhất là làm sao không có giai đoạn IntT này vào cuối mỗi chu kỳ, bạn tích hợp dần dần mọi thứ và kiểm tra dần cho đến lúc hệ thống thành hình.


Có một số ngôn ngữ không phải là ngôn ngữ lập trình, nhưng là ngôn ngữ giao tiếp giữa các chương trình, đã được hình thành và dần chuẩn hóa như UML, XML, SQL… Bạn cần phải biết những ngôn ngữ này cũng như biết dùng chúng lúc cần.
UML rất đẹp ở chỗ nó vừa trực quan, lại vừa hình thức. XML là chuẩn để định nghĩa những chuẩn mới. Nó không phải là giải pháp cho vấn đề trao đổi dữ liệu như bạn nghĩ, dù là nó được nói đến như vậy. Nó chỉ là việc tự động hóa cho phần chán nhất của trao đổi dữ liệu: biến đổi toàn bộ cấu trúc của dữ liệu thành tuyến tính để gởi đi và ngược lại. XML có những phương pháp kiểm tra kiểu và kiểm tra tính chính xác, nhưng lần nữa, cũng chỉ là một phần của những cái bạn sẽ cần đến trong thực tế. SQL không thực sự là một ngôn ngữ lập trình, và là ngôn ngữ chung của các cơ sở dữ liệu quan hệ. Có thể bạn không làm việc liên quan đến cơ sở dữ liệu, nhưng cũng nên có hiểu biết cơ bản về cú pháp và ngữ nghĩa của SQL.


Theo đà phát triển, công nghệ phần mềm tiến từ chỗ không thể hiểu nỗi đến nghiên cứu, đến sản phẩm mới, đến các sản phẩm chuẩn hóa, đến các sản phẩm giá rẻ. Do đó các công cụ công nghệ phần mềm nặng ký thường đòi hỏi nhiều đầu tư để hiểu và sử dụng chúng. Các lập trình viên hạng trung cần biết sử dụng chúng khi cần thiết. Theo tôi, một số công cụ nặng ký cần có:

  • Cơ sở dữ liệu quan hệ.
  • Các máy tìm kiếm toàn văn (full-text search engine).
  • Các thư viện toán học.
  • OpenGL.
  • Các bộ phân tích cú pháp XML (XML-parser).
  • Các chương trình bảng tính.


Phân tích dữ liệu nằm ở giai đoạn sớm của dự án, khi bạn phân tích các hoạt động kinh doanh và tìm ra các yêu cầu đối với phần mềm. Định nghĩa hình thức này có thể làm cho bạn, lập trình viên, nghĩ rằng cần phải tập trung vào coding và để công việc đó cho ai đó làm thiết kế. Nếu theo đúng các tiến trình làm phần mềm thì có thể là như vậy. Nhưng lập trình viên kinh nghiệm thường trở thành người thiết kế, và người thiết kế sắc bén thường trở thành người phân tích kinh doanh. Và họ được trao cái quyền thu thập yêu cầu dữ liệu và đặt các yêu cầu đó trên bàn cho bạn làm. Nhưng vì dữ liệu nằm ở trung tâm của hoạt động lập trình, người phân tích kinh doanh phân tích dữ liệu ở cấp cao, kế đến người thiết kế bóp nặn các phân tích đó sao cho khi nó đến bàn của bạn, bạn chỉ việc áp dụng những thuật toán thông minh nhất để giải quyết công viêc. Sự việc không hoàn toàn như vậy, vì dù ở công đoạn nào dữ liệu cũng là điều chính yếu cần quan tâm. Nếu bạn tìm hiểu xem tay phân tích kinh doanh làm gì để lấy yêu cầu từ khách hàng, bạn sẽ thấy họ vẽ những data flow diagram, định vị các nguồn thông tin, cũng như định hình các dòng thông tin lưu chuyển. Có được yêu cầu cần phải tích hợp luồng thông tin nào vào hệ thống, người thiết kế sẽ xây dựng các nguồn thông tin theo các thuật ngữ của cơ sở dữ liệu quan hệ, của các protocol trao đổi thông tin, của các định dạng file….để công việc có thể được giao xuống cho lập trình viên. Tuy nhiên quá trình chưa dừng ở đây, vì bạn, lập trình viên, sau quá trình tinh lọc dữ liệu này, cần phải phân tích dữ liệu để có thể làm điều đó theo cách tốt nhất. Cái dòng bên dưới công việc của bạn là gì nếu không phải là câu của Niklaus Wirth: Algorithms + Data Structures = Programs. Không có thuật toán nào tự đứng một mình, tự nó làm điều gì đó với chính nó. Do không có thuật toán nào chạy trong chân không nên bạn cần biết phân tích dữ liệu ai đó đã đem đến cho bạn để có thể viết code.

Ví dụ: tìm xem từ nào trong từ điển có nhiều hơn 3 anagram có nghĩa (tức là cũng có trong từ điển) (anagram: một cách đảo các chữ cái của từ đó). Nếu bạn làm bằng cách xem xét tất cả hoán vị có thể có thì dường như bạn đã chọn cách làm tệ nhất.




Để quản lý thời gian phát triển, luôn duy trì một kế hoạch ngắn gọn và cập nhật. Kế hoạch là một tập các ước lượng, các lịch biểu, các cột mốc (milestone) đê đánh dấu tiến độ. Trong kế hoạch đó cần có tất cả những thứ bạn cần làm, các buổi họp, các buổi làm việc với QC, tài liệu, đặt mua thiết bị… Nếu là kế hoạch cho nhóm, thì cả nhóm phải đồng ý với kế hoạch đầu và trong mỗi lúc thực hiện.

Kế hoạch dự án là để giúp ra quyết định, chứ không phải để phô bày cách tổ chức. Kế hoạch phải cập nhật, để cùng với phán đoán của bạn, có thể dịch chuyển các tác vụ từ người này sang người khác. Nếu để lỡ một milestone, phải có hành động ngay, như là báo cho ông chủ biết. Vì ước lượng và lập lịch không bao giờ là hoàn hảo, và có thể tạo ra ảo tưởng bạn có thể bù những ngày đã lỡ trong những ngày còn lại.


Có những rủi ro liên quan đến các phần mềm do một hãng thứ 3 viết:

Đừng đặt hy vọng vào các thứ chưa có, các phần mềm được hứa là sẽ có. Dĩ nhiên là không nên hoàn toàn hoài nghi về lời hứa của một công ty về một sản phẩm nào đó trong một hạn thời gian nào đó, nhưng khôn ngoan hơn là làm lơ như là chưa nghe lời hứa đó. Và đừng đưa nó vào các văn kiện viết.

Ngay cả khi các lời hứa có thể tin được, nó vẫn chứa rủi ro. Nếu bạn dùng phần mềm của một hãng thứ ba, nhớ là hãy đánh giá nó sớm, sớm hơn rất nhiều trước khi tích hợp. Hiểu được mức độ của các phần mềm do hãng thứ ba viết là một kiến trúc rất đặc biệt, và thường chỉ có chuyên gia mới có được. Và bạn tiết kiệm được rất nhiều thời gian nếu có những người như vậy. Tìm cách có một kế hoạch dự phòng trong trường hợp bất khả kháng.


Dùng các cố vấn (consultant), nhưng đừng dựa hẳn vào họ. Họ là những người tuyệt vời và xứng đáng được kính trọng. Vì họ tham gia vào nhiều dự án, họ sẽ biết nhiều về các công nghệ đặc biệt, hay ngay cả các kỹ thuật lập trình nhiều hơn bạn. Cách tốt nhất sử dụng họ là nhờ họ như những gia sư: dạy học các bằng ví dụ. Hơn nữa, họ có thể dễ đến và dễ đi hơn. Họ thường được ít hơn nếu công ty làm việc tốt hơn. Một số thật giỏi, một số trung bình, số còn lại thì kém. Nhưng thường thị bạn chọn họ không kỹ như là chọn lập trình viên, nên thường bạn có nhiều người dỡ hơn. Nếu cố vấn đi viết code, thì bạn cần phải cân nhắc hơn, vì bạn không thể kết thúc dự án với một khối code lớn không có ai review.


Cân nhắc chi phí của các buổi họp. Chi phí của nó bằng thời gian nhân cho số người tham gia. Họp hành thì cần, nhưng ít hơn nghĩa là tốt hơn. Khuyến khích các giao tiếp ít hình thức, vì thường là có nhiều việc được làm hơn trong giờ ăn trưa hơn các giờ khác. Thật xấu hổ là nhiều công ty không nhận ra và hỗ trợ điều này.


Bất đồng là cơ hội để có được một quyết định tố, nhưng phải được xử lý không khéo. Nếu bạn cảm thấy mình đã diễn đạt tốt và được mọi người chú ý lắng nghe thì không có gì nhiều để nói. Nhưng nếu bạn không thể bênh vực cho quyết định mà bạn bất đồng, thì hãy cứ nói vậy. Điều này chứng tỏ bạn là người có suy nghĩ độc lập và có trách nhiệm. Trong một số trường hợp, bất đồng có thể đưa đến công việc được xử lý theo cách của các cá nhân, khi người ra quyết định cảm thấy bất an và cảm thấy đây là một thách thức với uy quyền của cá nhân mình, hãy nhớ rằng trong những trường hợp đó, họ phản ứng với phần có nguồn gốc bò sát trong não họ, bạn nên trình bày những lý lẽ của mình ở một nơi riêng. Nhưng cho dù quyết định có được đảo ngược hay không, ban không bao giờ được nói: Tôi đã nói với anh mà!.



Phát triển phần mềm đã luôn là cân bằng giữa việc làm gì và việc phải hoàn thành nó. Cái chính là bạn sẽ bị đòi hỏi hy sinh chất lượng cho thời gian theo cách làm tổn thương các kỹ sư cũng như các nhân viên kinh doanh. Nếu điều này xảy ra, hãy thông báo cho các thành viên của nhóm cái giá của việc giảm bớt chất lượng, vì dù sao bạn cũng hiểu điều này hơn là ông chủ. Hãy là rõ cái gì mất và cái gì được. Nếu nó ảnh hưởng đến phía QA, hãy làm rõ nó ra, nếu nó để lại nhiều bug về sau, cũng chỉ ra điều đó. Nếu như bạn được yêu cầu gói cái đống kém chất lượng này vào một component nào đó để chuẩn bị làm nó ở các phase sau, hãy giải thích điều đó với nhóm của bạn để họ có chuẩn bị.

NinjaProgrammer ở Slashdot có nói:

Nhớ rằng thiết kế tốt sẽ có tác dụng chống lại code kém. Nếu như các phần trừu tượng, giao diện (interface) tốt có nhiều trong code, thì việc viết lại mớ code đó sẽ ít khó khăn hơn. Nếu như khó viết code khó sửa thì hãy xem xem điều gì sai trong thiết kế.


Các hệ thống phần mềm hiện đại càng phụ thuộc nhiều vào các component không trực tiếp nằm trong vòng kiểm soát của bạn. Điều này tăng hiệu suất nhờ vào việc tái sử dụng. Tuy vậy các component cũng mang đến vài vấn đề:

  • Sửa lỗi trong các component này thế nào?
  • Component có làm bạn phụ thuộc vào hệ thống hay phần mềm khác không?
  • Bạn làm gì nếu như component không làm việc?

Nên luôn cần phải gói các component này bằng một cách nào đó, cô lập nó và thay thế khi cần thiết. Hơn nữa việc gói này cũng khiến cho porting phần mềm (từ hệ thống này sang hệ thống khác) cũng dễ hơn.

Có được source code của các component làm rủi ro giảm đi khoảng 4 lần. Nếu bạn fix lỗi của các component này, nhớ đưa nó lại cho người sản xuất chúng, để họ tích hợp các fix vào các bản phát hành sau, nếu không bạn sẽ không vui vẻ gì khi phải hỗ trợ một phiên bản không chính thức.


Dùng các gói phần mềm người khác viết là cách hay nhanh để tạo nên hệ thống, nhưng rủi ro cần phải cân nhắc. Bạn phải cân nhắc xem gói phần mềm đó đã đủ trưởng thành chưa (vì thường thì các gói phần mềm trưởng thành cùng với quá trình sử dụng):

  • Gói đó có thực sự có được không?
  • Bạn đã biết gì về gói đó?
  • Bạn có phải là người dùng đầu tiên?
  • Có lý do mạnh nào để tiếp tục không?
  • Gói đó có được bảo trì không?
  • Nếu những người đang bảo trì “bỏ chạy” thì nó có tiếp tục sống không?
  • Có gói nào khác thay thế được chỉ tốt bằng nửa thế không?
  • Công ty bạn có thực sự muốn nó không ?
  • Nếu nó thực sự tốt, bạn có thể thuê người làm tiếp trên nó không?

Cân nhắc tất cả những tiêu chí này mới thấy giá trị lớn lao của các gói phần mềm mã nguồn mở được phát hành tốt trong vai trò giảm rủi ro cho các doanh nghiệp.


Các doanh nghiệp thường luôn phải quyết định: mua hay làm. Những quyết định này thường đáng tiếc ở những điểm sau: nó thường bỏ lơ các gói mã nguồn mở (vì chúng không cần phải mua). Điều quan trọng hơn là một quyết định như vậy thường bỏ qua chi phí tích hợp, mà chi phí này không nhỏ:

  • Những gì bạn cần có giống những thứ đã được thiết kế sẵn đó không?
  • Bạn sẽ cần phần nào của cái bạn mua?
  • Chi phí của việc tích hợp?
  • Chi phí cho đánh giá việc tích hợp?
  • Mua sẽ gia tăng hay giảm bớt chi phí bảo hành về lâu về dài?
  • Nếu phải tự làm, điều đó có đặt bạn vào một vị trí kinh doanh bạn không muốn không?

Bạn phải nghĩ rất kỹ nếu như làm một cái gì đó rất lớn đủ để xây cả một doanh nghiệp khác. Những ý tưởng như vậy thường được đề nghị bởi những người giỏi và lạc quan, những người sẽ cống hiến rất nhiều cho nhóm của bạn. Nếu nó hấp dẫn, bạn cũng có thể thay đổi kế hoạch kinh doanh, nhưng đừng đầu tư lớn hơn cho cả doanh nghiệp của bạn mà không suy nghĩ tỉnh táo.

Sau đó bạn xây dựng hai kế hoạch, một tự làm và một mua và so sánh chi phí. Và những chi phí này phải tính trên thời gian dài.


Tưởng tượng bạn có trách nhiệm vượt quá thẩm quyền của bạn. Đóng cái vai bạn muốn làm. Biết ơn những đóng góp cho công ty cũng như cho cá nhân. Nếu bạn muốn thành leader, hãy tìm cách tập trung sự hưởng ứng. Nếu bạn muốn là manager, hãy có trách nhiệm với lịch biểu. Ngay cả khi đang làm việc với leader hay manager của mình, bạn vẫn có thể làm vậy, vì làm vậy giúp họ rảnh hơn. Lên kế hoạch học các kỹ năng: kỹ thuật cũng như xã hội.


Tuyển dụng luôn không được quan tâm đúng mức. Thuê một người không thích hợp cũng giống như một hôn nhân có vấn đề.

Có nhiều kiểu phỏng vấn khác nhau. Một số có tính “giày vò”, giao cho ứng viên một khối lượng khổng lồ. Điều này cũng giúp cho việc phát hiện các điểm mạnh và yếu của ứng viên khi phải chịu sức ép. Ứng viên sẽ không thành thật với chính mình hơn là với người phỏng vấn, và các khả năng tự lừa dối mình thật đáng ngạc nhiên.

Bạn nên hỏi miệng các ứng viên các vấn đề kỹ thuật trong khoảng 2 giờ. Với thực hành, bạn sẽ biết cách tìm ra họ biết và không biết những gì, và chỉ ra cho họ thấy. Các ứng viên thường tôn trọng điều này. Tôi đã đôi lần nghe các ứng viên nói rằng chất lượng của các kỳ sát hạch là một trong những động lực cho việc chọn công ty làm việc của họ. Những người tốt muốn được thuê vì khả năng, chứ không phải vì nơi họ làm việc sau cùng, hay vì một đặc tính không quan trọng nào khác. Bạn cũng cần đánh giá khả năng học hỏi của ứng viên, và điều này quan trọng hơn chúng ta tưởng.

Phỏng vấn cũng là một quá trình bạn: bạn bán công ty hay dự án cho ứng viên. Tuy nhiên, khi nói chuyện với lập trình viên, cũng đừng cố tô bóng sự thật, nói về những thứ không tốt trước, sau đó về các thứ tốt hơn.


Có một phần của khoa học máy tính gồm cả thuật toán, cấu trúc dữ liệu, toán… những lập trình viên biết nhưng ít dùng. Thực tế, những thứ này quá phức tạp và không cần thiết lắm. Ví dụ như không ích lợi gì trong việc cải tiến một thuật toán nếu như phần lớn thời gian là gọi cơ sở dữ liệu một cách không hiệu quả. Phần đáng thương của lập trình là làm cho các hệ thống nói chuyện được với nhau và dùng các cấu trúc dữ liệu đơn giản để xây dựng các giao diện đẹp.
Khi nào thì công nghệ cao là công nghệ thích hợp? Khi nào thì bạn nên cày một cuốn sách để tìm một thuật toán không có gì đặc biệt? Đôi khi làm điều này cũng có ích nhưng cũng với đánh giá cẩn thận.

Ba cân nhắc quan trọng nhất đối với các kỹ thuật khoa học máy tính có tiềm năng là:

  • Nó có được gói cẩn thận để ít gây rủi ro cho các hệ thống khác, và chi phí toàn bộ cho bảo trì có thấp không?
  • Lợi ích có đáng chú ý không?
  • Bạn có thể kiểm tra và đánh giá nó đúng được không?

Nếu như một sửa đổi thuật toán có thể làm hiệu suất toàn hệ thống tăng gấp đôi (hay giảm chi phí phần cứng đi một nữa) thì đúng là tội ác nếu không cân nhắc nó. Chìa khóa khi biện hộ cho sự thay đổi là: rủi ro thật sự ít, công nghệ này đã được nghiên cứu kỹ, chỉ còn rủi ro khi tích hợp.


Kỹ sư, lập trình viên thường được liệt vào một loại người, một loại văn hóa khác với những người khác. Điều này có nghĩa là những người khác thì khác chúng ta. Khi phải trao đổi với những nhân viên không kỹ thuật, hãy luôn nhớ rằng: tìm cách hiểu họ.

Những nhân viên không kỹ thuật cũng thông minh, nhưng không có chung nền tảng kỹ thuật với chúng ta. Chúng ta làm ra sản phẩm, họ bán, đếm, quản lý sản phẩm… họ cũng không giỏi làm việc nhóm như chúng ta (điều này hiển nhiên không có ngoại lệ). Kỹ năng xã hội của họ tệ lắm cũng bằng chúng ta, nhưng công việc của họ không đòi hỏi họ phải thực tập cách hành xử thân mật, cách ăn nói chính xác, cách chia nhỏ sự việc như chúng ta. Những người này thường dễ bằng lòng hơn, cũng như chúng ta, họ có thể nói mà không thực sự hàm ý vậy.

Những người không kỹ thuật vẫn có thể hiểu các vấn đề kỹ thuật, nhưng họ không có cái mà với chúng ta cũng là một điều khó: đánh giá kỹ thuật. Họ vẫn có thể kỹ thuật vận hành như thế nào, nhưng lại không thể hiểu tại sao làm theo cách này lại mất 3 tháng trong khi cách kia lại mất 3 ngày (lập trình viên cũng có những huyền thoại kiểu như vậy thôi), và đây cũng là một cách để tìm tiếng nói chung với họ.

Khi nói chuyện với người trong nhóm, bạn thường dùng một vài kiểu viết tắt có liên quan đến kinh nghiệm làm việc của bạn. Cần phải có chút nỗ lực để không dùng các dạng này với người không hiểu chúng, nhất là khi có thành viên khác của nhóm bạn ở đó. Với nhóm bạn, những điều ngầm định và mục đích cơ bản không cần phải nhắc lại nhiều, phần lớn thời gian dành cho các chi tiết. Với người ngoài nhóm, câu chuyện phải ngược lại. Họ thường không hiểu những gì bạn không bỏ qua, và làm cho hai bên nghĩ rằng mình hiểu nhau, nhưng thực ra sự không thông hiểu lại càng lớn. Bạn sẽ phải nghĩ rằng bạn sẽ không giao tiếp tốt và tìm hiểu tại sao như vậy. Tìm cách bắt họ tóm tắt những gì bạn nói để chắc rằng họ hiểu.

Tôi thích làm việc với những thành viên không kỹ thuật. Bạn thường có được lợi thế vì bạn biết nhiều ví dụ và ngôn ngữ của bạn rõ ràng. Bạn được đào tạo để tìm trật tự trong hỗn loạn, và họ thích điều đó ở chúng ta. Vì chúng ta hiểu biết các lý luận kỹ thuật, chúng ta cũng sẽ dễ hiểu các khoản liên quan đến kinh doanh, và chúng ta thường tìm được giải pháp cho vấn đề. Những nhân viên không kỹ thuật thường đề xuất các giải pháp họ nghĩ là sẽ dễ hơn cho chúng ta, nhưng thực tế, những giải pháp sau cùng thường chỉ được tìm thấy bằng cách tổng hợp các cái nhìn ngoài cuộc với các đánh giá kỹ thuật. Cá nhân tôi thích Extreme Programming vì nó đã đề cập đến sự không hiệu quả này; kết nối các lượng giá với các ý tưởng sẽ dễ dàng tìm được các kết hợp tốt nhất giữa chi phí và lợi ích hơn.






Việc của chúng ta là làm những điều khó và thăm dò những điều không thể. Từ quan điểm của hầu hết lập trình viên, một điều là không thể khi nó không thể có được từ hệ thống hiện tại hay nó không thể đánh giá được một cách chính xác. Nếu theo định nghĩa này thì tất cả những việc nghiên cứu là không thể.

Sự phân biệt không khôi hài như ta nghĩ, vì thực sự đôi khi bạn đã được đòi hỏi phải làm điều không thể (từ quan điểm khoa học hay từ quan điểm công nghệ phần mềm). Thực sự thì đó chỉ là việc giúp tìm ra một giải pháp cho một vấn đề thực sự khó và hoàn tất phần quan trọng của giải pháp đó. Và một giải pháp được gọi đơn thuần chỉ là khó khi nó có thể được lập lịch một cách tự tin và các rủi ro được hiểu rõ.

Một yêu cầu như thế này thì rất khó có thể thỏa mãn: xây dựng một hệ thống tính toán được kiểu tóc và màu tóc hấp dẫn nhất cho một người. Nhưng vấn đề có thể trở thành đơn thuần chỉ là khó nếu nó có thể được phát biểu sinh động hơn: xây dựng một hệ thống tính được các kiểu tóc và màu tóc hấp dẫn cho một người, cho phép họ xem trước và thay đổi, để sau một hồi thay đổi, họ thấy kiểu ban đầu rất đạt và do đó chúng ta có thể kiếm tiền từ đó. Bạn không thể thành công nếu bạn không có các định nghĩa sinh động về chữ thành công.


Nhúng một ngôn ngữ vào hệ thống là công việc gợi tình và sáng tạo nhất bạn có thể làm. Nó làm cho hệ thống trở nên rất mạnh. Ví dụ như các text-editor tốt nhất đều có các ngôn ngữ nhúng. Nó có thể được sử dụng để người dùng có thể sử dụng sản phẩm với nhiều tính năng hơn. Dĩ nhiên là chức năng này cần phải được xem là tùy chọn, để người đã quen dùng và không ai khác phải dùng đến nó. Tôi và nhiều lập trình viên khác đã rơi vào cái bẫy này nhiều lần. Đã có nhiều ngôn ngữ nhúng và bạn cần cân nhắc kỹ khi tạo ra một cái mới.

Câu hỏi thực sự cần cân nhắc là: điều này ủng hộ hay chống lại văn hóa của người sử dụng? Nếu người dùng hoàn toàn không phải là lập trình viên, liệu điều đó sẽ có ích gì không? Nếu người dùng là lập trình viên, tốt hơn chăng nếu bạn xài một tập các hàm API? Lập trình viên thường không muốn học các ngôn ngữ ít người dùng, nhưng nếu ngôn ngữ đó “khớp” vào trong môi trường của họ thì họ chẳng phải tốn nhiều thời gian để học nó.


Một lập trình viên đơn độc thích chọn ngôn ngữ phù hợp nhất cho công việc. Số còn lại không có ý thức nhiều về ngôn ngữ họ sẽ dùng. Thường thì việc quyết định điều này sẽ do các ông chủ chẳng mấy am hiểu kỹ thuật, và không đủ can đảm ủng hộ các công cụ không quy ước, mặc dù họ biết rằng các công cụ ít được chấp nhận nhất thường là những thứ tốt nhất. Dĩ nhiên sẽ là một lợi điểm lớn nếu như một nhóm có lựa chọn của riêng mình, bỏ ngoài tai tiếng nói của một cá nhân, vì ông chủ thường muốn thuê các lập trình viên dễ kiếm, và do đó phải là một ngôn ngữ phổ biến.

Nhưng điều gì cũng có nhiều mặt, ngay khi ngôn ngữ chính được chọn, các công cụ và chương trình khác vẫn nên được viết bằng một ngôn ngữ khác. Và nếu ngôn ngữ đó sẽ được nhúng, sự quyết định sẽ phụ thuộc vào văn hóa của cộng đồng lập trình. Việc học ngôn ngữ mới đối với người mới khởi đầu thường là đáng sợ, nhưng với người đã có kinh nghiệm, nó cũng như việc làm quen một thư viện mới. Thường thì người ta nghĩ một hệ thống lớn viết bằng 3, 4 ngôn ngữ thật là hỗn độn, nhưng theo ý tôi, thường thì các hệ thống đó mạnh hơn các hệ thống đơn ngữ.



Áp lực công việc nếu hiểu theo nghĩa bình thường thì đó là một dấu hiệu tốt, nó thể hiện khả năng và sức khỏe của hệ thống của bạn. Nhưng một khi áp lực đó được lập lịch thì điều đó có nghĩa là bạn buộc phải giao hàng sớm hơn bạn có thể, và điều đó thường không tốt, nhưng lại phổ biến. Áp lực được lập lịch thường có vài lý do: những lập trình viên không cảm thấy yêu thích công việc của mình, cũng có thể là từ khách hàng, họ nghĩ đòi hỏi sản phẩm sớm hơn sẽ khiến chúng ta làm việc chăm hơn. Điều này có thể là đúng, nhưng hiệu quả thực sự lại nhỏ, và thiệt hại lại lớn. Khách hàng thường không biết nội bộ của công việc như thế nào, do đó họ càng đặt thêm nhiều áp lực lên chúng ta. Điểm chính để chống lại áp lực được lập lịch là hiểu nó như một áp lực kinh doanh thông thường, giám sát quan hệ giữa các nguồn lực ta có và sản phẩm, Ước tính chi tiết, hào hiệp về tất cả nhân lực chúng ta có. Và điều này cho phép có những quyết định quản lý tốt về các khả năng cân bằng, co giãn.

Điều then chốt bên trong việc ước lượng này là: sức lao động là thứ chất lỏng hầu như không nén được. Hiểu theo cách khác, một lập trình viên sẽ không nói Không nhưng có thể nói: Khi nào ông sẽ từ bỏ thứ ông muốn?. Đánh giá rõ ràng, chính xác cũng là cách để được các lập trình viên kính trọng, và đây cũng là cách những người chuyên nghiệp hành xử. Thiết lập một lịch trình không tưởng rõ ràng sẽ gây đau đớn cho mọi người. Extreme Programming đã nói rõ về điều này, và tôi nghĩ ai cũng có thể dùng nó.


Trách nhiệm của bạn là hiểu những người dùng, và giúp ông chủ của bạn cũng hiểu như vậy. Vì người dùng không liên quan mật thiết đến quá trình sản xuất, họ sẽ cư xử khác so với bạn:

  • Người dùng thường tuyên bố ngắn gọn
  • Người dùng có công việc riêng, họ thường nghĩ về các cải tiến nhỏ trong sản phẩm, chứ không phải các cải tiến lớn.
  • Người dùng thường không có được cái nhìn về chính cộng đồng người dùng của họ.

Nhiệm vụ của bạn là đem lại thứ họ muốn, chứ không phải là thứ họ nói họ muốn. Tốt hơn, hãy đề nghị và kiểm chứng họ đồng ý về đề nghị của bạn trước khi bắt đầu. Bạn phải coi chừng tính kiêu ngạo cũng như tính khiêm tốn giả tạo khi muốn biết khách hàng cần gì. Lập trình viên được đào tạo để thiết kế và code. Nghiên cứu viên thị trường được đào tạo đế biết người khác muốn gì. Hai kiểu người này, hay hai trạng thái này trong cùng một con người phải làm việc hòa hợp với nhau để tạo ra được viễn cảnh tốt nhất. Và bạn hãy kiểm tra các suy nghĩ, ý kiến của bạn càng nhiều càng tốt.


Muốn thăng tiến đến một vị trí, hãy hành xử như là bạn đang ở trong vị trí đó. Muốn thăng tiến đến một chức danh, tìm hiểu xem người khác chờ đợi điều gì từ chức danh đó và làm chúng. Để được tăng lương, hãy thương lượng với đầy đủ thông tin. Nếu bạn cảm thấy bạn bị bỏ qua quyền được thăng tiến, hãy nói chuyện với ông chủ về điều đó, hỏi rõ ràng bạn cần phải làm gì để được như vậy và hãy làm chúng. Nghe có vẻ nhàm chán, nhưng thường thì những điều bạn thấy cần phải làm lại khác với ý kiến của ông chủ bạn. Và điều này cũng giúp chốt ông chủ của bạn lại ở một vài điểm. Hầu hết các lập trình viên đều có cái nhìn phóng đại về khả năng của mình. Dù sao, không phải ai cũng ở trong top-ten. Nhưng tôi đã thấy nhiều người không được đánh giá đúng mức, nhưng thường thì mọi người xung quanh tương đối vừa phải, bạn không thể được đánh giá đúng nếu như không làm cho ai thấy rõ ràng điều đó trong công việc. Đôi khi do nguyên nhân thói quen cá nhân, một số người sẽ không được để ý đến nhiều…



Nietschze đã cường điệu khi nói: Cái gì không huỷ diệt tôi sẽ làm tôi mạnh hơn. Trách nhiệm lớn nhất của bạn là với nhóm của bạn. Bạn phải hiểu rõ mọi người. Và tìm cách mở rộng công việc hơn là làm họ quá tải với chúng. Nói chuyện với mọi người về sức ép công việc, và cách nó đang ép họ. Nếu lập trình viên cảm thấy mình chịu được một dạng sức ép, họ sẽ cảm thấy có động lực từ đó. Bạn cũng nên tìm hiểu về động cơ làm việc của những người khác, cái gì làm cho họ thấy công việc thú vị. Nhiều khi bạn cũng không thể thỏa mãn được họ, nhưng ít ra bạn cũng biết được họ mong muốn điều gì.

Bạn cũng nên cho phép người khác (và cả chính bạn) thất bại đôi lần, và chuẩn bị có một số thất bại trong kế hoạch. Nếu không có thất bại nào, bạn sẽ không có được cảm giác phiêu lưu, hay là bạn đang không cố gắng đúng mức. Nếu ai đó cố tình không làm việc ở mức đúng với họ, hãy kiên nhẫn tìm cách làm cho họ hoạt bát hơn. Nhưng khi kiên nhẫn cạn hết thì hãy cứ sa thải. Bạn không thể tiếp tục giữ anh ta vì như vậy không công bằng với các thành viên khác.

Với những thành viên giỏi, hãy công khai tán dương họ trước mọi người, và giữ những lời phê bình ở chỗ riêng tư. Người giỏi thường làm những việc khó hơn, và điều này là tự nhiên, chẳng ai để ý gì đến điều đó nếu ai cũng làm việc chăm chỉ. Một thực tế ít khi nhìn thấy là 1 lập trình viên giỏi thường tốt hơn cả 10 lập trình viên kém. Nên có tình huống là, bạn sẽ đi nhanh hơn nếu bỏ những người yếu hơn ở lại phía sau. Nhưng thường thì như vậy chỉ mang lại các lợi ích ngắn hạn, về lâu về dài, cộng đồng cần những dạng ích lợi khác: sự đào tạo những người kém hơn, sự phổ biến tri thức trong mọi người, và khả năng đứng vững khi những người giỏi ra đi.


Bạn cân bằng nhu cầu cá nhân với nhu cầu của nhóm khi chọn các phương diện của dự án để tham gia. Bạn nên làm những gì bạn giỏi nhất, nhưng cũng nên học các kỹ năng mới. Kỹ năng lãnh đạo và giao tiếp quan trọng hơn kỹ năng kỹ thuật. Nếu bạn rất giỏi, hãy nhận phần khó và rủi ro nhất của công việc, và làm nó sớm nhất có thể.


Xây dựng tinh thần đồng đội và giữ cho mọi người có liên quan với nhau. Để xây dựng tinh thần đồng đội, những thứ như áp quần, logo, đồng phục cũng hay, nhưng không bằng những kính trọng cá nhân. Tinh thần này có được khi mọi người quyết định hy sinh vì tập thể và nghĩ rằng những hy sinh đó cũng là vì lợi ích của họ. Là leader, bạn không thể đòi hỏi điều này nhiều hơn bạn có thể cung cấp chúng. Chìa khóa của việc lãnh đạo là tạo sự đồng tâm nhất trí giữa mọi người.


Nhiều giám đốc nghĩ rằng lên kế hoạch và không cần để ý đến những người sẽ làm chúng. Điều này là không thể vì khả năng và năng suất của mọi người khác nhau.

Cũng như một nhạc trưởng cần cân nhắc các loại gỗ làm ra các nhạc cụ trong giàn nhạc, leader thường không thể tách rời các thành viên ra khỏi các công việc đã được chia. Đây cũng là lý do không nên phá vỡ các nhóm đang có hiệu suất cao.

Cũng có một nguy cơ tiềm tàng là mọi người sẽ chán những việc họ thường làm mà không được học các kỹ năng khác và cải thiện các điểm yếu của họ. Dù sao, chuyên môn hóa vẫn tốt nếu không bị lạm dụng.


Nhiều khi không thể tránh được các công việc nhàm chán, vì nó quan trọng với sự thành công của dự án. Những công việc này có thể làm tổn thương những người làm chúng. Hãy tìm cách bắt máy tính làm giùm, hay giúp các thành viên khác làm nó. Làm một chương trình làm những công việc nhàm chán trong một tuần hay tự làm việc đó cũng trong một tuần, dĩ nhiên cách làm tự động hóa sẽ tốt hơn. Nếu không thể khác được thì cũng phải làm thôi, nhưng đừng để những người phải làm việc đó một mình, ít nhất hãy giao việc đó cho một nhóm hai người.


Tạo ra một viễn cảnh và minh họa giá trị của viễn cảnh đó với cả tổ chức. Cho phép người khác có phần trong viễn cảnh đó. Tìm ra các nhà tài trợ chính riêng rẽ, làm một mô hình để minh họa các ý tưởng. Mô hình, hình mẫu luôn tốt hơn, nhất là trong ngành phần mềm.


Hạt giống chứa những ý tưởng từ những người đã trưởng thành nhưng chưa được thực hiện. Hạt giống phát triển thành phôi, và lớn lên. Và cuối cùng thì đơm hoa kết trái. Về sau thì cây chết và xác nó dùng để nuôi những sinh vật khác. Phần mềm cũng vậy. Một cây cầu thì không thể như vậy, chúng ta có một chiếc cầu chưa hoàn tất, chứ không có một chiếc cầu “trẻ em”, vì cầu đơn giản hơn phần mềm nhiều.

Bạn nên nghĩ về phần mềm như một sinh vật phát triển, nó cho phép chúng ta có những bước tiến dài trước khi thấy được hình ảnh sau cùng. Phải có được phản hồi từ phía người dùng về phần mềm. Phát triển và tỉa bớt các cành yếu. Lập trình viên là những người phát triển một sản phẩm hoàn chỉnh, nhưng lập trình viên giỏi phải phát triển được con đường phát triển cho đến hệ thống sau cùng.

Những cách tiếp cận thường có dạng xoắn ốc, và nhớ đặt những milestone trên đó. Và trên đường phát triển, không chỉ phát triển hệ thống mà phát triển nhóm và con người.

Rob Hafernik đã gửi cho tôi những ghi chú này, và tôi không thể làm tốt hơn là trích dẫn lại ở đây:

Đó không phải chỉ là hệ thống, mà là thuật toán, giao diện người dùng, mô hình dữ liệu, vân vân… Điều sống còn là bạn làm việc trên toàn hệ thống để biết được nó đạt những mục tiêu trung gian. Không gì tệ hơn việc xây dựng tất cả mọi thứ để cuối cùng biết rằng nó không làm việc (như thất bại gần đây ở Voter News System). Vì điều đó là do một quy luật tự nhiên: không hệ thống phức tạp nào được xây từ đầu, nó chỉ có thể tiến hóa từ hệ thống đơn giản lên hệ thống phức tạp qua những bước có chủ ý.


Giao tiếp tốt rất khó, nó là một kỹ năng thuộc về chính nó. Càng khó hơn, vì người mà bạn giao tiếp ai cũng có thiếu sót. Thường họ không cố hiểu bạn, họ diễn đạt nghèo nàn. Họ thường làm việc quá nhiều, hay quá chán công việc, và thường chú trọng vào việc của họ hơn những điều bạn đề cập. Bạn càng viết, nghe, nói giỏi, bạn càng dễ tìm hiểu xem vấn đề nằm ở đâu và làm sao để giải quyết chúng.

Lập trình viên là một sinh vật có xã hội và sống phụ thuộc vào giao tiếp với cộng nhóm mình. Lập trình viên giỏi là những sinh vật xã hội chỉ bằng lòng với việc giao tiếp nhiều hơn ra ngoài nhóm của mình. Và ông chủ (nếu không phải là lập trình viên) cần lập trình viên vì họ là một phần của chiếc cầu nối giữa các ý tưởng và thực thể trong quần thể.

Tôi không hẳn đã giao tiếp tốt, nhưng tôi thường làm các cách sau: chuẩn bị các ý tưởng, nói cho người khác nghe, giao cho họ một văn bản viết, cho họ xem demo, và lặp đi lặp lại như vậy. Và không nên thất vọng khi các ý tưởng của bạn chưa được chấp nhận.


Nhiều khi bạn phải nói với một người những điều sẽ làm họ khó chịu. Nhớ rằng bạn làm vậy có lý do, ngay cả khi không thể làm được gì khác thì hãy cố nói với họ sớm. Cách thông báo tốt nhất là kèm theo luôn một giải pháp. Cách thứ nhì là nhờ họ giúp với chính vấn đề đó. Và có nguy cơ là người ta sẽ không tin bạn, và bạn cần hậu thuẫn cho sự quyết đoán của mình.

Một trong những điều khó chịu nhất bạn thường nói là: kế hoạch phải trễ một thời gian. Ai có lương tâm cũng ghét những câu này, vậy nên hãy nói nó sớm. Không gì tệ hơn tiếp tục trì hoãn khi đã trễ. Bạn cũng có thể tìm cách nói điều đó với sự hậu thuẫn của một nhóm.


“Chuyện hoang đường” hàm nghĩa không có thật, nhưng nó có những ý nghĩa sâu xa hơn. Nó có nghĩa như là những câu chuyện của lòng tin, những câu chuyện giải thích quan hệ giữa con người và vũ trụ. Những giám đốc thường quên họ đã học những gì khi còn là lập trình viên, và tin vào những chuyện hoang đường ấy dễ dàng. Bạn cần phải nhận ra những điều đó:

  • Nhiều tài liệu hơn là tốt hơn (họ muốn có tài liệu, nhưng họ không muốn bạn mất thời gian để làm chúng).
  • Có thể coi mọi lập trình viên như nhau (thật sự các lập trình viên rất khác nhau).
  • Có thể thêm tài nguyên vào một dự án trễ để tăng tốc (chi phí giao tiếp với những người mới nhiều khi nhiều hơn là những người đó có thể giúp).
  • Có thể ước lượng chi phí phát triển phần mềm chính xác (điều này ngay cả về mặt lý thuyết cũng không làm được).
  • Có thể ước lượng hiệu suất của lập trình viên bằng một số lượng giá đơn giản, như số dòng code (nếu như ngắn gọn là sức mạnh, thì có lẽ càng ít code càng tốt).

Nếu có cơ hội, hãy tìm cách giải thích những điều này, nhưng đừng thất vọng nếu không thành công, và đừng chiến đấu một cách ngoan cố. Những huyền thoại này chỉ cũng cố ý kiến của các giám đốc là mình phải cố kiểm soát mọi việc. Sự thật là người ta đã ủng hộ nếu nó tốt và chống lại nếu nó xấu.


Có những lúc công ty sẽ có vấn đề: ngừng sản xuất, công ty bị mua lại… Những điều này không làm ai yên tâm, nhưng có lẽ ít tác động đến lập trình viên hơn, vì tính cách lập trình viên thiên về khả năng hơn là vị trí. Nếu bạn không phải là lập trình viên, xin dừng ở đây.

Các kỹ sư có năng lực sáng tạo, và chống đỡ. Những người không phải là kỹ thuật có thể ra lệnh cho người khác xung quanh, nhưng họ chẳng làm gì được nếu không có các kỹ sư. Và đây là nền móng để tạm thời chống đỡ các tình trạng hỗn loạn trong tổ chức. Nếu bạn lâm vào tình trạng đó, tốt nhất làm lơ và tiếp tục công việc như chẳng có gì xảy ra. Rất thường thấy một kẻ xả stress nào đó không có năng lực sẽ tìm cách bảo bạn làm những điều ngu ngốc, tốt nhất là hãy cười và chẳng làm gì hết cho đến khi hắn đi khỏi, và tiếp tục làm những gì bạn nghĩ là tốt nhất lúc đó. Đây là điều tốt nhất có thể làm cho bạn, và cho cả dự án và công ty.