CHƯƠNG 1. TỔNG QUAN KỸ THUẬT LẬP TRÌNH 1.1 Tổng quan về kỹ thuật lập trình 1.1 Phong cách lập trình Một chương trình nguồn được xem là tốt không chỉ được đánh giá thông qua thuật giải đúng và cấu trúc dữ liệu thích hợp, mà còn phụ thuộc vào phong cách và kỹ thuật mã hoá (coding) của người viết chương trình. Nếu một người lập trình viết một chương trình dù thực hiện đúng yêu cầu đặt ra nhưng mã nguồn quá lộn xộn và phong cách lập trình cẩu thả, thì mã nguồn này sẽ gây khó khăn không chỉ cho những người khác muốn đọc hiểu nó, mà còn cho chính người lập trình khi muốn chỉnh sửa hoặc cải tiến. Đôi khi người mới lập trình không quan tâm đến vấn đề này do ban đầu chỉ làm việc với chương trình nhỏ.
Tuy nhiên, vấn đề phát sinh khi họ phải làm việc với dự án lớn và chương trình lúc này không còn đơn giản vài chục dòng lệnh nữa. Nếu không rèn luyện một phong cách và trang bị một số kỹ thuật lập trình tốt thì người lập trình đối mặt với nhiều khó khăn… Trong chương đầu tiên xin giới thiệu một số kỹ thuật và phong cách lập trình cơ bản, ít nhiều giúp cho người học viết chương trình được tốt hơn.2 Một số kỹ thuật và phong cách lập trình căn bản. Cách đặt tên biến Thông thường tùy theo ngôn ngữ và môi trường lập trình, người viết chương trình thường chọn cho mình một phong cách nhất quán trong việc đặt tên các định danh. Một số quy tắc cần quan tâm khi đặt tên như sau: – Tên của định danh phải thể hiện được ý nghĩa: thông thường các biến nguyên như i, j, k dùng làm biến chạy trong vòng lặp; x, y dùng làm biến lưu tọa độ, hoặc dùng làm biến đại diện cho các số bất kỳ… Còn những biến lưu trữ dữ liệu khác thì nên đặt gợi nhớ, nhưng tránh dài dòng: biến đếm số lần dùng "count, dem, so_luong…", biến lưu trọng lượng “weight, trong_luong”, chiều cao “height” ; … Nếu đặt quá ngắn gọn như c cho biến đếm, hay w cho khối lượng thì sau này khi nhìn vào chương trình sẽ rất khó hiểu ý nghĩa của chúng.
Ngược lại đặt tên quá dài như "the_first_number, the_second_number,…" để chỉ các số bất kỳ, sẽ làm dư thừa, rườm rà trong chương trình. – Tên phải xác định được kiểu dữ liệu lưu trữ: phong cách lập trình tốt là khi người đọc nhìn vào một biến nào đó thì xác định ngay được kiểu dữ liệu và tên đối tượng mà biến đó lưu trữ. Cho nên tên biến thường là danh từ (tên đối tượng) kèm theo tiền tố mang ý nghĩa kiểu dữ liệu. Giả sử có biến đếm số lần thì ta có thể đặt iNumber, trong đó i là kiểu của dữ liệu, strContent là kiểu chuỗi, CPoint là lớp Point…Có nhiều cú pháp quy ước đặt tên biến, người lập trình có thể chọn cho mình một quy ước thích hợp.
Có thể tham khảo một số quy ước trong phần bên dưới. – Theo một quy ước cụ thể: + Cú pháp Hungary: hình thức chung của cú pháp này là thêm tiền tố chứa kiểu dữ liệu vào tên biến.1 bên dưới là một số tiền tố quy ước được nhiều lập trình viên sử dụng. Các công ty phần mềm thường có các quy ước về cách đặt tên biến cho 5 đội ngũ lập trình viên. Tuy nhiên đa số các quy ước này đều dựa trên cú pháp Hungary.
Tiền tố Kiểu dữ liệu Ví dụ minh họa b bool bool bEmpty, bChecked ; c char char cInChar, cOutChar ; str/s String string strFirstName, strIn, strOut ; i/n integer int iCount, nNumElement ; li long integer long liPerson, liStars ; f float float fPercent ; d double double dMiles, dFraction ; if Input file stream ifstream ifInFile ; of Output file stream ofstream ofOutFile ; S Struct struct sPoint{…} ; C Class class CStudent,CPerson + Đối với những hằng thì tất cả các ký tự đều viết HOA.1: #define MAXSIZE 100 const float PI = 3.14 ; + Cách đặt tên cho hàm : hàm bắt đầu với ký tự đầu tiên là ký tự viết thường và các ký tự đầu từ phía sau viết hoa, hoặc các từ cách nhau bằng dấu _ (underscore) và không có tiền tố. Tuy nhiên điều này cũng không bắt buộc tùy theo ngôn ngữ lập trình. Ngoài ra hàm có chức năng thực hiện một nhiệm vụ nào đó, cho nên tên chúng là động từ hoặc cụm động từ, thường bắt đầu bằng các động từ chính: get, set, do, is, make… Ví dụ 1. Phong cách viết mã nguồn – Sử dụng tab để canh lề chương trình : khi soạn thảo mã nguồn nên dùng tab với kích thước là 4 hay 8 khoảng cách để canh lề.
Thói quen này giúp cho chương trình được rõ ràng và dễ đọc, dễ quản lý. 6 Không nên Nên void docFile (SV a[], int &n) void docFile (SV a[], int &n) { { ifstream in; ifstream in; char* filename="filein.txt"; char* filename = in.txt"; in>>n; in.diem; } } } – Sử dụng khoảng trắng : chương trình sẽ dễ nhìn hơn Không nên Nên int iCount =0 ; int iCount = 0 ; for(int i=0;i<n;i++) for (int i = 0 ; i < n ; i++) { { iCount++; iCount ++; } } cout<<"Ket qua la:"<<iCount; cout << "Ket qua la:" << iCount; – Tránh viết nhiều lệnh trên một dòng. Không nên Nên if(a>5){b=a; a++} if ( a > 5) { b = a; a ++; } – Định nghĩa các hằng số. 7 Một số lập trình có thói quen không định nghĩa những hằng số thường xuyên sử dụng.
Dẫn đến những con số khó hiểu xuất hiện trong chương trình, một số tài liệu lập trình gọi những con số này là “magic mumber”. Không nên Nên. #define MAX_LENGTH 100 for (int = 0; i < 100; i #define MAX_NUM 100 ++). Trong đoạn chương trình bên trái rất khó phân biệt giá trị 100 ở ba vị trí có mối quan hệ gì với nhau.
Tuy nhiên, trong đoạn bên phải ta dễ dàng thấy được ý nghĩa của từng giá trị khi thay bằng định danh. Ngoài ra khi cần thay đổi giá trị của MAX_LENGTH, MAX_NUM thì chỉ cần thay một lần trong phần định nghĩa. Do đó đoạn chương trình bên phải dễ hiểu hơn và dễ thay đổi chỉnh sửa. – Viết chú thích cho chương trình Trước và trong khi lập trình cần phải ghi chú thích cho các đoạn mã trong chương trình.
Việc chú thích giúp chúng ta hiểu một cách rõ ràng và tương minh hơn, giúp ta dễ đang hiểu khi quay lại chính sửa hoặc cải tiến chương trình. Đặc biệt giúp ta có thể chia sẻ và cùng phát triển chương trình theo nhóm làm việc. Cụ thể, đối với mỗi hàm và đặc biệt là các hàm quan trọng, phức tạp, chúng ta cần xác định và ghi chú thích về những vấn đề cơ bản sau : + Mục đích của hàm là gì ? + Biến đầu vào của hàm (tham số) là gì ? + Các điều kện ràng buộc của các biến đầu vào (nếu có) ? + Kết quả trả về của hàm là gì ? + Các ràng buộc của kết quả trả về (nếu có). + Ý tưởng giải thuật các thao tác trong hàm.3 : Chú thích hợp lý, từng phần làm cho hàm rõ nghĩa, dễ hiểu.
//Hàm tạo danh sách liên kết đôi chứa Phân Số bằng cách đọc dữ liệu từ file txt 8 void createDList (DList & l) { int n; ifstream in; //biến dùng đọc file //tên file chứa dữ liệu đọc vào char* filename = "infile.open (filename); if (in) { in >> n; for (int i = 1; i<= n; i++) { PS x; in >> x.ms = rand() % 100 + 1; //Tạo node p chứa x và nối p vào sau danh sách l. DNode* p = createDNode (x); if (l.pTail = p; else { p -> pPre = l.close(); } Tuy nhiên không phải bất cứ lệnh nào cũng chú thích, việc chú thích tràn lan ngay cả với câu lệnh đơn giản cũng không có ý nghĩa gì. Đôi khi còn làm cho chương trình khó nhìn hơn.4 : Không nên chú thích câu lệnh đơn giản này //Nếu nhiệt độ vượt quá mức qui định thì phải cảnh báo if (nhietDo > nhietDoCB) cout<<" Nhiet do vuot muc qui dinh" ; //i là biến chạy trong vòng lặp for để xác định các chỉ số phần tử mảng a. for (int i = 0 ; i<n ; i++) cout<< a[i] ; – Nên viết biểu thức điều kiện mang tính tự nhiên : biểu thức nên viết dưới dạng khẳng định, việc viết biểu thức dạng phủ định sẽ làm khó hiểu.
9 Không nên Nên if (!(i < a) || !(i >= b)) if ((i >= a) || (i < b)) – Viết các lệnh rõ ràng, tối ưu sự thực thi mã nguồn. Stt Không nên Nên 1 int i = 0; for(int i = 0; i < n; i++) while (i < n) { {. } i++; } 2 i = i + 3 ; i += 3 ; i +=1 ; i ++ ; 3 return (a + b * c) ; return a + b * c ; 4 if (a > b) return a > b ? f (a) : return f(a); g(b) ; else return g(b); 5 if (a > b) return a > b ; return true ; else return false ; 6 return p.next == NULL ? return p.relat return ives.rela data[x] = a > b ? f(a) : tives. data[x] = f(b); 10 8 int countNodes (Node int countNodes (Node *root) *root) { { if (root->left == return root == NULL ?