Friday, October 31, 2008

Ubuntu post-installation notes

Well, I have to reinstall Ubuntu Linux (not the latest version, though) .

1/ Partitionize two partitions: 60 GB (ext3) for root, and 400MB for swap
2/ Install Ubuntu from live CD (using the mentioned partitions as "/" and "swap" mount point)
3/ Get a quick reference in hard-copy or from either wiki or .
4/ Open a terminal/konsole (by Alt+F2 and typing: gnome-terminal )
5/ Add extra repositories of APT by editing sources.list:
$ sudo cp -p /etc/apt/sources.list /etc/apt/sources.listBACKUP
$ sudo gedit /etc/apt/sources.list

+ Add "universe" and "multiverse" repositories to the end of ALL repositories lines
deb CODENAME main restricted

deb CODENAME main restricted universe multiverse

(with the CODENAME is "hardy" for 8.04 or lower, "feisty" for 7.04 or lower, etc...)

+ Then we add SECURITY, BACK-PORTS, PLF and CANNONICAL repositories:
deb CODENAME-security main restricted universe multiverse
deb-src CODENAME-security main restricted universe multiverse

## BACKPORTS REPOSITORY (May contain illegal packages. Use at own risk.)
deb CODENAME-backports main restricted universe multiverse
deb-src CODENAME-backports main restricted universe multiverse

## PLF REPOSITORY (May contain illegal packages. Use at own risk.)
deb CODENAME free non-free

## CANONICAL COMMERCIAL REPOSITORY (Hosted on Canonical servers)
deb CODENAME-commercial main

+ Save the file (sources.list)

6/ Update the APT repositories list with approriate GPG key :
$ wget -q -O- | sudo apt-key add -
$ sudo apt-get update

7/ Install gcc, g++, make, and libc , by using APT with "build-essential" :
$ sudo apt-get install build-essential

8/ Install more build tools, such as cvs, xorg, xlibs, ... :
$ sudo apt-get install cvs xorg-dev xlibs-dev libxft-dev libx11-dev

9/ Install MS TrueType core fonts (Arial, Tahoma, Verdana, Courier New, Times New Roman) :
$ sudo apt-get install msttcorefonts

10/ Install xvnkb (Vietnamese typing) from .deb package :
$ wget
$ sudo dpkg -i xvnkb-0.2.9a-utf_i386.deb

+ 2nd method: from source (prerequisite: steps 7 and 8 above)
$ cvs -d '' login
$ cvs -z3 -d '' checkout xvnkb
$ cd xvnkb
$ ./
$ ./configure
$ make
$ sudo make install

11/ Install Adobe Flash Player using APT :
$ sudo apt-get install flashplugin-nonfree
$ sudo update-flashplugin

+ 2nd method: get from Adobe site and install manually
$ wget
$ tar -cxvf install_flash_player_9_linux.tar.gz
$ sudo cp -f install_flash_player_9_linux/ /usr/lib/firefox/plugins/
$ sudo cp -f install_flash_player_9_linux/ ~/.mozilla/firefox/

12/ Install codecs for music/movie player :
$ sudo apt-get install w32codecs

13/ Install MPlayer plugin for Firefox/Mozilla (automatic install MPlayer) :
$ sudo apt-get install mozilla-mplayer

or if you prefer VideoLAN client instead of MPlayer (automatic install VLC) :
$ sudo apt-get install mozilla-plugin-vlc

14/ Install ntfs-3g (old kernel version need this driver for better writing to NTFS partition) :
$ sudo apt-get install ntfs-3g ntfs-config

15/ Install xchm (I prefer CHM Reader plugin of FF, though) :
$ sudo apt-get install xchm

16/ Install stardict :
$ sudo apt-get install stardict stardict-tools

+ Note: The dictionary data (available at: ) should be put in /usr/share/stardict/dic to work for StarDict. The pronounciation data (WyabdcRealPeopleTTS directory) should be put in the /usr/share directory, and with read permission allowed) .

17/ Change password for 'root' user :
$ sudo passwd root
Enter new UNIX password: ...
Retype new UNIX password: ...

18/ Add another user (my annoying brother) :
$ sudo mkdir -p /home/kidlaze
$ sudo useradd kidlaze -m /home/kidlaze
$ sudo passwd kidlaze
$ sudo chown kidlaze /home/kidlaze

+ 2nd method (GUI):
$ sudo users-admin

UPDATED: To make the default permission for newly created file/directory, you may change the usermask for easier dealing with permission problem, by adding the command at the end of start-up scripts :
$ sudo gedit ~/.bashrc

Add this simple command, at the end of the file .bashrc :
umask 002

Then save the file.

Personally speaking, I like changing the shell prompt, by editing the rc file in a similar way (adding the below command to the end of .bashrc file) :
PS1="[bibo @ \h: \w]\$ "

Well, that's enough for a basic user. For more applications, pls take a look at part 2 and more .

Have fun !

Thursday, October 30, 2008

Tuesday, October 28, 2008

Java Tiger and Mustang [2]

Trong bài trước tôi đã nêu những điểm mới trong JDK 5 (Tiger) , và bài này sẽ nêu những điểm mới của JDK 6 (tên mã Mustang) :

Các cải tiến chính của Mustang là nhắm vào GUI và lập trình Desktop.

Đọc và ghi dữ liệu ra màn hình console một cách thuận tiện.


java.util package
Phương thức copyOf của Array
Arrays.copyOf(int[] original,int iLength);
Arrays.copyOf(double[] original,int iLength);

Calendar có thêm DisplayName
String getDisplayName(int field, int style, Locale locale)
Map getDisplayNames(int field, int style, Locale locale)

Empty String methods
boolean isEmpty()

java.awt package
Đối tượng Desktop : Lập trình viên có thể gọi trình chạy tương ứng để đọc hoặc chạy bất kỳ file nào.

Desktop d = Desktop.getDesktop();
boolean isSupported(int action);
void open(File file)

java.awt package
Đối tượng SystemTray và TrayIcon : Tạo icon cho chương trình chạy ngầm trên System Tray

SystemTray t = SystemTray.getSystemTray();
TrayIcon tc =
new TrayIcon(Image i, String strTittle, PopupMenu p);
tc. setImageAutoSize(boolean b)

Splash Screen : Tạo màn hình splash trong lúc đợi máy ảo Java nạp chương trình.

java -splash:mySplashScreen.jpg HelloSplash
SplashScreen s = SplashScreen.getSplashScreen();
g = (Graphics2D)splash.createGraphics();

SortedTable : Sắp xếp và lọc dữ liệu trên bảng

class RowSorter
class RowFilter


TextPrint : In dữ liệu từ text ra máy in, hỗ trợ paste.


Tab Pane : Tab Component Pane
setTabComponentAt(int index, Component c) package
GifWriter : Hỗ trợ convert sang chuẩn ảnh gif
DiskSpace : Xem thông tin còn trống trên các ổ đĩa.

JDBC 4.0 : (12/2006)
Không cần chỉ rõ Driver lúc dịch.
Nâng cao có chế bắt lỗi :

SQLException implements Iterable.
Bắt nhiều lỗi trong một SQLException

Đối tượng RowId
RowId rowid = rs.getRowId(int index);

Cuối cùng là hỗ trợ thêm khả năng kéo thả của nhiều Component và JComponent

Have fun,

Monday, October 27, 2008

Web server choice [2]

Servlet containers: Tomcat vs Jetty vs Resin

(đang viết tiếp)

Sunday, October 26, 2008

Web server choice

Apache vs Lighttpd vs Cherokee vs Nginx vs AsyncWeb

+ Apache: suitable for student learnings, and SME .

+ Lighttpd: for start-ups (especially Web 2.0)

+ Cherokee: for big enterprises who don't have their own one (and maybe Web3.0 start-ups? )

+ Nginx: It's a good alternative for Apache, for better security and slightly better performance

+ AsyncWeb: written in pure Java, has some potential to compete with the well-knowns

FYI, those all are open source software, and the performance of Cherokee > Lighttpd > Nginx > Apache ~ AsyncWeb .
(Mongrel is also a honourable mention, for Ruby guys)

The Servlet ones will be discussed in the next entry.

Saturday, October 25, 2008

Well-known ports

FTP 21 (control) , 20 (data)
IMAP 143
POP3 110
Telnet 23
SSH 22

MySQLd 3306
Oracle 1521 , 2483
Tomcat 8080
JBoss 8080
IRCd 6667 , 194
SVN 3690 , 3980
Torrent 6881-7000
Rsync 873

LDAP 389
Kerberos 88
OpenVPN 1194
RTMP 3500
RIP 520
RPC 530
SQLServer 1443

NTP 123
Auth 113
epmap 135
NetBIOS 139

Friday, October 24, 2008

Java test tools

As a QA (or a tester) , you should be familiar with Test Driven Development and such phrases: Test plan, Test case, Test suite, Test report, Test coverage . A good programmer should be familiar with them, too.

For a non-trivial application, there are several kinds of test: Unit, Functional, Integration, System, Acceptance, Regression, Non-functional, Performance, Load, Soak; and Continuous Integration .

Using the good tools can enhance productivity substantially , so let's have a look at some best tools around:

+ IDE : Eclispe, NetBeans
+ Build: Ant, Maven
+ Unit test: JUnit, TestNG
+ Mock object: JMock, EasyMock
+ Database: DBUnit
+ Servlet container: Cactus
+ Web application: Selenium, HttpUnit
+ Coverage: Cobertura, Emma
+ Performance: JMeter, Eclipse TPTP
+ Acceptance: Selenium, FitNesse, Stiq
+ Continuous Integration: Cruise Control, Continuum, Hudson

If you are new to testing in java, you can start with JUnit. My recommended books then are Java Power Tools (chapter 13), and Pragmatic Unit Testing: In Java With JUnit .

btw, when you find something more useful feel free to tell me !

Thursday, October 23, 2008

Symfony quick note

Từ khi Ruby on Rails ra đời và thành công rực rỡ, cộng đồng PHP đã học hỏi Rails và bắt đầu tạo nên hàng loạt framework để phát triển web bằng PHP với nhiều điểm học lại từ Rails , trong đó các framework nổi tiếng nhất là Kohana (CodeIgniter), Symfony, Zend, CakePHP, Akelos, ...

(đang viết tiếp)

Wednesday, October 22, 2008

Interview Question: Ask!

What behavior do you think recruiters find most unforgivable?

1/ Poor personal appearance

2/ Overemphasis on money

3/ Failure to look at interviewer while interviewing

4/ Doesn’t ask questions

5/ Late to interview

hehe, which one ?

Tuesday, October 21, 2008

Google DevFest Vietnam


Thanks for registering for Google DevFest Vietnam! We're looking forward to meeting you there. Be sure to bring your laptops, power chords, questions, and enthusiasm.

The event details are as follows:

Registration will begin at 1pm on November 4th. Please join us at that time.
The event will be hosted at Ho Chi Minh University of Technology, in the A5 conference room.

Attached is a map with directions to the Ho Chi Minh University of Technology.

See you soon!

Developer Relations, Google Inc."

khà khà, cái Hackathon này sẽ vui đây :D

Monday, October 20, 2008

Tritanium Key

Yet another Vietnamese typing software !

Ai quan tâm có thể tải về chạy thử xem sao :)

Sunday, October 19, 2008

Standard Widget Toolkit

SWT là một UI toolkit mã nguồn mở được khởi đầu bởi IBM, nhằm phát triển GUI bằng ngôn ngữ Java, thay cho các gói truyền thống được Sun cung cấp sẵn như AWT, Swing.

Mục tiêu của SWT là cung cấp giao diện thuần (Native) và cải thiện về mặt tốc độ so với Swing, nên SWT chủ yếu hiện thực bằng cách gọi API của chính OS trên platform đó, thay vì tự vẽ lại như Swing. Đa số API của các OS phổ biến hiện nay đều hiện thực bằng C/C++ nên thường SWT sử dụng JNI để hiện thực chức năng nói trên.

Một điểm lưu ý nữa là SWT khuyến cáo người phát triển tự loại bỏ các thành phần không dùng tới, thay vì dựa vào bộ dọn rác (garbage collector) của Java .

Các thành phần SWT thường dùng:

+ Display và Shell
+ Label, Text và StyledText
+ Button (push, check, radio, toggle, arrow)
+ Slider, Spinner và Sash
+ Table, TableColumn, TableItem và TableEditor
+ TabFolder và TabItem
+ ToolBar và ToolItem
+ Tray và TrayItem
+ Tree và TreeItem
+ ToolTip và ProgressBar
+ ... (ngoài ra còn nhiều thành phần mà AWT/Swing không có) ...

(Nếu trong Eclipse chưa có gói swt.jar thì bạn có thể vào website Eclipse để tải)

Saturday, October 18, 2008

Unikey 4.0 Final

Như đã có nói ở bài trước , Unikey là bộ gõ tiếng Việt phổ biến nhất trên Windows , và có lẽ cũng là tốt nhất (hiện chỉ có WinVnKey có khả năng vượt qua) .

Hiện đã ra phiên bản 4.0.8 Final ở đây:

Chưa rõ phiên bản trên có phải là official release hay không, theo Mediocre Ninja biết thì dường như là do một thành viên của tự mod lại, chứ không phải của anh Phạm Kim Long và Lâm Vĩnh Niên.

Phiên bản Unikey 4.0 RC xài cũng khá ổn định, bạn nào xài ổn thì cứ xài tiếp khoan dùng bản mới vội. Mặc dù bản mới này tuyên bố sửa được vài lỗi trên Vista, và chạy tốt trên Vista 64 bit .

Friday, October 17, 2008

Interview Question: FizzBuzz

Đây là 1 câu hỏi phỏng vấn dạng simple programming test (không dùng computer), nhằm loại bớt những người dự tuyển tuyên bố là thông thạo về 1 ngôn ngữ nào đó (nhưng thực tế rất ít viết code).

Theo tôi dạng phỏng vấn này khá hiệu quả, bởi nó cho thấy ứng viên có lập trình bằng ngôn ngữ này trong vòng 3 tháng gần đây, và cũng phần nào phản ánh suy nghĩ, phong cách lập trình của người viết.
Ít ra cũng không thuộc dạng stupid-interview-questions (cái này khi nào có dịp sẽ bàn kỹ hơn) .

Đề bài:
Write a program that prints the numbers from 1 to 100. But for multiples of three print "Fizz" instead of the number and for the multiples of five print "Buzz". For numbers which are multiples of both three and five print "FizzBuzz".
(Viết 1 chương trình in các con số từ 1 đến 100. Tuy nhiên ở những con số là bội số của 3 thì in ra "Fizz", bội số của 5 thì in ra "Buzz", bội số của cả 3 và 5 thì in ra "FizzBuzz" thay cho các con số đó.)

Dĩ nhiên là There's More Than One Way To Do It (TMTOWTDI, đọc là "tim-toady") , câu nói yêu thích của các lập trình viên Perl.

Ở đây tôi nêu lên vài cách giải mà theo tôi là ổn (if I were the interviewer) :

* Đơn giản: (KISS, YAGNI)
Code đơn giản không có nghĩa là code ngắn nhất, hay là phải dùng những phần tử cơ bản nhất, mà là dễ dàng đáp ứng ĐỦ yêu cầu (kết quả đúng ngay từ lần đầu chạy), trong khi trình bày ngắn gọn và dễ hiểu.


for i in range(1, 100):
if (i % 3 == 0) and (i % 5 == 0):
print “FizzBuzz”
elif i % 3 == 0:
print “Fizz”
elif i % 5 == 0:
print “Buzz”
print i


1.upto(100) do |number|
if number % 15 == 0 then
puts 'FizzBuzz'
elsif number % 5 == 0 then
puts 'Fizz'
elsif number % 15 == 0 then
puts 'Buzz'
puts number


(for (i 1 100)
(= 0 (% i 15)) (set 'i "FizzBuzz")
(= 0 (% i 5)) (set 'i "Buzz")
(= 0 (% i 3)) (set 'i "Fizz"))
(println i))

* Dễ dùng lại và mở rộng: (DRY, DRW)
VD nếu như sửa Blah là bội của 4 (thay vì Fizz của 3), hoặc thêm vào FizzBuzzBlah là bội của 60 (3x4x5) , thì liệu code bạn viết lại có đỡ tốn công và vẫn giữ được các ưu điểm (dễ hiểu, chạy nhanh, ...) hay không?


a = nil, 'fizz', 'buzz', 'fizzbuzz'
1.upto(100) { |a[0]| puts a[(a[0]%3 == 0 ? 1 : 0) + (a[0]%5 == 0 ? 2 : 0)] }

(Ruby - extended)
a = nil, 'Fizz', 'Buzz', 'FizzBuzz', 'Blah', 'FizzBlah', 'BlahBuzz', 'FizzBuzzBlah'
1.upto(100) { |a[0]| puts a[(a[0]%3 == 0 ? 1 : 0) + (a[0]%5 == 0 ? 2 : 0) + (a[0]%4 == 0 ? 4 : 0)] }

* Dễ nhìn, thanh thoát: (Refactoring, DRY)
Thường sau khi viết đạt yêu cầu KISS ta sẽ refactor code để củng cố YAGNI và DRY , cũng để code dễ nhìn và dễ hiểu hơn, mặc dù về performance hoặc line-of-code thì có thể không tối ưu lắm.

(Java - verbose)
public class FizzBuzz {
public static void main(String[] args) {

for(int i = 1; i <= 100; i++) {
if (((i % 3) == 0) && ((i % 5) == 0))
else if ((i % 3) == 0)
else if ((i % 5) == 0)
else System.out.println(i);

(Java - shorter)

public class FizzBuzz {
public static void main(String[] args) {

for(int i = 1; i <= 100; i++) {
i%15!=0?i%5!=0?i%3!=0 ? i :"Fizz":"Buzz":"FizzBuzz" );

(chứ phỏng vấn thiệt mà tìm tòi hướng này chắc là ít nhất cũng cả tiếng cho 1 bài cỡ FizzBuzz)

* Cực ngắn, gõ ít nhất: (one-liner, Perl-Golf)
Bạn phải đam mê lập trình thực sự mới tham gia được loại này. Cái kiểu one-liner này xuất phát từ Perl, do sự linh động, uyển chuyển và mạnh mẽ của Perl trong xử lý text của Perl. Bây giờ các lập trình viên ngôn ngữ hậu duệ của Perl (như Python, Ruby) cũng bắt đầu thích trò brainstorming này :D

for i in range(1,101):print”FizzBuzz”[i*i%3*4:8–-i**4%5]or i


print$_%3?$_%5?$_:"":Fizz,$_%5?"":Buzz,"\n"for 1..100;

* Phức tạp hóa, làm rối rắm: (complicated, obfuscated)

using System;

namespace FizzBuzz
internal class Program
private static void Main()
IFormatProvider formatProvider = new FizzBuzzFormatter();

for (int i = 1; i < = 100; i++)
Console.WriteLine(String.Format(formatProvider, “{0:FB}”, i));


internal class FizzBuzzFormatter : ICustomFormatter, IFormatProvider
public string Format(string format, object arg, IFormatProvider formatProvider)
if (format == null)
return String.Format(”{0}”, arg);

if (format.StartsWith(”FB”) && arg is int)
int val = (int) arg;
bool mod3 = val%3 == 0;
bool mod5 = val%5 == 0;

if (!mod3 && !mod5)
return arg.ToString();

string s = String.Empty;

if (mod3)
s += "Fizz";

if (mod5)
s += "Buzz";

return s;

return String.Format(”{0:” + format + “}”, arg);

public object GetFormat(Type formatType)
if (formatType == typeof (ICustomFormatter))
return this;
return null;

(Csharp - longer)
public abstract class Factory
public string ToString(char[] chars)
return new string(chars);

public class FizzFactory : Factory
private const char F = 'F';
private const char i = 'i';
private const char z = 'z';

public bool isFizz(int input)
if (input == 3) return true;
else if (input == 6) return true;
else if (input == 9) return true;
else if (input == 12) return true;
else if (input == 15) return true;
else if (input == 18) return true;
else if (input == 21) return true;
else if (input == 24) return true;
else if (input == 28) return true;
else if (input == 30) return true;
else if (input == 33) return true;
else if (input == 36) return true;
else if (input == 39) return true;
else if (input == 42) return true;
else if (input == 45) return true;
else if (input == 48) return true;
else if (input == 51) return true;
else if (input == 54) return true;
else if (input == 57) return true;
else if (input == 60) return true;
else if (input == 63) return true;
else if (input == 66) return true;
else if (input == 69) return true;
else if (input == 72) return true;
else if (input == 75) return true;
else if (input == 78) return true;
else if (input == 81) return true;
else if (input == 84) return true;
else if (input == 87) return true;
else if (input == 90) return true;
else if (input == 93) return true;
else if (input == 96) return true;
else if (input == 99) return true;
else return false;

public string GetFizz()
return base.ToString(new char[4] { F, i, z, z });

public class BuzzFactory : Factory
private const char B = 'B';
private const char u = 'u';
private const char z = 'z';

public bool isBuzz(int input)
if (input == 5) return true;
else if (input == 10) return true;
else if (input == 15) return true;
else if (input == 20) return true;
else if (input == 25) return true;
else if (input == 30) return true;
else if (input == 35) return true;
else if (input == 40) return true;
else if (input == 45) return true;
else if (input == 50) return true;
else if (input == 55) return true;
else if (input == 60) return true;
else if (input == 65) return true;
else if (input == 70) return true;
else if (input == 75) return true;
else if (input == 80) return true;
else if (input == 85) return true;
else if (input == 90) return true;
else if (input == 95) return true;
else if (input == 100) return true;
else return false;

public string GetBuzz()
return base.ToString(new char[4] { B, u, z, z });

public delegate void FizzBuzzWriter(string input);
public class Looper
private FizzFactory Fizz;
private BuzzFactory Buzz;
public event FizzBuzzWriter OnFizzBuzz;

public Looper(Factory fizzFact, Factory buzzFact)
Fizz = (FizzFactory) fizzFact;
Buzz = (BuzzFactory) buzzFact;

public void execute(int start, int finish)
for(int i = start; i<=finish; i++)
string val = String.Empty;
if (Fizz.isFizz(i)) val += Fizz.GetFizz();
if (Buzz.isBuzz(i)) val += Buzz.GetBuzz();
if (val == String.Empty) val = i.ToString();

if (OnFizzBuzz != null) OnFizzBuzz(val);


public class TheFizzBuzzProgram
public static void main(string[] args)
Looper l = new Looper(new FizzFactory(), new BuzzFactory());
l.OnFizzBuzz += new FizzBuzzWriter(l_OnFizzBuzz);

static void l_OnFizzBuzz(string input)
Console.Write(input + Environment.NewLine);

* Hiệu quả, chạy nhanh nhất: (performance, effectiveness)
Chưa test, ai có kết quả test vài trường hợp thì post lên thử nhé ^_^

Search vòng vòng Internet còn thấy thêm khá nhiều implementation với nhiều ngôn ngữ nữa, có thể kể JavaScript, ASP, Pascal, C++, VB, Groovy, Prolog, SmallTalk, Scheme, Haskell, Erlang, COBOL, bash, batch, ... thậm chí cả SQL (yay!), XSL (wow!), hợp ngữ IL (cool!), ASM86 trên Windows lẫn Linux (cooler!) , ASM51 (w00t!), etc ; nhưng nhìn chung mấy đoạn mã ở trên là đủ tiêu biểu rồi :D

Have fun !

Wednesday, October 15, 2008

Self-reproducing programs

Also known as quine :D

My quick try:


public class PrintMySelf { //Print the very source code
//this simple version replace line comment by blank line

public static void main(String args[]) throws IOException {

//use PushbackInputStream to get/unget each character
FileInputStream fileIS = new FileInputStream("");
PushbackInputStream pushbackIS = new PushbackInputStream(fileIS);

int dataByte = 0;

while ( (dataByte = != -1 ) {
char dataChar = (char) dataByte;

if (dataChar == '/') { //strip all line comments
dataChar = (char);

if (dataChar == '/') {
dataByte =;

while ( (dataByte != -1) && (dataByte != 13) ) {
dataByte =;
dataChar = (char) dataByte;

} else {
pushbackIS.unread( (int) dataChar );



Some other solutions:


s = 's = %c%s%c%cprint s %% (39, s, 39, 10)'
print s % (39, s, 39, 10)


class PrintMyself { static void Main(string[] args) {string x1 = ";char[] x2 = {'c','l','a','s','s',' ','P','r','i','n','t','M','y','s','e','l','f',' ','{','{',' ','s','t','a','t','i','c',' ','v','o','i','d',' ','M','a','i','n','(','s','t','r','i','n','g','[',']',' ','a','r','g','s',')',' ','{','{','s','t','r','i','n','g',' ','x','1',' ','=',' ','{','0','}','{','1','}','{','0','}'};System.Console.Write(string.Format(new string(x2), (char)34, x1) + x1);}}";char[] x2 = {'c','l','a','s','s',' ','P','r','i','n','t','M','y','s','e','l','f',' ','{','{',' ','s','t','a','t','i','c',' ','v','o','i','d',' ','M','a','i','n','(','s','t','r','i','n','g','[',']',' ','a','r','g','s',')',' ','{','{','s','t','r','i','n','g',' ','x','1',' ','=',' ','{','0','}','{','1','}','{','0','}'};System.Console.Write(string.Format(new string(x2), (char)34, x1) + x1);}}

Have fun,

Tuesday, October 14, 2008

Future programming language?

According to TIOBE, Java is the most popular programming language now.

Nevertheless, we can see new waves: Python, Ruby, Groovy, Scala, F#, Arc, ... And the others are still rolling .

Which one do you think will be dominant in 2012 - 2013 ?

Monday, October 13, 2008

Best text editors

Developers still spend a lot of time with plain text. No matter how many wizards and other sorcerers we develop, most coding is still in plain text. Most of the information you keep should also reside in plain text because you never know if the tool you are using will be around in five years. It’s a good bet that you’ll be able to read plain ASCII (and probably Unicode) for the next century or so.
(As The Pragmatic Programmer [Addison-Wesley] admonishes: "Keep knowledge in plain text.")

Because so much of what we do revolves around text, it makes sense to find your perfect text editor.

This isn’t about IDEs; company policy and the language you use generally dictate that. IDEs are great at producing source code. But they are lacking in some of the best tools for plain old text.

And IDE is usually "heavy" (i.e. resource-consuming) for the student computer, whereas the developer often just want a quick edit. Why would we need to wait 8 seconds for IDE booting, just for a 5 second copy & paste & modify? Therefore it's essential to get a general source code editor (or lightweight IDE), beside the primary IDE .

Hence, which text editor to pick ?

Usually, the criteria for a good text editor are :

+ Syntax highlighting (i.e colorful)

+ Line number, column number, num of chars, ...

+ Braces matching and block folding

+ Smart indent , bracing, shortcut keys

+ Multi programming languages support

+ Customizable syntax/font/theme/hotkey...

+ Auto completion (keywords, APIs, ... )

+ Lightweight, small footprint

+ Macro recording

+ Supports multi types of line-breaking, character encoding, collation

+ Regular Expression search/replace

+ Multiple documents (tab/panel/... ) in a window

+ Multiple views in a document window

+ Some advanced features (convert charset, file explorer, function list, link compiler, plugins, ... )

Now, let's have a look at the candidates:

1/ Notepad++ (screenShot) : currently it is the most favourite one. It has enough good features, and does the job well. Despite being written in C++ and WinAPI (based on Scintilla lib), it can run smoothly on *nix via Wine. Notepad++'s biggest drawback is the slowness when processing large file ( > 100 MB) , you can begin to see this downfall if you have to open an XML or SQL file which is more than 80 MB.
( thôi viết tiếng Việt cho khỏe :D )

2/ jEdit (screenShot) :

3/ SciTE (screenShot) : cũng là phần mềm mã nguồn mở và dùng thư viện Scintilla như Notepad++ , do chính tác giả của Scintilla phát triển (ban đầu nhằm minh họa thư viện trên). SciTE có phiên bản chạy tốt trên cả Win lẫn Linux, có dung lượng nhỏ nhưng đầy đủ tính năng của 1 editor mạnh, và đã được AutoIT developer xem là editor chính cho AutoIT .

4/ Emerald (screenShot) : trước đây là Crimson Editor, từng được coi là text editor miễn phí tốt nhất trên Windows (như Notepad++ bây giờ) , sau đó ngưng phát triển 1 thời gian nên bị các tool kia vượt qua, và bây giờ come back với tên mới là Emerald :D

5/ PSPad (screenShot) :
cũng là phần mềm miễn phí nhưng không open source, hỗ trợ rất nhiều ngôn ngữ lập trình (nhất là các loại về Web) . Nói chung nếu bạn chỉ code trên Windows thì cái này cũng là ứng cử viên nặng ký.

6/ kate (screenShot) : cá nhân tớ đánh giá kate khá cao , nếu chỉ xét các text editor dạng GUI trên Linux thì xem như nó đỉnh nhất, hơn gedit hay kedit, kwrite nhiều. Các chức năng IDE cũng có thể cạnh tranh với XEmacs, Geany, BlueFish, ... nói chung nếu bạn xài KDE thì nên dùng kate làm text editor chính.

7/ Emacs derivation (XEmacs, Aquamacs, nano, pico, ...) :
(to be updated)

8/ vi derivation (VIM, elvis, nvi, vile, ... ) :
VI/vim is a very good powerful and lightweight editor. It can run on console, i.e. command-line, of ALL the modern Operating Systems. VI/vim is incredibly hard to learn; it has a virtual cliff-face learning curve. But, once you’ve mastered it, you are the most effective manipulator of text possible. Watching experienced VIM coders typing prolly make you impressed, people say that the cursor just follows their eyes !
Despite small footprint, VIM can open big ( > 100 MB ) files, replace many ( > 1000 ) words much faster than such as Notepad++ , jEdit, ... Not only able to invoke shell commands, VI/vim also supports hundreds of language syntax highlightings, macro recording, and scripting, mapping hotkeys as many as you want, and lot of more cool features !

9/ Another freeware (Notepad2, Smultron, ConTEXT, ... ) : Trong số này thì cũng có vài cái xài được, nhưng có vẻ chưa mature đủ để vượt qua danh tiếng những cái trên. Time will tell, though.

10/ proprietary ones (TextMate, e, SlickEdit, UltraEdit, ... ) :
thường phải trả phí từ 20-60$ . Nổi bật nhất có lẽ là TextMate , rất được hâm mộ trên máy Mac, không chỉ ở giao diện elegant, nhiều theme đẹp mắt mà còn đủ các tính năng đáng kể như đã nêu ở trên .
Có một bản port sang Windows là "e" , hay còn gọi là "E" , hoặc "eText editor" hoặc "eEditor" , cũng đang được đánh giá cao, vượt hơn những đối thủ cạnh tranh trước đó như UltraEdit, EditPlus, SlickEdit, TextPad, EmEditor ...

have fun,

Sunday, October 12, 2008

Ubuntu Linux clothes !

Canonical's Ubuntu (including kUbuntu, Xubuntu, Edubuntu, ... ) has surpassed RedHat's Fedora Core to be the most used Linux distribution since 2006: xp%2Cwindows vista%2Cubuntu

Based on that reputation, Canonical has lauched a series of T-shirt, hat, etc... with the Ubuntu logo:

Second Edition Hardy Heron Mens T-shirt
Second Edition Hardy Heron Mens T-shirt
£ 13.62
Ladies Hardy Heron T-shirt
Ladies Hardy Heron T-shirt
£ 13.62
Organic Circle of Friends Mens T-shirt (White)
Organic Circle of Friends Mens T-shirt (White)
£ 12.77
Organic Circle of Friends Mens T-shirt (Black)
Organic Circle of Friends Mens T-shirt (Black)
£ 12.77
Ubuntu Fleece Jacket
Ubuntu Fleece Jacket
£ 21.28
Organic Circle of Friends Ladies T-shirt
Organic Circle of Friends Ladies T-shirt
£ 12.77
Ubuntu Circle of Friends Hoody (black)
Ubuntu Circle of Friends Hoody (black)
£ 21.28
Ubuntu Beanie Hat - Black
Ubuntu Beanie Hat - Black
£ 6.81
I Do it with Ubuntu Mens T-shirt
I Do it with Ubuntu Mens T-shirt
£ 10.21
Baseball Cap
Baseball Cap
£ 4.26
Hoody (Chocolate Colour)
Hoody (Chocolate Colour)
£ 16.17
Sweatshirt (Fawn Colour)
Sweatshirt (Fawn Colour)
£ 14.47
Mens T-Shirt (White)
Mens T-Shirt (White)
£ 6.38
Mens T-Shirt (Black)
Mens T-Shirt (Black)
£ 8.51
Ladies T-Shirt (Black)
Ladies T-Shirt (Black)
£ 8.09
Polo Shirt (Fawn colour)
Polo Shirt (Fawn colour)

More to see here:

My favourite ones:

UBN00058 - Ubuntu Ogio Metro Backpack

Price : £ 51.06

UBN00052 - Ubuntu Ogio Messenger Bag

Price: £ 45.96

UBN00080 - Ubuntu Drinking Mug

Enjoy your favourite hot drink with this white earthenware mug. 92mm tall.

Price: £ 4.26


(Thanks KinqV for hosting images)

Tips for Unit Test

Today, I would like to recommend 12 tips for Unit Testing to every developer :) .
(A good case study for Unit Test is the Craftsman story, you can read the Vietnamese translation here: )

Unit Testing is one of the pillars of Agile Software Development. First introduced by Kent Beck, unit testing has found its way into the hearts and systems of many organizations. Unit tests help engineers reduce the number of bugs, hours spent on debugging, and contribute to healthier, more stable software.

In this post we look at a dozen unit testing tips that software engineers can apply, regardless of their programming language or environment.

1/ Unit Test to Manage Your Risk

2/ Write a Test Case Per Major Component

3/ Create Abstract Test Case and Test Utilities

4/ Write Smart Tests

5/ Set up Clean Environment for Each Test

6/ Use Mock Objects To Test Effectively

7/ Refactor Tests When You Refactor the Code

8/ Write Tests Before Fixing a Bug

9/ Use Unit Tests to Ensure Performance

10/ Create Tests for Concurrent Code

11/ Run Tests Continuously

12/ Have Fun Testing!

Probably the most important tip is to have fun. When I first encountered unit testing, I was sceptical and thought it was just extra work. But I gave it a chance, because smart people who I trusted told me that it's very useful.

Unit testing puts your brain into a state which is very different from coding state. It is challenging to think about what is a simple and correct set of tests for this given component.

Once you start writing tests, you'd wonder how you ever got by without them. To make tests even more fun, you can incorporate pair programming. Whether you get together with fellow engineers to write tests or write tests for each other's code, fun is guaranteed. At the end of the day, you will be comfortable knowing your system really works because your tests pass.

(Full credit of this article belongs to Alex Iskold and ReadWriteWeb)


Saturday, October 11, 2008

Java Tiger and Mustang

Chà, đã mấy ngày rồi mà bài quiz Java về Object của Weiqi Gao mà mình đưa lên vẫn chưa có comment nào, chẳng lẽ bài tầm thường quá nên các Java gurus không thèm reply chăng T_T

Không sao , giờ thì mình revisit lại những điểm mới trong Java 5.0 (Tiger) và 6.0 (Mustang) cái đã. Hy vọng những cái này sẽ giúp cho các bạn mới làm quen với Java bằng sách tiếng Việt (vì các sách này chỉ dịch lúc còn Java 1.4, 1.3) .

Đầu tiên là Tiger. Không chỉ quyết định đổi tên phiên bản từ 1.5 thành 5.0 (thực chất chỉ là một nỗ lực marketing, như hồi đổi tên Solaris 2.7 thành 7.0) , Sun còn áp dụng 1 loạt thay đổi đáng kể đến ngôn ngữ Java và các lớp :

* Đổi tên :
J2SDK -> JDK (không còn tưởng niệm JavaSE 1.2)
J2SE -> Java SE , J2EE -> Java EE , J2ME -> Java ME
1.5 -> 5.0 (và open source gần hết mã nguồn Java)

* Annotations : (còn gọi là Metadata)
Đây không phải là điều gây nhiều hứng thú trước khi nó ra đời, nhưng cuối cùng nó lại là điểm sáng nhất trong số các cải tiến ở Java 5.
Cho phép người phát triển tạo những ký hiệu đánh dấu (annotation) riêng, gần giống như các annotation của javadoc . Sun cũng cung cấp sẵn một số annotation: @Override, @Deprecated, @SuppressWarning, ...
Về mặt cú pháp, các annotation này có vai trò như 1 loại modifier (bổ từ: public, static, final, ... ) đặc biệt ; do đó nằm ở vị trí tương ứng như modifier.


public @interface RequestForEnhancement {
int id();
String synopsis();
String engineer() default "[unassigned]";
String date(); default "[unimplemented]";

public class Foo {
@Test public static void m1() { }
public static void m2() { }
public static void m3() {
throw new RuntimeException("Boom");
public static void m4() { }
public static void m5() { }
public static void m6() { }
@Test public static void m7() {
throw new RuntimeException("Crash");
public static void m8() { }

* Generics :
Đây là tính năng được mong đợi nhất, như Template trong C++, Generics trong C#, nhưng đáng tiếc nó đã được implement không tốt lắm, dẫn đến sai lầm cố hữu là sự phức tạp không cần thiết, điều mà cộng đồng Java đã phê phán Sun từ thời EJB.
Cú pháp cho phép kiểu của các phần tử mảng và collection được chỉ ra.
Mục đích phát hiện những lỗi sai về kiểu dữ liệu ngay tại thời điểm dịch (complilation time) thay vì lúc chạy chương trình (runtime).

Cú pháp : Collection<T>

Ví dụ :

List<String> list = new ArrayList<String>();

* Lặp For mới (ForEach)
Nâng cao việc sử dụng vòng for với mảng và collection

Cú pháp:
for (kiểu_dữ_liệu biến : mảng)

Ví dụ :

for (String myString : arrayOfStrings) { /* ... */ }

* Formatter và printf :
Định dạng printf hầu như giống C hoàn toàn (mở rộng hơn)


System.out.printf("%s %5d\n", user,total);

* enum
Rất giống enum trong C++ , có điều tên các phần tử không cần đặt thêm prefix (hay suffix) , bởi có thể gọi được như kiểu Static field.

Ví dụ :

enum Seasons { fall, winter, spring, summer } ;

* Hỗ trợ Unicode (UCS-2, UTF-16)
java.lang.String và java.lang.Character có phân biệt điểm mã (Code Point) cho các ký tự. UTF-16 theo chuẩn
(tương lai có thể Java hỗ trợ cả UTF-8, UTF-32)

* JFrame.getContentPane().add()
Gọi add component trực tiếp từ JFrame không cần qua contentPane.

* import static
Cho phép sử dụng hằng số và phương thức tĩnh mà không cần chỉ ra tên lớp.
Giúp thuận tiện trong lập trình

Ví dụ :

import static java.lang.Math.*;

* Variable arguments (varargs)
Số lượng tham số của method có thể thay đổi,
Sử dụng cú pháp ba chấm ' . . . '

Ví dụ :

void argtest(Object ... args) {}

* AutoBoxing-Unboxing
Có thể sử dụng kiểu dữ liệu nguyên thủy gán trực tiếp cho wrapper class

Ví dụ :

Integer I = 5;

Còn các điểm mới của Java 6 (Mustang) xin được tách ra thành một entry khác , bởi bài này đã khá dài :-)

Thursday, October 09, 2008

Java String test

Rumor spreads out that StringBuffer's operations is notably faster than String's.

Let's have some code String vs StringBuffer to see whether the rumor are true or not !

For quick text edit I always use VIM :
$ vim

Here comes the code:

import java.util.Date;

public class TestStringPerformance {
public static void main(String[] args) {
TestStringPerformance aString = new TestStringPerformance();



private void testStringAppend(int loopNum) {
Date startDate = new Date();
String prefixString = "A";
for (int i = 0; i< loopNum; i++) {
prefixString = prefixString + i;
Date endDate = new Date();
printTime("StringAppend", startDate, endDate);

private void testStringNew(int loopNum) {
Date startDate = new Date();
String newString;
for (int i = 0; i< loopNum; i++) {
newString = "B";
Date endDate = new Date();
printTime("StringNew", startDate, endDate);

private void testStringBufferAppend(int loopNum) {
Date startDate = new Date();
StringBuffer prefixString = new StringBuffer("A");
for (int i = 0; i< loopNum; i++) {
Date endDate = new Date();
printTime("StringBufferAppend", startDate, endDate);

private void testStringBufferNew(int loopNum) {
Date startDate = new Date();
StringBuffer prefixString = new StringBuffer("A");
for (int i = 0; i< loopNum; i++) {
Date endDate = new Date();
printTime("StringBufferNew", startDate, endDate);

private void testStringReplace5Chars(int loopNum) {
Date startDate = new Date();
String prefixString = "AAAAABBBBB";
for (int i = 0; i< loopNum; i++) {
prefixString = prefixString.replaceFirst("BBBBB", "BBBBB");
Date endDate = new Date();
printTime("StringReplace5Chars", startDate, endDate);

private void testStringBufferReplace5Chars(int loopNum) {
Date startDate = new Date();
StringBuffer prefixString = new StringBuffer("AAAAABBBBB");
for (int i = 0; i< loopNum; i++) {
Date endDate = new Date();
printTime("StringBufferReplace5Chars", startDate, endDate);

private void printTime(String methodName, Date startDate, Date endDate) {
long millis = endDate.getTime() - startDate.getTime();
System.out.println(methodName + " took " + millis + " milliseconds ");

Now let's compile and run to see the result:

$ javac

$ java TestStringPerformance
StringAppend took 4047 milliseconds
StringBufferAppend took 656 milliseconds
StringAppend took 3235 milliseconds
StringBufferAppend took 656 milliseconds
StringNew took 0 milliseconds
StringBufferNew took 16 milliseconds
StringNew took 0 milliseconds
StringBufferNew took 0 milliseconds
StringReplace5Chars took 203 milliseconds
StringBufferReplace5Chars took 0 milliseconds
StringReplace5Chars took 32 milliseconds
StringBufferReplace5Chars took 0 milliseconds

$ java -version
java version "1.6.0_06"
Java(TM) SE Runtime Environment (build 1.6.0_06-b02)
Java HotSpot(TM) Client VM (build 10.0-b22, mixed mode, sharing)

So what ?
The answer is, On my PC and with JRE 1.6 update 6, StringBuffer is much faster than String on "Append" and "Replace" operations, but was slower on first initilization.

I ran the test again:

$ java TestStringPerformance
StringAppend took 3265 milliseconds
StringBufferAppend took 641 milliseconds
StringAppend took 3266 milliseconds
StringBufferAppend took 640 milliseconds
StringNew took 0 milliseconds
StringBufferNew took 16 milliseconds
StringNew took 0 milliseconds
StringBufferNew took 0 milliseconds
StringReplace5Chars took 93 milliseconds
StringBufferReplace5Chars took 0 milliseconds
StringReplace5Chars took 47 milliseconds
StringBufferReplace5Chars took 0 milliseconds

Somehow the time of "Replace" operation is changed: The String ran faster than the first time, whereas the StringBuffer is slower.
However, the final conclusion is the same :D .

What is the result on your PC?

Linux directory structure

Nhìn "bề nổi" thì cấu trúc và cách tổ chức file của Linux cũng không khác DOS/Windows và các Hệ điều hành khác là mấy. Chỉ có vài điểm khác biệt mà bạn cần phải chú ý:

+ Cấu trúc thư mục của Linux KHÔNG cần khái niệm các ổ đĩa: Cho dù bạn có bao nhiêu phân vùng thì đường dẫn tuyệt đối của một thư mục cũng bắt đầu từ một thư mục gốc có tên là '/' (đọc là 'root') , chứ không phải là C: hay D: ^^ . Bởi các phân vùng luận lý hoặc các ổ đĩa vật lý đều có thể được sẽ được "map" (ánh xạ) vào một thư mục con riêng biệt bất kỳ .
(thực sự thì Windows cũng map tự động các phân vùng logic thành các tên C:\ , D:\ , ... )

+ Trong đường dẫn của Linux, các thư mục được phân cách nhau bằng ký hiệu slash (sổ trái) / , trong khi với DOS/Windows là ký hiệu sổ phải \ (backslash)

+ Tên của các tập tin hoặc thư mục trong Linux phân biệt chữ hoa và chữ thường, VD: 'abc', 'Abc', 'ABC' là khác nhau. (trong khi trong Windows thì không phân biệt)

LinuxDirectoryStructure-VsWin |

Từ thư mục root ta sẽ có các thư mục con, mỗi thư mục con lại có một số thư mục con nữa, cứ thế tạo thành 1 cấu trúc thư mục dạng cây (và đó cũng là lý do tại sao thư mục đầu tiên được gọi là gốc/rễ: 'root' ) . Tuy nhiên do tính cơ động cao, dễ mount/unmount và không tự phân thành các phân vùng con, cấu trúc thư mục của Linux có thể trở thành rất lớn (big tree) và khó nhớ . Vì thế người ta đã cố gắng tạo một cấu trúc thư mục đồng nhất, tổ chức sắp xếp phân cấp thành các nhóm theo chức năng.

LinuxDirectoryStructure-Root |

Cho đến nay hầu như cách tổ chức thư mục trên Linux/Unix đã được chuẩn hóa, mỗi dòng phân phối Linux đều giống nhau ở một số phần chung (kể cả các BSD và Unix khác cũng tương tự), có thể nói là thống nhất mặc dù số lượng dòng phân phối Linux lên đến hàng trăm !

Bây giờ ta sẽ lược sơ qua các thư mục chủ yếu mà hệ thống Linux nào cũng đặt làm mặc định (default) : / , /boot , /bin , /home , /usr , /opt, /etc , /dev, /var, /tmp , ...

LinuxDirectoryStructure-All |

* Thư mục /
Đây thường được gọi với tên 'root directory' - nghĩa là thư mục gốc. Đây là nơi sẽ chứa mọi thư mục con khác. Đây là thư mục bắt buộc phải có cho bất cứ một hệ thống linux nào.

* Thư mục /boot
Thường được dùng để chứa kernel, và các cấu hình để boot hệ thống. Chẳng hạn có thư mục con /boot/grub là nơi chứa GRUB giúp cho việc multi-boot giữa nhiều hệ điều hành, đây là 1 thư mục đáng chú ý khi bạn cài song song Linux với Windows.

* Thư mục /home
Là nơi chứa tất cả các dữ liệu cá nhân cho từng user trên hệ thống (ngoại trừ user root). VD: tạo /home/CuTi là thư mục riêng cho user CuTi, /home/CuTeo là thư mục riêng cho user CuTeo ^^ . Cũng có thể phân ra kiểu khác: như có phòng ban SV và phòng ban GV thì ta đặt /home/SV/CuTi , /home/SV/CuTeo và /home/GV/Ninja, /home/GV/Mediocre , ...

* Thư mục /media và /mnt
Hai thư mục này thường được dùng để đặt các mount point, tức là điểm để mount thủ công các thiết bị. Như đã bàn ở trên, một partition muốn dùng được phải được mount. Các mount point đó thường được đặt trong /mnt. Một số các chương trình ứng dụng mới không dùng /mnt mà dùng /media là nơi default để đặt các mount point. Do đó, rất nhiều distro cung cấp cả hai thư mục, và sử dụng link để tương thích cho thói quen của user và các application.
(VD: phân vùng cài Windows của bạn thường được mount ở 1 trong 2 thư mục trên, USB flash disk cắm vào cũng thường được mount ở đây)

* Thư mục /usr
Là nơi chứa rất nhiều các chương trình được cài đặt trên hệ thống. Ngoài ra, các thư mục con của /usr còn dùng để chứa các tập tin chạy (binary), các library, các tập tin include, các manual pages, vân vân... Chẳng hạn từ điển StarDict thường được cài vào thư mục /usr/share/stardict , các tài liệu manual thì nằm trong /usr/man hoặc /usr/doc
(đây cũng là lý do mà sau khi cài Win tôi cài toàn bộ ứng dụng vào D:\usr thay vì C:\Program Files)

* Thư mục /dev
/dev là nơi kernel đặt các thiết bị (device) file. Trong linux và các hệ điều hành Unix-like, mỗi device đều được gán cho một file và các file này sẽ được đặt trong /dev. Chẳng hạn các ổ đĩa cứng ATA sẽ được nhận là /dev/hda , /dev/hdb, /dev/hdc... , còn các ổ SCSI và flash (USB) thì nhận là /dev/sda , /dev/sdb , ...
Ngoài các file device dành cho các hardware trên hệ thống, ở /dev còn có thêm một số file rất tiện dụng như /dev/zero, /dev/null, /dev/random.

Lưu ý: /dev là một pseudo fileSystem. Nghĩa là directory /dev là một file system ảo. Kernel sẽ tự tạo và đặt các device file vào /dev nếu như kernel nhận ra device đó. Bất kỳ một device nào cũng cần có driver để tương tác với kernel. Driver cho linux thường đã được nằm sẵn trong kernel. Bạn nào có config và rebuild kernel sẽ nhận ra có rất nhiều driver được support.

* Thư mục /etc
Nơi chứa các file cấu hình hệ thống, lưu dạng text để user dễ chỉnh sửa. Các tập tin đáng chú ý gồm có:
/etc/inittab : là một file định rõ những process nào được khởi động cùng hệ thống.
Ví dụ: bạn có thể cấu hình X –Windows có thể khởi động cùng với hệ thống hay ko, hoặc điều gì xảy ra khi bạn nhấn tổ hợp phím (CTRL+ALT+BACKSPACE).
/etc/fstab : file chứa thông tin mount tự động các thiết bị ngoại vi: HDD, CDROM ...
/etc/password : lưu giữ thông tin về user và password tương ứng

* Thư mục /bin
Đây là thư mục chứa các chương trình nhị phân (binary) thực thi cơ bản nhất trong hệ thống. Các file thực thi (executable) này thường là các chương trình thiết yếu và đủ để hệ thống có thể khởi động và làm việc ở mức căn bản.
(ngoài ra còn /usr/bin chứa nhiều utilities cho người dùng hơn, và một số hệ thống tạo ra /sbin , /usr/sbin dành cho các super user )

* Thư mục /lib
/lib thường là nơi chứa các library cần thiết cho hệ thống hoạt động. Một số thư mục khác cũng dùng để đặt lib gồm có: /usr/lib, /usr/local/lib.
Một thư mục đáng quan tâm khác trong /lib là /lib/modules. /lib/modules chứa các modules của kernel đang dùng. Nếu trên máy tính có nhiều hơn 1 kernel, trong /lib/modules sẽ có các directory khác tương ứng cho từng version của kernel.

* Thư mục /opt
/opt thường được dùng làm nơi cài đặt thêm các chương trình mang tính 'optional', có nghĩa là không có mặt mặc định chung cho hệ thống (server != desktop) . Chẳng hạn các gói như XAMPP thường được cài vào đây.

* Thư mục /tmp
Dùng để chứa các file tạm (temporary). Các file này thường được tạo khi chạy chương trình và xóa sau khi chương trình đã hoàn tất và thoát. (Nhưng các file tạm cỡ lớn và hay thay đổi thì thường lưu trong /var hơn là trong /tmp , chẳng hạn các file tạm của server , database)
Một điểm lưu ý là các users đều phải có quyền write và read trên /tmp. Một user bình thường hoàn toàn cần có /tmp để chứa các file tạm khi user đó sử dụng hệ thống.

* Thư mục /var
/var thường được gọi là 'kho chứa log' cho cả hệ thống. Mặc định, rất nhiều chương trình sẽ có log ở một trong các thư mục nằm trong /var. Để tránh bị "phình to" quá khổ thì thường sẽ có 1 script viết chạy thường trực kiểm tra dung lượng var và khi lớn đến mức nào đó sẽ report, gởi mail để có biện pháp clean hoặc tăng mount thêm ổ cứng vật lý ^^

* Thư mục /proc
/proc cũng là một pseudo fileSystem. Các file hoặc thư mục trong /proc sẽ được kernel khởi tạo trong lúc hoạt động. Trong /proc sẽ có các file hoặc thư mục tương ứng cho các process đang chạy, và ngay cả kernel. Rất nhiều kernel parameters có thể được xem và thay đổi bằng cách edit trực tiếp các file tương ứng trong /proc mà không cần dùng sysctl .

* Thư mục /root
/root là home directory cho account có quyền cao nhất trong hệ thống Linux, mặc định account này tên là 'root' . Thư mục này cũng tương tự như các home directory khác trên hệ thống. Chỉ khác ở điểm thư mục này không nằm trong /home/username mà được đặt ngay trong /

* [Bonus]
Ngoài các thư mục chính kể trên, Linux có thể còn một số thư mục khác nằm ngay trong / . Và thường Linux còn cần có một phân vùng hoán chuyển (swap) để làm vùng nhớ tạm khi RAM không đủ. Trước đây swap thường chiếm khoảng 1.5 đến 2.5 lần dung lượng RAM, nhưng bây giờ hệ thống nào cũng dư RAM, nên máy cá nhân chỉ cần 200-500 MB cho swap là đủ rồi :-)
(Cái Virtual Memory của Windows cũng là bắt chước từ cái swap này)

(Tổng hợp từ "Lập trình Linux" tập 1, khoaimi, và Wiki)

Wednesday, October 08, 2008

Quick Java quiz

Tuần trước có vào đọc thấy bài Quiz ở blog Weiqi Gao, cũng hay hay, show cho bà con xem:

Q: Compile, or no compile?

public class Foo {
public static void main(String[] args) {
Integer Object = new Integer(1024);
Object Integer = Object;

Kết quả chạy thử thì Compile được, không có vấn đề gì.

Kết luận: Các tên lớp (Ojbect, Integer, ...) không phải là từ dành riêng (reserved word) trong Java, vì thế ta có thể đặt làm tên biến như bình thường, biên dịch không báo lỗi.

Còn bây giờ là 1 bài Quiz khác cho các bạn :-)

/* Given the following code what is the effect of a being 5: */

public class Test {
public void add(int a) {
loop: for (int i = 1; i < 3; i++) {
for (int j = 1; j < 3; j++) {
if (a == 5) {
break loop;
System.out.println(i * j);

Chọn lựa:

A. Generate a runtime error
B. Throw an out of bounds exception
C. Print the values: 1, 2, 2, 4
D. Produces no output

Your choice?

Vietnamese Typing

Vấn đề về gõ tiếng Việt, mã hóa Vietnamese Unicode, đối với tôi vẫn là đề tài khá thú vị. Nếu có điều kiện tôi sẽ viết nhiều hơn về đề tài này. Còn trong bài này chỉ xin giới thiệu sơ lược về các bộ gõ tiếng Việt .

Ở đây chỉ xét các ứng dụng trên máy vi tính phổ biến, còn trên các nền mobile hoặc chuyên biệt thì tạm thời chưa xét vì... chưa phát triển mấy :-) .

* Bộ gõ độc lập (standalone application) trên Linux và *BSD:
+ xvnkb của Đào Hải Lâm
+ x-unikey của Phạm Kim Long

* Bộ gõ độc lập (standalone application) trên MacOS:
+ VietPad của Nguyễn Quân (actually this is a text editor written in Java/.NET, so it can also be used in other platforms)
+ Vietnamese Keyboard Set của Gero Herrmann
+ MacVnKey của Ngô Đình Học

* Bộ gõ độc lập (standalone application) trên Windows: có khá nhiều lựa chọn
+ UniKey của Phạm Kim Long
+ WinVnKey của Nguyễn Tấn Cường, Nguyễn Thư, Ngô Đình Học et al
+ DotNetKey của Bùi Đức Tiến
+ Key4U của Nguyễn Anh Tuyên
+ VPSKeys của Ngô Đình Học et al

Ngoài top 5 kể trên còn có VietKey của Đặng Minh Tuấn, VietSpell của Lưu Hà Xuyên, mVietX của Phạm Sơn, VNCode của Nguyễn Thư, ...

* Bộ gõ JavaScript (web-based application) trên các trình duyệt: cũng khá phong phú
+ Mudim của Nguyễn Hoài Anh
+ A.V.I.M (tên cũ: H.I.M) của Đặng Trần Hiếu
+ mViet của Phạm Sơn
+ vietUni của Trần Anh Tuấn
+ vietTyping của Nguyễn Thắng

Ngoài top 5 kể trên còn có CH.I.M của Đào Hải Lâm, B.I.M của Sơn, VietJIE của Âu Địch Xương, VoviUnicode của Lý Phúc Hiếu, ... và vài bộ gõ tự viết dùng cho cá nhân
( các bộ gõ JS này hoàn toàn có thể làm thành 1 extension cho FireFox hoặc ThunderBird )

Bài đã khá dài nên phần về các kiểu gõ tiếng Việt (VNI, Telex, VIQR, TuBinhTran) sẽ được tách ra thành 1 entry khác .

Tuesday, October 07, 2008

Windows post-installation notes

For some reason I had to reinstall Windows, and I'd like to keep a minimal backup with good software. It would be interesting to find out what applications you consider essential when doing a complete re-format. So I meditated and tried to pick the best ones. Here were my 'TO DO' list:

1/ Resize the C: partition to 4 GB (to be exact, 4000.5 MB )
2/ Install Windows XP Pro :-)
3/ Install NIC driver, and setup Internet connection
4/ Install AVG (AntiVir and Avast are good, either)
5/ Start scanning, and install other drivers (not reboot yet)
6/ Setup domain/workgroup, map network drives/printers
7/ Prepare folders ('D:\usr' instead of %ProgramFiles%, 'D:\home\ninja' instead of %UserProfile%, ... )
8/ Customize the Taskbar, Start Menu, Power settings.

9/ Install Firefox 2 (FF3 sucks) and some plugins (DownThemAll, ...)
10/ Install 7-zip (alternative: IZarc)
11/ Install Unikey (tool for typing Vietnamese)
12/ Install Adobe flash player
13/ Install VLC (MPlayer is another option)
14/ Install K-lite codecs
15/ Install Foxit Reader
16/ Install StarDict
17/ Install XnView (is Picasa better? )
18/ Install Comical
19/ Install Notepad++
20/ Install FreeCommander
21/ Reboot and make a mini backup

22/ Install ImgBurn (or CDBurnerXP)
23/ Install Audacity
24/ Install CamStudio
25/ Install JRE
26/ Install (next time maybe Lotus Symphony or KingSoft)
27/ Install OpenProj
28/ Install Free Download Manager
29/ Install ThunderBird
30/ Install Skype
31/ Install Pidgin
32/ Install KVIrc
33/ Install uTorrent (Vuze is a good alternative one)
34/ Install eMule
35/ Customize Desktop, reboot and make a lite backup

36/ Install Cygwin
37/ Install VIM (Vi IMproved)
38/ Install JDK
39/ Install XAMPP
40/ Install Eclipse (perhaps EasyEclipse? )
41/ Install TortoiseSVN (not Git yet)
42/ Install WinSCP and Putty
43/ Install HeidiSQL
44/ Install DBDesigner
45/ Install ArgoUML
46/ Install Dev-Cpp
47/ Install FreeMind
48/ Install VMWare
49/ Install SQLite
50/ Install PosgreSQL
51/ Install Eclipse plugins (CheckStyle, Subversive, Aptana, PHPeclipse, ...) , Mozilla plugins (for FireFox, ThunderBird)
52/ Reboot and make teh backup !

Yeahhh, it's time for games installation !
And maybe more (GIMP, Python, Ruby, Rails, Symfony, Django, ... ) ^_^

What are your essentials after a Windows re-format?

Sunday, October 05, 2008

Software development principles

A good software, in the developer POV, should satisfy below criteria:

* FUNCTIONAL (as specified, with reasonable resource) : of course, trivial assumption.

* REUSABLE : currently the most notable criteria, which is the father of OOP and RAD.

* EXTENSIBLE : the brother of "reusable", in other words, it's the good side of "flexible" (the bad side is "modifiable/shrinkable" which requires more efforts).

* RELIABLE : even when the software is run in non-specified conditions, it should not lead to system crash/hanging/exploitation, and should produce the most accurate result, while giving the user some warning/caution.

Hence, the pragmatic software development, after LOTS of failed projects, has proven some paradigms to achieve the above criteria in a predictable way. That's why we have now programming philosophies, conventions, OOP, OOAD, principles, and also a bunch of design patterns.

And here are my notes about some useful development principles:

* KISS: Keep It Simple, Stupid (làm đơn giản thôi, lũ ngốc)
This is not only useful in software development, but also in a wide array of disciplines, such as animation, journalism, photography, engineering, and strategic planning. As Einstein's maxim: "everything should be made as simple as possible, but no simpler." .
Surprisingly, there are numerous so-called developers who forget this principle in serious development.

* DRW: Don't Reinvent Wheels (đừng có phát minh lại cái bánh xe)
This is also a general principle for gaining solutions in shorter time. It is emphasized in software development in which the human cost, which is highest part of software TCO, is proportional to development time and maintenance efforts. If there is a good solution we can get, just take it instead of creating a new solution from scratch, that's the economical way.

* DRY: Don't Repeat Yourself (đừng lặp lại cái đã làm rồi)
This principle is about re-use, not about re-invent. Yet it is similar in the economical sense. When re-use some components, we should avoid duplicated information as much as possible, because duplication increases the difficulty of change, may decrease clarity, and leads to opportunities for inconsistency.

* YAGNI: You Ain't Gonna Need It (còn lâu mới cần đến chức năng đó)
After some experience in programming, a developer usually impose himself on foreseeing unspecified usage and preparing for changing requests. Some even go further by adding functionality (without any request), which usually turns out to break the rate of process. Therefore a developer, though is encouraged to think out of the box, should only implement things when he actually need them, never when he just foresee that he need them.

Well, let's call it a day.
Design principles and design patterns will be mentioned in next entries .


Planning 5 months


* Objective: the title says it all

* Start date: 2008-10-05

* Due date: 2009-03-07 (duration: 5 months)

* Venue: working desk

* Agenda:

1/ Blog Mediocre-Ninja :

+ Mỗi tuần ít nhất 3 bài viết về kỹ thuật, công nghệ (computer-related) .

+ Các bài đó chủ yếu (hơn 50%) sẽ viết bằng tiếng Anh , trực tiếp soạn HTML .

+ Dùng một số thủ thuật để tăng page view và PageRank .

2/ Communication with hackers :

+ Tham gia IRC thường xuyên, học hỏi các cao thủ người Việt ở mỗi channel .

+ Tạo nick mới ở các diễn đàn, thêm nick những bạn cũ đã lâu không gặp .

3/ Project for fun :

+ Thứ nhất : ngốn 4500 trang sách tiếng Anh .

+ Thứ hai : làm 2 ứng dụng desktop , rồi port 1 cái sang mobile .

+ Thứ ba : làm 1 ứng dụng web, hoặc tham gia dự án collaboration .

4/ Miscellaneous :

+ tiếng Pháp, thời khóa biểu, chặn website .

+ xây dựng mô hình, quy trình công việc sử dụng triệt để OSS .

* Deadline: 2009-03-31

* Note: Các chi tiết Lưu lại dạng XML project để dễ mở bằng OpenProj, OpenWorkbench .

Saturday, October 04, 2008

Blogspot CSS customization

Some important meta-tags and CSS selectors in Blogspot template:

include data='blog' name='all-head-content'
. . .
#header-wrapper {
text-align: $startSide;
. . .
#main-wrapper {
margin-$startSide: 1%;
width: 64%;
. . .
#sidebar-wrapper {
margin-$endSide: 1%;
width: 29%;
. . .
.date-header {
font-size: 100%
. . .
.post {
margin: 0 0 1.5em;
. . .
.post-title {
font-size: 125%;
line-height: 1.1em;
. . .
.post-title a, .post-title a:visited, .post-title strong {
color: $textColor;
. . .
.post div {
margin: 0 0 .75em;
. . .
#comments-block dd p {

Well, good enough ? Looks like I have a neat Web 2.0 blog now !

Tạm thời nhiêu đó đã, còn một số cách để tăng views và PageRank sẽ trình bày sau ^o^ .

Test code display

Ok, let's see if the programming font, background and border are eye-candy or not .

class Program : Object {
static int _I = 1;

/// The quick brown fox jumps over the lazy dog

static void Main(string[] args) {
Uri Illegal1Uri = new Uri("http://packmyboxwith/jugs.html?q=five-dozen&t=liquor");
Regex OperatorRegex = new Regex(@"\S#$", RegexOptions.IgnorePatternWhitespace);

for (int O = 0; O < 123456789; O++) {
_I += (O % 3) * ((O / 1) ^ 2) - 5;
if (!OperatorRegex.IsMatch(Illegal1Uri.ToString())) {


DejaVu Sans Mono and Vera Sans Mono are able to kick Consolas !

Giờ test thử quote xem sao :
# DOS to Unix text convert (dos2unix much faster)
$ perl -i -pe 's/\r//g' file

# Legacy MacOS to Unix text convert
$ perl -i -pe 's/\r/\n/g' file

# Unix to DOS text convert (unix2dos much faster)
$ perl -i -pe 's/\n/\r\n/' file

Đoạn này test thử highlight coi có đẹp không .

Ổn rồi ^_^ .

Friday, October 03, 2008

Hello world !

Tập tành viết blog thôi ^o^
Hello seems to be the hardest word ! (@kavax-JGuru)

#include "iostream.h"
#include "string.h"

class string {
int size;
char *ptr;

string() : size(0), ptr(new char('\0')) {}

string(const string &s) : size(s.size) {
ptr = new char[size + 1];
strcpy(ptr, s.ptr);

~string() {
delete [] ptr;

friend ostream & operator <<(ostream &, const string &);

string & operator=(const char *);

ostream & operator<<(ostream &stream, const string &s) {
return(stream << s.ptr);

string & string::operator=(const char *chrs) {
if (this != &chrs) {
delete [] ptr;
size = strlen(chrs);
ptr = new char[size + 1];
strcpy(ptr, chrs);

int main() {
string str;
str = "Hello World";
cout << str << endl;