Từ 1 tới 4 trên tổng số 4 kết quả

Đề tài: Phong cách lập trình (programming style)

  1. #1
    Ngày gia nhập
    11 2007
    Nơi ở
    Biết để làm gì?
    Bài viết
    827

    Mặc định Phong cách lập trình (programming style)

    Phong cách lập trình (programming style)

    Mở đầu
    Hãy xem đoạn mã sau đây:
    C++ Code:
    1. if ( ( country == SING ) || ( country == BRNI ) ||
    2.      ( country == POL ) || ( country == ITALY ) ) {
    3.     /*
    4.      * If the country is Singapore, Brunei or Poland
    5.      * then the current time is the answer time
    6.      * rather than the off hook time
    7.      * Reset answer time and set day of week
    8.      */
    9.     ...
    10. }

    Đoạn mã trên được viết một cách rất đẹp đẽ, được comment cẩn thận và là một phần trong một chương trình chạy hoàn toàn đúng. Tuy nhiên đoạn mã này vẫn gây ra một chút băn khoăn cho người đọc: Những đất nước Singapore, Brunei, Poland và Italy có mối liên hệ gì với nhau? Tại sao Italy lại không được nói đến trong phần comment? Vì đoạn mã và phần comment có sự khác nhau nên một trong hai thứ phải sai mà cũng có thể là cả hai đều sai. Đoạn mã có nhiều khả năng đúng hơn vì nó đã được test; có thể phần comment đã không được cập nhật theo sự thay đổi của đoạn mã. Nếu là người bảo trì cho đoạn chương trình này, rất có thể bạn cần phải biết mối quan hệ giữa các quốc gia được nhắc đến.

    Đoạn chương trình nói trên đại diện cho phần lớn các chương trình trong thực tế: Hầu hết chạy đúng nhưng vẫn cần phải cải tiến.

    Mục đích của style là làm cho chương trình trở nên dễ đọc đối với người viết và những người khác, một style tốt là một phần thiết yếu của việc lập trình tốt. Viết một chương trình chạy đúng là chưa đủ bởi chương trình không chỉ để cho máy tính đọc mà còn để các lập trình viên khác đọc. Hơn nữa, một chương trình có style tốt luôn có nhiều khả năng chạy đúng hơn một chương trình có style tồi.

    Vậy thế nào là một style tốt? Điều đó tùy thuộc vào quy định của từng công ty, tổ chức, dự án…Phần sau đây giới thiệu những style cơ bản nhất.

    1.1 Cách đặt tên cho biến và hàm

    Tên của biến hay hàm “đánh dấu” cho biến/hàm đó và mang thông tin về mục đích của đối tượng mà nó mô tả. Tên phải mang thông tin, rõ ràng, dễ nhớ và tốt nhất là phải phát âm được. Tên biến phải phù hợp với phạm vi (scope) của biến đó, phạm vi của biến càng rộng thì tên biến càng phải mang nhiều thông tin.

    Quy tắc 1: Đặt tên giàu tính mô tả cho các biến toàn cục và tên ngắn gọn cho các biến cục bộ.

    Các biến toàn cục có thể được sử dụng trong toàn chương trình, bởi vậy cần đặt tên đủ dài và đủ ý nghĩa để nhắc nhở người đọc về ý nghĩa của chúng. Nên viết comment bên cạnh phần khai báo của biến toàn cục. Ví dụ:

    int npending = 0; /* độ dài hiện thời của hàng đợi */

    Các hàm, lớp hay cấu trúc toàn cục cũng cần có các tên giàu tính mô tả về vai trò của chúng trong chương trình.

    Trái lại, các biến cục bộ chỉ cần các tên ngắn gọn. Đối với một biến cục bộ, chỉ cần đặt tên n hoặc npoints là đủ. Một tên đại loại như numberOfPoints là quá thừa! Theo thônglệ, các tên i và j được dành cho các chỉ số, p và q dành cho các con trỏ, s và t dành cho các xâu. Vì vậy, hoàn toàn không cần thiết để dùng các tên biết dài loằng ngoằng như sau:
    C++ Code:
    1. for ( theElementIndex = 0;
    2.       theElementIndex < numberOfElement;
    3.       theElementIndex++ )
    4.     elementArray[ theElementIndex ] = theElementIndex;
    Vòng lặp này có thể viết lại như sau mà vẫn đảm bảo tính dễ hiểu:
    C Code:
    1. for( i = 0; i < nelems, i++ )
    2.     elem[ i ] = i;

    Các lập trình viên thường có xu hướng sử dụng các tên biến dài bất kể ngữ cảnh. Đó là một sai lầm bởi sự rõ ràng thường đạt được nhờ sự ngắn gọn. Thông thường người ta dùng các tên bắt đầu hoặc kết thúc bởi chữ “p” cho các biến con trỏ (chẳng hạn nodep), các tên bắt đầu bằng chữ hoa cho biến toàn cục (chẳng hạn Globals) và tất cả chữ cái hoa cho các hằng số (chẳng hạn CONSTANTS).

    Các namespace trong C++ và package trong Java góp phần làm rõ nghĩa của các tên mà không cần sử dụng các tên dài.

    Quy tắc 2: Đặt tên một cách nhất quán

    Các biến có liên quan phải được đặt các tên có liên quan, đồng thời phải làm nổi bật được sự khác nhau của chúng. Các tên trong lớp sau đây vừa quá dài vừa không hề nhất quán:

    C++ Code:
    1. class UserQueue {
    2.     int noOfItemsInQ, frontOfTheQueue, queueCapacity;
    3.     public int noOfUsersInQueue() {...}
    4. };
    Thứ nhất, cùng một nội dung là queue nhưng được biểu diễn bởi ba dấu hiệu: Q, Queue và queue. Thứ hai, các biến và các hàm thành phần của lớp UserQueue chỉ có thể được sử dụng bởi các đối tượng của lớp này, do vậy viết

    C++ Code:
    1. queue.queueCapacity

    hay

    C++ Code:
    1. queue.noOfUsersInQueue()

    rõ ràng là thừa. Chúng ta có thể viết lại lớp này với các tên mới như sau:

    C++ Code:
    1. class UserQueue {
    2.     int nitems, front, capacity;
    3.     public int nusers() {...}
    4. }

    Không chỉ bản thân đoạn mã định nghĩa lớp đó dễ hiểu hơn, mà những đoạn mã sử dụng lớp UserQueue cũng dễ hiểu hơn:
    C++ Code:
    1. queue.capacity++;
    2. n = queue.nusers();

    Lớp UserQueue vẫn có thể cải tiến thêm, bởi nitems và nusers thực chất là cùng biểu diễn một khái niệm và do đó chỉ cần sử dụng một trong hai tên đó mà thôi.

    Quy tắc 3: Đặt các tên “động” cho hàm

    Tên hàm nên là một động từ theo sau bởi một danh từ. Ví dụ:

    C++ Code:
    1. now = date.getTime();

    Các hàm trả về giá trị boolean nên được đặt tên thể hiện giá trị mà nó trả về. Ví dụ:

    C++ Code:
    1. isOctal( c )

    thì tốt hơn là

    C++ Code:
    1. checkOctal( c );

    vì cách đặt tên thứ nhất cho biết ngay rằng hàm trả về giá trị true nếu c là một số octal và trả về false trong trường hợp ngược lại.

    Quy tắc 4: Tên hàm phải phù hợp với chức năng

    Tên một hàm mô tả chức năng của hàm đó. Bởi vậy đặt tên hàm sai dễ dẫn đến việc hiểu sai chức năng của hàm. Ngược lại, một tên hàm đúng có thể giúp người đọc phát hiện ra các lỗi trong định nghĩa hàm. Dưới đây là một macro được đặt tên đúng nhưng định nghĩa lại sai:

    C Code:
    1. #define isoctal( c ) ( ( c ) >= ‘0’ && ( c ) <= ‘8’ )

    Trong trường hợp này, việc đặt tên đúng giúp chúng ta dễ dàng phát hiện ra lỗi sai. Định nghĩa đúng cho macro này phải là:

    C Code:
    1. #define isoctal( c ) ( ( c ) >= ‘0’ && ( c ) <= ‘7’ )

    Sau đây là một hàm với các tên hoàn toàn mâu thuẫn với chức năng của nó:

    C++ Code:
    1. public boolean inTable( Object obj )
    2. {
    3.     int j = this.getIndex( obj );    return ( j == nTable );
    4. }

    Hàm getIndex trả về một giá trị trong đoạn 0 đến nTable – 1 nếu obj có mặt trong bảng và trả về nTable trong trường hợp ngược lại. Bởi vậy, hàm inTable sẽ trả về true khi j == nTable, tức là khi obj không có mặt trong bảng. Rõ ràng điều này hoàn toàn mâu thuẫn với tên hàm. Những sai làm kiểu này sẽ gây nên rắc rối lớn khi chương trình được bảo trì, phát triển bởi các lập trình viên khác trong tương lai.
    1.2: Biểu thức và lệnh

    Cũng giống như việc đặt tên cho hàm và biến, chúng ta cần viết các biểu thức và câu lệnh càng dễ hiểu càng tốt. Nên nhớ rằng các chương trình do bạn viết ra không chỉ để cho bạn đọc mà còn dành cho nhiều người khác đọc nữa.

    Quy tắc 1: Viết các lệnh “thò ra thụt vào” (indent) để nêu bật cấu trúc của chương trình

    Xem vòng lặp sau đây:

    C++ Code:
    1. for(n++;n<100;field[n++]=’’);
    2. *i = ‘’;
    3. return( ‘\n’);

    Định dạng lại ta có đoạn mã tốt hơn sau đây

    C++ Code:
    1. for(n++, n < 100; field[n++] = ‘’ )
    2.     ;
    3. *i = ‘’;
    4. return( ‘\n’)
    ;

    Chúng ta còn thu được đoạn mã tốt hơn nữa khi sau khi đưa phép gán vào trong thân vòng lặp và tách lệnh tăng n ra:

    C++ Code:
    1. for( n++; n < 100; n++ )
    2.     field[ n ] = ‘’;
    3. *i = ‘’;
    4. return ‘n’;

    Quy tắc 2: Viết các biểu thức ở dạng “tự nhiên”

    Hãy viết các biểu thức ở dạng mà chúng ta nói về chúng. Ví dụ đoạn mã sau đây khá khó hiểu:

    C Code:
    1. if ( ! ( block_id < actblks ) || ! ( block_id >= unblocks ) )

    Biến đổi tương đương chúng ta có đoạn mã “tự nhiên” hơn sau đây:

    C Code:
    1. if( ( block_id >= actblks ) || ( blockId < unblocks ) )

    Quy tắc 3: Sử dụng cặp dấu ngoặc (,) để tránh nhập nhằng về thứ tự thực hiện của các toán tử

    Vì phép toán logic có độ ưu tiên cao hơn phép gán nên cần sử dụng dấu ngoặc cho hầu hết các biểu thức có mặt chúng đồng thời:
    C Code:
    1. while ( ( c == getchar() ) != EOF )
    ...

    Các toán tử thao tác bit & và | có mức ưu tiên thấp hơn các toán tử so sánh như == nên khi nhìn thấy biểu thức
    C Code:
    1. if ( x & MASK == BITS )

    thì thực tế thứ tự thực hiện là

    C Code:
    1. if ( x & ( MASK == BITS ) )

    Chắc hẳn đây không phải là chủ định của lập trình viên viết biểu thức này.

    Chúng ta nên sử dụng các dấu ngoặc kể cả khi không bắt buộc. Hãy so sánh hai cách viết sau đây xem cách nào tốt hơn:

    C Code:
    1. leap_year = y % 4 == 0 && y % 100 != 0 || y % 400 == 0


    C Code:
    1. leap_year = ( ( y%4 == 0 ) && ( y%100 != 0 ) ) || ( y%400 == 0 )

    Chú ý rằng các dấu cách xung quanh các toán tử % đã được bỏ đi nhằm thể hiển rõ hơn cấu trúc của biểu thức.

    Quy tắc 4: Tách các biểu thức phức tạp thành các biểu thức đơn giản hơn

    Biểu thức sau đây rất ngắn gọn nhưng lại chứa quá nhiều phép toán:

    C Code:
    1. *x += ( *xp = ( 2*k < ( n – m ) ? c[ k + 1 ] : d[ k — ] ) );

    Chúng ta nên viết lại như sau:
    C++ Code:
    1. if( 2*k < n – m )
    2.     *xp = c[ k + 1 ];
    3. else
    4.     *xp = d[ k– ];
    5. *x += *xp;
    Quy tắc 5: Viết các lệnh dễ hiểu, không viết các lệnh “khôn ngoan”

    Các lập trình viên thường thích viết các lệnh càng ngắn gọn càng tốt. Tuy nhiên điều này thường gây phiền toái cho người khác. Hãy xem biểu thức sau đây làm gì:

    C Code:
    1. subkey = subkey >> ( bitoff – ( ( bitoff >> 3 ) << 3 ) );

    Biểu thức trong cùng ( bitoff >> 3 ) dịch phải bitoff 3 bit. Kết quả thu được lại được dịch trái 3 bit. Bởi vậy 3 bit cuối cùng của bitoff được thay thế bởi các số 0. Kết quả này lại được trừ đi bởi giá trị ban đầu của bitoff, kết quả của phép trừ chính là 3 bit cuối cùng trong giá trị ban đầu của bitoff. Ba bit này được dùng để dịch subkey sang phải.

    Bởi vậy, biểu thức nói trên tương đương với biểu thức sau đây:

    C Code:
    1. subkeu = subkey >> ( bitoff & 0×7 );

    Rõ ràng cách viết thứ hai dễ hiểu hơn nhiều. Một ví dụ khác về cách viết biểu thức ngắn gọn nhưng làm phức tạp hóa vấn đề:
    C Code:
    1. child = ( ! LC && ! RC ) ? 0 : ( ! LC ? RC : LC );

    Cách viết dưới đây dài hơn, nhưng dễ hiểu hơn nhiều:
    C++ Code:
    1. if( LC == 0 && RC == 0 )
    2.     child = 0;
    3. else if( LC == 0 )
    4.     child = RC;
    5. else
    6.     child = LC;

    Toán tử ?: chỉ thích hợp cho những biểu thức ngắn kiểu như sau đây:

    C Code:
    1. max = ( a > b ) ? a : b;

    hoặc

    C Code:
    1. printf( “The list has %d item%s\n”, n, n == 1 ? “” : “s” );

    Hãy nhớ rằng mục tiêu của chúng ta là viết những đoạn mã dễ hiểu, chứ không phải các đoạn mã ngắn gọn.

    Quy tắc 6: Cẩn thận với hiệu ứng lề (side effect)

    Toán tử ++ gây ra hiệu ứng lề: Bên cạnh việc trả về giá trị của biến, nó còn tăng giá trị của biến thêm 1 đơn vị. Điều này có thể rất tiện lợi trong nhiều trường hợp, song cũng có thể gây ra rất nhiều phiền toái. Vấn đề nằm ở chỗ việc lấy ra giá trị và việc tăng giá trị của biến có thể không xảy ra cùng lúc. Trong C và C++, thứ tự thực hiện của các hiệu ứng lề là không được định nghĩa. Vì vậy câu lệnh sau đây có thể cho kết quả sai:

    C Code:
    1. str[ i++ ] = str[ i++ ] = ‘ ‘;

    Chủ định của người viết là thêm hai dấu cách vào hai vị trí tiếp theo của xâu str. Tuy nhiên, tùy thuộc vào thời điểm chỉ số i được cập nhật mà sau khi thực hiện lệnh có một hoặc hai dấu cách được thêm vào xâu str cũng như i được tăng lên một hay hai đơn vị. Tốt nhất nên tách lệnh trên thành hai lệnh:

    C Code:
    1. str[ i++ ] = ‘ ‘;
    2. str[ i++ ] = ‘ ‘;
    Tương tự, lệnh sau đây có thể cho nhiều kết quả khác nhau:

    C Code:
    1. array[ i++ ] = i;

    Nếu giá trị ban đầu của i là 3, phần tử array[ 4 ] có thể nhận giá trị 3 hoặc 4.

    Các thao tác vào/ra dữ liệu cũng thường gây ra hiệu ứng lề. Lệnh sau đây cố gắng đọc hai giá trị số có liên quan từ thiết bị nhập chuẩn:
    C Code:
    1. scanf(%d %d”, &yr, &profit[ yr ] );

    Chủ định của người viết là sử dụng giá trị mới của yr trong profit[ yr ]. Tuy nhiên, câu lệnh này sai ở chỗ: Một phần của lệnh thay đổi giá trị của yr trong khi một phần khác lại sử dụng giá trị đó. Nhớ rằng tất cả các tham số của scanf đều được tính toán trước khi scanf thực sự được gọi. Bởi vậy giá trị của yr trong profit[ yr ] luôn là giá trị cũ. Để sửa lỗi này, như thường lệ, hãy viết lại lệnh trên thành hai lệnh dưới đây:
    C Code:
    1. scanf(%d”, &yr );
    2. scanf(%d”, &profit[ yr ] );

    nguồn từ internet,sorry vì không nhớ chính xác tác giả
    Cánh Chym ứ mỏi

  2. #2
    Ngày gia nhập
    11 2007
    Nơi ở
    Biết để làm gì?
    Bài viết
    827

    Mặc định Các idiom trong lập trình

    Các idiom

    Không biết dịch từ “idiom” thế nào cho chính xác. Tạm hiểu idiom là các chuẩn không bắt buộc nhưng được đa số người dùng tuân theo. Sử dụng các idiom giúp giảm bớt khả năng mắc lỗi đồng thời làm chương trình dễ đọc hơn và nhất là có vẻ “chuyên nghiệp” hơn Sau đây là một số idiom phổ biến:
    Các idiom cho mảng

    Để duyệt qua n phần tử của một mảng và khởi tạo chúng, có các cách viết sau đây:
    PHP Code:
    0;
    while ( 
    <= n – 1 )
        array[ 
    i++ ] = 1.0
    hoặc
    PHP Code:
    for( 0n; )
        array[ 
    i++ ] =  1.0
    hoặc
    PHP Code:
    for( n–i >= 0; )
        array[ 
    ] = 1.0
    Tất cả những cách viết trên đều đúng, tuy nhiên idioms cho trường hợp này là:
    PHP Code:
    for( 0ni++ )
        array[ 
    ] = 1.0
    Idiom của vòng lặp duyệt qua các phần tử của một danh sách (list) là
    PHP Code:
    for( = list; != NULLp->next )
        ... 
    Đối với các vòng lặp vô hạn, idiom là
    PHP Code:
    for ( ; ; )
    ... 
    hoặc
    PHP Code:
    while( )
        ... 
    Các idiom cho xâu và kí tự

    Xem đoạn mã sau đây:

    C++ Code:
    1. char *p, buf[ 256 ];
    2.  
    3. gets( buf );
    4. p = malloc( strlen( buf ) );
    5. strcpy( p, buf );
    Đoạn mã trên sai ở chỗ: Hàm strlen không tính đến kí tự null ở cuối xâu, trong khi hàm strcpy vẫn sao chép kí tự null ở cuối xâu nguồn sang xâu đích. Kết quả là strcpy ghi kí tự null ra ngoài vùng nhớ được cấp phát cho p. Idiom cho trường hợp này là:
    PHP Code:
    mallocstrlenbuf ) + );
    strcpypbuf 
    ;
    hoặc trong C++
    PHP Code:
    = new charstrlenbuf ) + ];
    strcpypbuf ); 
    Nếu trong một đoạn mã cấp phát bộ nhớ cho xâu mà bạn không nhìn thấy số 1, hãy kiểm tra lại! Java không gặp vấn đề này bởi xâu trong Java không được biểu diễn như các mảng kí tự kết thúc bởi null, hơn nữa các chỉ số của mảng cũng được kiểm tra.
    Hầu hết các môi trường phát triển C và C++ đều cung cấp một hàm có tên là strdup. Hàm này sử dụng malloc và strcpy để tạo ra một bản sao của xâu, nhờ đó tránh được lỗi nói trên. Thật không may, strdup lại không phải là một hàm chuẩn của ANSI C.
    Khi làm việc với các kí tự, hãy sử dụng các hằng kí tự thay vì các số nguyên. Ví dụ để kiểm tra xem c có phải một chữ cái hoa hay không, có thể dùng đoạn mã sau
    i
    PHP Code:
    f>= 65 && <= 90 )
        ... 
    Tuy nhiên đoạn mã này hoàn toàn phụ thuộc vào bộ mã biểu diễn kí tự đang được sử dụng. Cách tốt hơn là viết như sau:
    PHP Code:
    if( >= ‘A’ && <= ‘Z’ )
        ... 
    Tuy nhiên cách viết này cũng chưa chắc đã đúng nếu trong bảng mã kí tự đang được sử dụng, các chữ cái hoa không nằm cạnh nhau. Đối với những tình huống kiểu này, tốt nhất là sử dụng các hàm chuẩn
    PHP Code:
    if ( isupper) ) 
    trong C và C++, hoặc
    PHP Code:
    if ( Character.isUpperCase) ) 
    trong Java.
    Idiom cho lệnh if
    Tiếp theo là một idiom dành cho câu lệnh if. Hãy xem đoạn mã loằng ngoằng sau đây làm gì
    C++ Code:
    1. if ( argc==3 )
    2.     if ( ( fin = fopen(argv[l] , “r” ) ) != NULL )
    3.         if ( ( fout = fopen( argv[2], “w” ) ) != NULL ) {
    4.  
    5.             while ( ( c = getc( fin ) ) != EOF )
    6.                 putc( c, fout );
    7.             fclose( fin );
    8.             fclose( fout );
    9.  
    10.         } else
    11.             printf ( “Can’t open output file %s\n”, argv[2] ) ;
    12.     else
    13.         printf( “Can’t open input file %s\n”, argv[l] ) ;
    14. else
    15.     printf ( “Usage: cp input file outputfile\n” ) ;
    Viết lại đoạn mã này theo đúng idiom như sau:
    C++ Code:
    1. if ( argc != 3 )
    2.     printf ( “Usage: cp input file outputfile\n” ) ;
    3. else if ( ( fin = fopen( argv[l] , “r” ) ) == NULL )
    4.     printf( “Can’t open input file %s\n”, argv[l] );
    5. else if ( ( fout = fopen( argv[2], “w” ) ) == NULL ) {
    6.     printf ( “Can’t open output file %s\n”, argv[2] ) ;
    7.     fclose( fin ) ;
    8. } else {
    9.     while ( ( c = getc( fin ) ) != EOF)
    10.         putc( c, fout );
    11.     fclose( fin ) ;
    12.     fclose( fout ) ;
    13. }
    Nguyên tắc khi viết các lệnh if là: Đặt các phép toán kiểm tra điều kiện càng gần các hành động tương ứng càng tốt.
    Số 0 trong chương trình

    Số không thường xuyên xuất hiện trong các chương trình với nhiều ý nghĩa khác nhau. Trình dịch sẽ tự động chuyển số 0 thành kiểu thích hợp. Tuy nhiên nên viết ra một cách tường minh bản chất của số 0 mà chúng ta đang nói đến. Cụ thể, hãy sử dụng ( void* )0 hoặc NULL để biểu diễn con trỏ null trong C, sử dụng ‘\ 0′ cho kí tự null ở cuối mỗi xâu và sử dụng 0.0 cho các số float hoặc double có giá trị không. Đừng viết đoạn mã như sau
    PHP Code:
    0;
    name] = 0;
    0
    Hãy viết
    PHP Code:
    NULL;
    name] = '\ 0';
    0.0
    Số 0 nên để dành cho các số nguyên có giá trị bằng không. Tuy nhiên trong C++, 0 (thay vì NULL) lại được sử dụng rộng rãi cho các con trỏ null. Java định nghĩa hẳn từ khóa null cho các cho các object reference không tham chiếu đến cái gì cả.
    Đã được chỉnh sửa lần cuối bởi dieucay555 : 24-10-2008 lúc 04:42 PM.
    Cánh Chym ứ mỏi

  3. #3
    Ngày gia nhập
    06 2008
    Bài viết
    25

    Nguồn đây nè, google cái ra thôi
    Ref Link Code:

  4. #4
    Ngày gia nhập
    09 2008
    Nơi ở
    Kĩ viện
    Bài viết
    169

    Góp ý phát: Pointer không cho p vào cũng không sao, cả mấy kiểu "iXX(int)" "fXXX(float)" nữa, Mấy IDE lớn nó có interllisense nhắc phát là biết ngay.

    Nên có comment thể hiện tác dụng của biến hoặc method. Với công ngệ nhắc lệnh tiên xờ tiến của microsoft, ta không cần phải mò mẫm tới tận cái chỗ định ngĩa method đó hay "điện hỏi tác giả" . VD.

    Ảnh đính kèm bên dưới(picasa bị dồ rồi).
    Attached Thumbnails Attached Thumbnails comment.JPG  
    Phá toái hư không - Bạch nhật thăng thiên.

Các đề tài tương tự

  1. Cần ebook: Joe Celko's SQL Programming Style
    Gửi bởi IT_girl trong diễn đàn Công cụ, ebooks C#, ASP.NET, và Windows Mobile
    Trả lời: 0
    Bài viết cuối: 02-11-2013, 12:15 PM
  2. Giày Kaitokid - Style phong cách cho các bạn nam
    Gửi bởi yamekd92 trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 0
    Bài viết cuối: 26-01-2013, 06:14 PM
  3. Giày cao gót phong cách Hàn Quốc style 2013
    Gửi bởi cnatngoan trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 0
    Bài viết cuối: 20-01-2013, 08:54 PM
  4. Xăng đan phong cách HÀN QUỐC NĂM Style 2013 - EV27
    Gửi bởi cnatngoan trong diễn đàn Giới thiệu website, sản phẩm của bạn
    Trả lời: 0
    Bài viết cuối: 14-01-2013, 04:26 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn