Baby Arthas
Dragon Quest
- 25/10/03
- 1,444
- 0
Từ đầu cần khẳng định ý định của snow khi viết bài này là mong muốn snow và các bạn sẽ cùng nhau tạo ra 1 loạt bài viết về các thuật toán cơ bản, về các kĩ năng lập trình cơ bản, về những CTDL cơ bản, về các kinh nghiệm lập trình của bản thân. Trong lập trình mà nói đây là những thứ rất quan trọng và mỗi người sẽ có những kinh nghiệm cũng như những “miếng” riêng rất hay. Vậy snow rất mong các bạn và snow sẽ cùng post lên nhưng hiểu biết và kinh nghiệm của mình để cùng nhau học hỏi và hi vọng đây sẽ là 1 bài tut tốt cho các bạn newbie cho cả snow và các bạn. Và snow tự nhận là mình ko giỏi và cần học hỏi nhiều, nên rất mong nhận được góp ý cũng như được học hỏi từ các bạn
Vì là bài viết dựa trên những gì snow được học, từng gặp, từng làm, từng đọc và bản thân snow là người không giỏi hệ thống lại vấn đề nên rất mong các mod nếu có thể thì chỉnh sửa lại cho có hệ thống hơn và cũng rất mong các mod sẽ post lên những kinh nghiệm của mình ...
Cũng chẳng biết phải bắt đầu như thế nào nên snow đành đem cái “khẩu hiệu” nổi tiếng của Niklaus Wirth ra làm lời đầu tiên cho mình :
Data Structures + Algorith = Programs (Cấu trúc dữ liệu + Giải thuật = Chương trình).
Thật ra mà nói khi snow chọn IT thì cũng chỉ là sự tình cờ(tại thấy là ngành “oách” nhất hiện tại... greenbiggrin.gif ), lúc đó đối với snow công việc lập trình là cái chi chi đó rất “ghê gớm” và cao siêu. Và với hiểu biết hạn hẹp của mình vào lúc đó snow tưởng tượng ra rất nhiều chuyện buồn cười về công việc lập trình cũng như về các lập trình viên. Chẳng hạn như muốn viết ra 1 chương trình thì người ta phải ngồi đó và viết vào máy từng mã nhị phân 0,1... y chang như mấy người điện tín viên gõ và nhận mã morse ( greenbiggrin.gif thật ra đây là công việc của trình biên dịch hoặc trình thông dịch chứ đâu phải của lập trình viên). Sau này có học rồi, tiếp xúc rồi mới thấy nó khác hẳn với suy nghĩ của mình. Nó không quá khó nhưng cũng không quá dễ, vấn đề là nó đòi hỏi bạn phải nắm được kiểu tư duy của nó.
Về mặt nào đó học lập trình giống như việc bạn học thêm 1 thứ ngôn ngữ mới, 1 thứ tư duy mới (có 1 câu danh ngôn rất hay về việc học ngoại ngữ mà snow thấy nó cũng có phần nào đúng với việc học lập trình “Học thứ tiếng của 1 dân tộc là học các tư duy của dân tộc đó”). Cũng vậy, khi bạn học lập trình là thật ra giống như bạn đang học nói chuyện với máy, học cách ra lệnh cho nó làm những gì mà bạn muốn. Vì vậy, nếu lời nói của bạn “trong sáng, dễ hiểu” đối với máy thì nó sẽ chạy tốt, còn ngược lại thì...... greenbiggrin.gif
Có người từng nói với snow: “Muốn lập trình tốt thì đầu tiên phải học cách... ngu như máy trước, rùi mới lập trình tốt được!”. Ý người đó muốn nói là lập trình viên phải hiểu được những giới hạn cũng như những khả năng của máy tính thì mới có thể lập trình tốt được. Nếu bạn ko nắm rõ thì những gì bạn viết ra đôi khi là Mission Impossible với 1 cái máy tính và khi đó nó sẽ trở nên “ngu”.
1. Những yêu cầu với 1 chương trình máy tính
Đầu tiên ta cần biết lập trình là viết ra những chương trình nhằm giúp máy tính giải quyết những bài toán, những yêu cầu nào đó trong thực tế cho ta. Vì vậy có 1 số yêu cầu nhất định cho việc viết chương trình:
+Đúng đắn: chương trình phải đáp ứng được những yêu cầu được đặt ra.
+Chính xác
+Tin cậy: bảo đảm cùng 1 dữ liệu nhập vào thì kết quả trả ra luôn luôn giống nhau
+Tổng quát: người lập trình viên phải có khả năng nhìn thấy tất cả mọi khả năng có thể của dữ liệu nhập vào và chương trình phải làm việc tốt được với mọi dữ liệu nhập vào.
+An toàn: chương trình phải làm việc tốt ngay cả trong những điều kiện bất thường xảy ra, hạn chế việc chương trình bị “chết” trong quá trình chạy vì nhiều nguyên nhân như dữ liệu nhập vào không phù hợp, lỗi truy cập...vv... (hình như việc này ngay cả Microsoft cũng...ko làm được vì Widows cứ bị hư hoài à...).
+Hiệu quả: Chương trình phải tiết kiệm tài nguyên ở mức thấp nhất có thể, chạy nhanh nhất ở mức có thể...
+Dễ : nâng cấp, sửa chữa.
2.Thiết kế chương trình:
a. Các xu hướng thiết kế:
Hiện nay có 2 xu hướng chính được chọn lựa trong việc thiết kế chương trình máy tính đó là : hướng thủ tục và hướng đối tượng
a.1.Hướng thủ tục(MP):
Thông qua 1 quá trình phân tích nhất định, lập trình viên sẽ tách bài toán hay yêu cầu ban đầu thành những bài toán con, yêu cầu con đơn giản hơn và giải quyết từng thứ 1. Việc này sẽ giúp bạn thực hiện được các bài toán phức tạp 1 cách dễ dàng. Bởi vì viết tổng thể cả 1 bài toán phức tạp là 1 việc làm rất khó và gần như Mission Impossible, nhưng chia nhỏ nó ra thành từng phần nhỏ hơn để giải quyết rùi gắn từng phần riêng đó lại là lựa chọn dễ dàng và khôn ngoan hơn. Việc này còn giúp cho chương trình của bạn dễ đọc, dễ bảo quản và dễ sửa chữa hơn.
Vd: yêu cầu đặt ra là bạn phải viết 1 chương trình dọc dữ liệu từ 1 file chứa các thông tin về số nhân viên, thông tin của từng nhân viên của 1 công ty, xử lí và trả lại thông tin về lương sẽ trả tháng này của từng nhân viên.
Như vậy nếu bạn để y nguyên như vậy mà làm sẽ rất khó và khi có sai sót bạn sẽ rất khó dò lỗi trong 1 khối chương trình gộp chung như vậy. Vì vậy bạn sẽ tách quá chương trình ra 1 số quá trình đơn giản hơn như sau:
Xử lí việc đọc file
Xứ lí thông tin đọc được từ file
Xử lí việc thông báo kết quả.
Từ các quá trình này bạn có thể tách thêm các quá trình con nữa nếu cần.
Như vậy khi xảy ra lỗi trong lập trình thì việc tìm lỗi và sữ chữa sẽ dễ dàng hơn cho bạn. Chẳng hạn khi lỗi thuộc về việc đọc file thì bạn chỉ cần dò tìm nó trong đoạn thủ tục bạn viết dùng để đọc file.
a.2.Hướng đối tượng(OOP): đây là 1 hướng thiết kế mới và gần với thực tế hơn phương pháp hướng thủ tục nhưng đương nhiên đòi hỏi ở bạn nhiều việc để làm và suy nghĩ hơn. 1 cách cơ bản mà nói thì hướng đối tượng nhìn vấn đề với 1 “con mắt khác” so với hướng thủ tục.
a.3 Khác như thế nào???
Nếu như ở hướng thủ tục bạn nhìn chương trình như “1 đống những công việc nhỏ cần phải làm tuần tự”. Thì khác 1 chút ở hướng đối tượng bạn nhìn theo hướng “1 đống những dữ liệu cần được tách riêng và xử lí” (đây là cảm nhận và cách hiểu riêng của snow về 2 hướng lập trình này...).
Vậy tại sao nói hướng đối tượng gần với thực tế hơn hướng thủ tục???
Đơn giản là vì trong thực tế mọi thứ tồn tại vốn dưới dạng các đối tượng (dữ liệu) khác nhau và các đối tượng đó tương tác với nhau chứ ko phải là các thủ tục.
Vd: bạn có thể hình dung như thế này. Cũng với ví dụ tính lương ở trên.
+Bây giờ giả sử tất cả các nhân viên đó đều thuộc về 1 công ty và có những chức vụ khác nhau. Như vậy nếu nhìn theo hướng thủ tục bạn sẽ chỉ thấy việc phải xử lí riêng cho từng loại nhân viên thuộc từng chức vụ 1 và việc này hơi “rối mù“ 1 chút trong chương trình và dễ gây nhầm lẫn cũng như sẽ khó cho việc sửa chữa, nâng cấp về sau nếu như xuất hiện thêm những chức vụ mới.
+Nhưng nếu bạn nhìn theo hướng đối tượng bạn sẽ thấy rằng đầu tiên ở đây có chung 1 loại đối tượng lớn nhất là “nhân viên”. Tiếp theo từ “nhân viên” ta có thể tách ra những đối tượng con của nó là “công nhân”, “trưởng phong”, “thư kí”, “giám đốc”, mỗi 1 đối tượng con sẽ có chung các đặc điểm của đối tượng cha và có riêng các đặc tính riêng của nó. Như vậy khi có thêm chức vụ thì bạn chỉ đơn giản thêm vào 1 đối tượng con mới chứ ko cần sửa lại đoạn mã đã viết ban đầu.
Nhưng bạn phải hiểu đối tượng trong hướng đối tượng ko chỉ đơn giản là “dữ liệu” mà mỗi đối tượng ngoài dữ liệu còn mang trong nó những thủ tục, hành vi của riêng đối tượng đó và đối tượng tương tác với các đối tượng khác thông qua các hành vi này. Và các đối tượng giống nhau sẽ có cùng những hành vi giống nhau. Đây là tính đóng gói của hướng đối tượng.
Ngoài ra hướng đối tượng còn có tính thừa kế nghĩa là tất cả những kiểu đối tượng con dẫn xuất từ cùng 1 kiểu đối tượng cha sẽ được thừa kế những “đặc tính” di truyền của cha (về dữ liệu cũng như hành vi...).
Một tính chất quan trọng khác của hướng đối tượng là tính đa hình, nghĩa là cùng 1 hành vi nhưng đối tượng sẽ có cách “xử sự” khác nhau với từng loại đối tượng khác nhau tuỳ theo định nghĩa của bạn về hành vi của đối tượng đối với từng loại đối tượng khác nhau...
b.Các phương pháp thiết kế:
Ở đây cũng có 2 phương pháp thiết kế chính là từ trên xuống (Top-down) và từ dưới lên (Bottom-up)
b.1.Top-down:
Đây là phương pháp thiết kế mang tính đi sâu vào tổng quát trước. Ở từng tầng của phương pháp thiết kế này chức năng tổng quát nhất được đem ra làm tên gọi, sau đó bạn phát triển những tầng tiếp theo nhỏ hơn của chức năng đó. Và cứ tiếp tục phân tầng như vậy cho tới khi các chức năng đã được đơn giản ở mức có thể thực hiện dễ dàng và hiệu quả.
b.2.Bottom-up:
Ngược lại với kiểu thiết kế top-down là kiểu bottom-up. Kiểu này được sử dụng chủ yếu khi bạn cần xây dựng chương trình từ những thứ đã có sẵn. Như vậy bạn chỉ cần tìm các thành phần cần thiết từ những thứ đã có. Một ví dụ đơn giản là khi bạn sử dụng các hàm đã có sẵn và được hỗ trợ của ngôn ngữ lập trình để xây dựng 1 ứng dụng đơn giản nào đó.
3.Các cấu trúc điều khiển cơ bản:
Dù chương trình của bạn có được xây dựng phức tạp như thế nào, có ứng dụng những giải thuật cao siêu tới đâu thì thực chất 2 thành phần cơ bản nhất xây dựng ra chúng vẫn chỉ là dữ liệu và các cấu trúc điều khiển. ở đây snow nói về các cấu trúc điều khiển cơ bản:
+Cấu trúc điều khiển tuần tự:
các toán tử, hàm, câu lệnh, dữ liệu được xử lí theo nguyên tắc tuần tự: trái sang phải, trên xuống dưới. Bạn phải nắm rõ sự tuần tự này và cả các thay đổi của dữ liệu trong thứ tự làm việc của chương trình nếu muốn đảm bảo chương trình sẽ chạy đúng.
+Cấu trúc điều kiện:
Bao gồm những toán tử, hàm, câu lệnh, dữ liệu chỉ được thực hiện hoặc xử lí khi 1 điều kiện nào đó được thỏa mãn.
+Cấu trúc lặp:
Gồm những toán tử, hàm, câu lệnh, dữ liện sẽ được xử lí lặp lại 1 số hữu hạn lần nào đó. Bạn phải chú ý khi sử dụng cấu trúc lặp để tránh tạo ra những cấu trúc lặp vô hạn sẽ dẫn đến việc treo máy. Vì vậy yêu cầu đầu tiên khi sử dụng cấu trúc lặp là điều kiện dừng của vòng lặp phải đúng đắn. Bạn còn phải lưu ý tính nhớ và sự thay đổi của dữ liệu trong vòng lặp để đảm bảo cho chương trình chạy đúng.
+Ngoài 3 cấu trúc cơ bản trên còn 1 kiểu lập trình rất cần thiết cho 1 số bài toán, đó là kiểu đệ qui. Đôi khi đây là “điều không thể tránh khỏi” khi bạn “đụng” vào những bài toán có bạn chất là đệ qui.
1 thủ tục đệ qui sẽ gọi lại bản thân nó tại 1 nơi nào đó bên trong thủ tục đó nếu 1 điều kiện dừng nào đó ko được thoả. Cũng giống như cấu trúc lặp, khi sử dụng đệ qui bạn phải đảm bảo điều kiện dừng cho nó. Nhưng bạn cần lưu ý là đệ qui sẽ chiếm 1 số khá lớn tài nguyên bộ nhớ do mỗi 1 lần đệ qui, các mã lệnh sẽ được “quăng” vào stack của bộ nhớ và lưu lại đó cho tới khi được xử lí. Như vậy đệ qui càng nhiều lần thì bộ nhớ sẽ “nặng” và ảnh hưởng tới hiệu quả của các chương trình khác. Trong 1 số trường hợp bạn có thể khử đệ qui bằng cách sử dụng các vòng lặp, stack hoặc queue...
1 ví dụ đơn giản về đệ qui trên C:
Chẳng hạn để tính 1 giai thừa n!, bạn có thể sử dụng 1 hàm đệ qui như sau:
int Giai_thua(int n)
{
if(n==1)
return 1;
return n*Giai_thua(n-1);
}
Nhưng cũng có thể sử dụng vòng lặp để giải quyết:
int Giai_thua(int n)
{
int result=1;
for(int i=2; i<=n; i++)
result *= i
return result;
}
4. Tổng quát về trình biên dịch và thông dịch của ngôn ngữ lập trình:
Ở đây snow chỉ nói sơ sơ những gì snow hiểu về trình biên dịch và thông dịch để giúp các bạn khỏi thắc mắc xem “nó làm ăn ra sao???”. Và đây cũng được coi là những hiểu biết sơ đẳng nhất mà bạn cần biết khi lập trình:
Như snow đã từng đề cập ở trên, việc lập trình ngày nay ko phải là cái kiểu ngồi dịch từng mã nhị phân như “cái thuở ban đầu lưu luyến ấy” nữa. Ngày nay các lập trình viên tạo ra các chương trình bằng việc lập trình bằng 1 ngôn ngữ nào đó và đem biên dịch bằng trình biên dịch của ngôn ngữ đó trước khi chạy chương trình, hoặc vừa chạy vừa dịch(chạy tới đâu dịch tới đó) nếu là trình thông dịch.
2 chương trình trên thực chất có thể coi là trung gian giao tiếp giữa người lập trình viên và máy tính. Hiểu nó bạn sẽ hiểu “Ê, tại sao tui viết cái lệnh toàn tiếng Anh hông hà mà mấy cái máy nó hiểu hay vậy???”. Thiệt ra thì máy đâu có hiểu mấy cái “tiếng Anh nửa mùa” mà bạn viết. Nó chỉ hiểu mã nhị phân 0,1 của những gì bạn viết ra đã được trình biên dịch hoặc thông dịch dịch lại cho nó “nghe” thôi. Nhưng giữa 2 chương trình thông dịch và biên dịch có những khác biệt nhất định dù chúng có cùng nhiệm vụ là “dịch” lại cho máy “nghe” những gì bạn “nói” với nó.
4.1 Trình biên dịch:
Toàn bộ mã chương trình mà bạn viết sẽ được trình này dịch ra hợp ngữ (assembly) để chuyển thành chỉ thị máy. Trong quá trình này có thể bao gồm quá trình tiền xử lí, biên dịch từng đoạn nhỏ của chương trình, kiểm tra lỗi, kiểm tra kiểu của các biến..., lắp ráp lại thành chương trình cuối cùng để máy có thể thực thi.
4.2 Trình thông dịch:
Khác với trình biên dịch, trình thôn dịch không dịch cùng lúc toàn bộ mã chương trình mà nó dịch từng dòng mã lệnh thành những chỉ thị mà máy có thể thực thi ngay. Từng lệnh sẽ được dịch và được thi hành ngay trong khi dịch chứ ko phải dịch xong tất cả, ráp nối lại rồi mới chạy như trình biên dịch. Nhưng đây cũng có thể là điểm bất lợi của trình thông dịch vì cùng 1 câu lệnh như nhau bạn có thể phải dịch lại nhiều lần ở nhiều thời điểm khác nhau. Trong khi ở trình biên dịch bạn sẽ chỉ phải dịch 1lần, khi cần thì trỏ vào đoạn mã chương trình đã được dịch trước đó.
Bài của Hot Snow !!! ( Edited By B.A )
Thanks - Baby Arthas !!!
Vì là bài viết dựa trên những gì snow được học, từng gặp, từng làm, từng đọc và bản thân snow là người không giỏi hệ thống lại vấn đề nên rất mong các mod nếu có thể thì chỉnh sửa lại cho có hệ thống hơn và cũng rất mong các mod sẽ post lên những kinh nghiệm của mình ...
Cũng chẳng biết phải bắt đầu như thế nào nên snow đành đem cái “khẩu hiệu” nổi tiếng của Niklaus Wirth ra làm lời đầu tiên cho mình :
Data Structures + Algorith = Programs (Cấu trúc dữ liệu + Giải thuật = Chương trình).
Thật ra mà nói khi snow chọn IT thì cũng chỉ là sự tình cờ(tại thấy là ngành “oách” nhất hiện tại... greenbiggrin.gif ), lúc đó đối với snow công việc lập trình là cái chi chi đó rất “ghê gớm” và cao siêu. Và với hiểu biết hạn hẹp của mình vào lúc đó snow tưởng tượng ra rất nhiều chuyện buồn cười về công việc lập trình cũng như về các lập trình viên. Chẳng hạn như muốn viết ra 1 chương trình thì người ta phải ngồi đó và viết vào máy từng mã nhị phân 0,1... y chang như mấy người điện tín viên gõ và nhận mã morse ( greenbiggrin.gif thật ra đây là công việc của trình biên dịch hoặc trình thông dịch chứ đâu phải của lập trình viên). Sau này có học rồi, tiếp xúc rồi mới thấy nó khác hẳn với suy nghĩ của mình. Nó không quá khó nhưng cũng không quá dễ, vấn đề là nó đòi hỏi bạn phải nắm được kiểu tư duy của nó.
Về mặt nào đó học lập trình giống như việc bạn học thêm 1 thứ ngôn ngữ mới, 1 thứ tư duy mới (có 1 câu danh ngôn rất hay về việc học ngoại ngữ mà snow thấy nó cũng có phần nào đúng với việc học lập trình “Học thứ tiếng của 1 dân tộc là học các tư duy của dân tộc đó”). Cũng vậy, khi bạn học lập trình là thật ra giống như bạn đang học nói chuyện với máy, học cách ra lệnh cho nó làm những gì mà bạn muốn. Vì vậy, nếu lời nói của bạn “trong sáng, dễ hiểu” đối với máy thì nó sẽ chạy tốt, còn ngược lại thì...... greenbiggrin.gif
Có người từng nói với snow: “Muốn lập trình tốt thì đầu tiên phải học cách... ngu như máy trước, rùi mới lập trình tốt được!”. Ý người đó muốn nói là lập trình viên phải hiểu được những giới hạn cũng như những khả năng của máy tính thì mới có thể lập trình tốt được. Nếu bạn ko nắm rõ thì những gì bạn viết ra đôi khi là Mission Impossible với 1 cái máy tính và khi đó nó sẽ trở nên “ngu”.
1. Những yêu cầu với 1 chương trình máy tính
Đầu tiên ta cần biết lập trình là viết ra những chương trình nhằm giúp máy tính giải quyết những bài toán, những yêu cầu nào đó trong thực tế cho ta. Vì vậy có 1 số yêu cầu nhất định cho việc viết chương trình:
+Đúng đắn: chương trình phải đáp ứng được những yêu cầu được đặt ra.
+Chính xác
+Tin cậy: bảo đảm cùng 1 dữ liệu nhập vào thì kết quả trả ra luôn luôn giống nhau
+Tổng quát: người lập trình viên phải có khả năng nhìn thấy tất cả mọi khả năng có thể của dữ liệu nhập vào và chương trình phải làm việc tốt được với mọi dữ liệu nhập vào.
+An toàn: chương trình phải làm việc tốt ngay cả trong những điều kiện bất thường xảy ra, hạn chế việc chương trình bị “chết” trong quá trình chạy vì nhiều nguyên nhân như dữ liệu nhập vào không phù hợp, lỗi truy cập...vv... (hình như việc này ngay cả Microsoft cũng...ko làm được vì Widows cứ bị hư hoài à...).
+Hiệu quả: Chương trình phải tiết kiệm tài nguyên ở mức thấp nhất có thể, chạy nhanh nhất ở mức có thể...
+Dễ : nâng cấp, sửa chữa.
2.Thiết kế chương trình:
a. Các xu hướng thiết kế:
Hiện nay có 2 xu hướng chính được chọn lựa trong việc thiết kế chương trình máy tính đó là : hướng thủ tục và hướng đối tượng
a.1.Hướng thủ tục(MP):
Thông qua 1 quá trình phân tích nhất định, lập trình viên sẽ tách bài toán hay yêu cầu ban đầu thành những bài toán con, yêu cầu con đơn giản hơn và giải quyết từng thứ 1. Việc này sẽ giúp bạn thực hiện được các bài toán phức tạp 1 cách dễ dàng. Bởi vì viết tổng thể cả 1 bài toán phức tạp là 1 việc làm rất khó và gần như Mission Impossible, nhưng chia nhỏ nó ra thành từng phần nhỏ hơn để giải quyết rùi gắn từng phần riêng đó lại là lựa chọn dễ dàng và khôn ngoan hơn. Việc này còn giúp cho chương trình của bạn dễ đọc, dễ bảo quản và dễ sửa chữa hơn.
Vd: yêu cầu đặt ra là bạn phải viết 1 chương trình dọc dữ liệu từ 1 file chứa các thông tin về số nhân viên, thông tin của từng nhân viên của 1 công ty, xử lí và trả lại thông tin về lương sẽ trả tháng này của từng nhân viên.
Như vậy nếu bạn để y nguyên như vậy mà làm sẽ rất khó và khi có sai sót bạn sẽ rất khó dò lỗi trong 1 khối chương trình gộp chung như vậy. Vì vậy bạn sẽ tách quá chương trình ra 1 số quá trình đơn giản hơn như sau:
Xử lí việc đọc file
Xứ lí thông tin đọc được từ file
Xử lí việc thông báo kết quả.
Từ các quá trình này bạn có thể tách thêm các quá trình con nữa nếu cần.
Như vậy khi xảy ra lỗi trong lập trình thì việc tìm lỗi và sữ chữa sẽ dễ dàng hơn cho bạn. Chẳng hạn khi lỗi thuộc về việc đọc file thì bạn chỉ cần dò tìm nó trong đoạn thủ tục bạn viết dùng để đọc file.
a.2.Hướng đối tượng(OOP): đây là 1 hướng thiết kế mới và gần với thực tế hơn phương pháp hướng thủ tục nhưng đương nhiên đòi hỏi ở bạn nhiều việc để làm và suy nghĩ hơn. 1 cách cơ bản mà nói thì hướng đối tượng nhìn vấn đề với 1 “con mắt khác” so với hướng thủ tục.
a.3 Khác như thế nào???
Nếu như ở hướng thủ tục bạn nhìn chương trình như “1 đống những công việc nhỏ cần phải làm tuần tự”. Thì khác 1 chút ở hướng đối tượng bạn nhìn theo hướng “1 đống những dữ liệu cần được tách riêng và xử lí” (đây là cảm nhận và cách hiểu riêng của snow về 2 hướng lập trình này...).
Vậy tại sao nói hướng đối tượng gần với thực tế hơn hướng thủ tục???
Đơn giản là vì trong thực tế mọi thứ tồn tại vốn dưới dạng các đối tượng (dữ liệu) khác nhau và các đối tượng đó tương tác với nhau chứ ko phải là các thủ tục.
Vd: bạn có thể hình dung như thế này. Cũng với ví dụ tính lương ở trên.
+Bây giờ giả sử tất cả các nhân viên đó đều thuộc về 1 công ty và có những chức vụ khác nhau. Như vậy nếu nhìn theo hướng thủ tục bạn sẽ chỉ thấy việc phải xử lí riêng cho từng loại nhân viên thuộc từng chức vụ 1 và việc này hơi “rối mù“ 1 chút trong chương trình và dễ gây nhầm lẫn cũng như sẽ khó cho việc sửa chữa, nâng cấp về sau nếu như xuất hiện thêm những chức vụ mới.
+Nhưng nếu bạn nhìn theo hướng đối tượng bạn sẽ thấy rằng đầu tiên ở đây có chung 1 loại đối tượng lớn nhất là “nhân viên”. Tiếp theo từ “nhân viên” ta có thể tách ra những đối tượng con của nó là “công nhân”, “trưởng phong”, “thư kí”, “giám đốc”, mỗi 1 đối tượng con sẽ có chung các đặc điểm của đối tượng cha và có riêng các đặc tính riêng của nó. Như vậy khi có thêm chức vụ thì bạn chỉ đơn giản thêm vào 1 đối tượng con mới chứ ko cần sửa lại đoạn mã đã viết ban đầu.
Nhưng bạn phải hiểu đối tượng trong hướng đối tượng ko chỉ đơn giản là “dữ liệu” mà mỗi đối tượng ngoài dữ liệu còn mang trong nó những thủ tục, hành vi của riêng đối tượng đó và đối tượng tương tác với các đối tượng khác thông qua các hành vi này. Và các đối tượng giống nhau sẽ có cùng những hành vi giống nhau. Đây là tính đóng gói của hướng đối tượng.
Ngoài ra hướng đối tượng còn có tính thừa kế nghĩa là tất cả những kiểu đối tượng con dẫn xuất từ cùng 1 kiểu đối tượng cha sẽ được thừa kế những “đặc tính” di truyền của cha (về dữ liệu cũng như hành vi...).
Một tính chất quan trọng khác của hướng đối tượng là tính đa hình, nghĩa là cùng 1 hành vi nhưng đối tượng sẽ có cách “xử sự” khác nhau với từng loại đối tượng khác nhau tuỳ theo định nghĩa của bạn về hành vi của đối tượng đối với từng loại đối tượng khác nhau...
b.Các phương pháp thiết kế:
Ở đây cũng có 2 phương pháp thiết kế chính là từ trên xuống (Top-down) và từ dưới lên (Bottom-up)
b.1.Top-down:
Đây là phương pháp thiết kế mang tính đi sâu vào tổng quát trước. Ở từng tầng của phương pháp thiết kế này chức năng tổng quát nhất được đem ra làm tên gọi, sau đó bạn phát triển những tầng tiếp theo nhỏ hơn của chức năng đó. Và cứ tiếp tục phân tầng như vậy cho tới khi các chức năng đã được đơn giản ở mức có thể thực hiện dễ dàng và hiệu quả.
b.2.Bottom-up:
Ngược lại với kiểu thiết kế top-down là kiểu bottom-up. Kiểu này được sử dụng chủ yếu khi bạn cần xây dựng chương trình từ những thứ đã có sẵn. Như vậy bạn chỉ cần tìm các thành phần cần thiết từ những thứ đã có. Một ví dụ đơn giản là khi bạn sử dụng các hàm đã có sẵn và được hỗ trợ của ngôn ngữ lập trình để xây dựng 1 ứng dụng đơn giản nào đó.
3.Các cấu trúc điều khiển cơ bản:
Dù chương trình của bạn có được xây dựng phức tạp như thế nào, có ứng dụng những giải thuật cao siêu tới đâu thì thực chất 2 thành phần cơ bản nhất xây dựng ra chúng vẫn chỉ là dữ liệu và các cấu trúc điều khiển. ở đây snow nói về các cấu trúc điều khiển cơ bản:
+Cấu trúc điều khiển tuần tự:
các toán tử, hàm, câu lệnh, dữ liệu được xử lí theo nguyên tắc tuần tự: trái sang phải, trên xuống dưới. Bạn phải nắm rõ sự tuần tự này và cả các thay đổi của dữ liệu trong thứ tự làm việc của chương trình nếu muốn đảm bảo chương trình sẽ chạy đúng.
+Cấu trúc điều kiện:
Bao gồm những toán tử, hàm, câu lệnh, dữ liệu chỉ được thực hiện hoặc xử lí khi 1 điều kiện nào đó được thỏa mãn.
+Cấu trúc lặp:
Gồm những toán tử, hàm, câu lệnh, dữ liện sẽ được xử lí lặp lại 1 số hữu hạn lần nào đó. Bạn phải chú ý khi sử dụng cấu trúc lặp để tránh tạo ra những cấu trúc lặp vô hạn sẽ dẫn đến việc treo máy. Vì vậy yêu cầu đầu tiên khi sử dụng cấu trúc lặp là điều kiện dừng của vòng lặp phải đúng đắn. Bạn còn phải lưu ý tính nhớ và sự thay đổi của dữ liệu trong vòng lặp để đảm bảo cho chương trình chạy đúng.
+Ngoài 3 cấu trúc cơ bản trên còn 1 kiểu lập trình rất cần thiết cho 1 số bài toán, đó là kiểu đệ qui. Đôi khi đây là “điều không thể tránh khỏi” khi bạn “đụng” vào những bài toán có bạn chất là đệ qui.
1 thủ tục đệ qui sẽ gọi lại bản thân nó tại 1 nơi nào đó bên trong thủ tục đó nếu 1 điều kiện dừng nào đó ko được thoả. Cũng giống như cấu trúc lặp, khi sử dụng đệ qui bạn phải đảm bảo điều kiện dừng cho nó. Nhưng bạn cần lưu ý là đệ qui sẽ chiếm 1 số khá lớn tài nguyên bộ nhớ do mỗi 1 lần đệ qui, các mã lệnh sẽ được “quăng” vào stack của bộ nhớ và lưu lại đó cho tới khi được xử lí. Như vậy đệ qui càng nhiều lần thì bộ nhớ sẽ “nặng” và ảnh hưởng tới hiệu quả của các chương trình khác. Trong 1 số trường hợp bạn có thể khử đệ qui bằng cách sử dụng các vòng lặp, stack hoặc queue...
1 ví dụ đơn giản về đệ qui trên C:
Chẳng hạn để tính 1 giai thừa n!, bạn có thể sử dụng 1 hàm đệ qui như sau:
int Giai_thua(int n)
{
if(n==1)
return 1;
return n*Giai_thua(n-1);
}
Nhưng cũng có thể sử dụng vòng lặp để giải quyết:
int Giai_thua(int n)
{
int result=1;
for(int i=2; i<=n; i++)
result *= i
return result;
}
4. Tổng quát về trình biên dịch và thông dịch của ngôn ngữ lập trình:
Ở đây snow chỉ nói sơ sơ những gì snow hiểu về trình biên dịch và thông dịch để giúp các bạn khỏi thắc mắc xem “nó làm ăn ra sao???”. Và đây cũng được coi là những hiểu biết sơ đẳng nhất mà bạn cần biết khi lập trình:
Như snow đã từng đề cập ở trên, việc lập trình ngày nay ko phải là cái kiểu ngồi dịch từng mã nhị phân như “cái thuở ban đầu lưu luyến ấy” nữa. Ngày nay các lập trình viên tạo ra các chương trình bằng việc lập trình bằng 1 ngôn ngữ nào đó và đem biên dịch bằng trình biên dịch của ngôn ngữ đó trước khi chạy chương trình, hoặc vừa chạy vừa dịch(chạy tới đâu dịch tới đó) nếu là trình thông dịch.
2 chương trình trên thực chất có thể coi là trung gian giao tiếp giữa người lập trình viên và máy tính. Hiểu nó bạn sẽ hiểu “Ê, tại sao tui viết cái lệnh toàn tiếng Anh hông hà mà mấy cái máy nó hiểu hay vậy???”. Thiệt ra thì máy đâu có hiểu mấy cái “tiếng Anh nửa mùa” mà bạn viết. Nó chỉ hiểu mã nhị phân 0,1 của những gì bạn viết ra đã được trình biên dịch hoặc thông dịch dịch lại cho nó “nghe” thôi. Nhưng giữa 2 chương trình thông dịch và biên dịch có những khác biệt nhất định dù chúng có cùng nhiệm vụ là “dịch” lại cho máy “nghe” những gì bạn “nói” với nó.
4.1 Trình biên dịch:
Toàn bộ mã chương trình mà bạn viết sẽ được trình này dịch ra hợp ngữ (assembly) để chuyển thành chỉ thị máy. Trong quá trình này có thể bao gồm quá trình tiền xử lí, biên dịch từng đoạn nhỏ của chương trình, kiểm tra lỗi, kiểm tra kiểu của các biến..., lắp ráp lại thành chương trình cuối cùng để máy có thể thực thi.
4.2 Trình thông dịch:
Khác với trình biên dịch, trình thôn dịch không dịch cùng lúc toàn bộ mã chương trình mà nó dịch từng dòng mã lệnh thành những chỉ thị mà máy có thể thực thi ngay. Từng lệnh sẽ được dịch và được thi hành ngay trong khi dịch chứ ko phải dịch xong tất cả, ráp nối lại rồi mới chạy như trình biên dịch. Nhưng đây cũng có thể là điểm bất lợi của trình thông dịch vì cùng 1 câu lệnh như nhau bạn có thể phải dịch lại nhiều lần ở nhiều thời điểm khác nhau. Trong khi ở trình biên dịch bạn sẽ chỉ phải dịch 1lần, khi cần thì trỏ vào đoạn mã chương trình đã được dịch trước đó.
Bài của Hot Snow !!! ( Edited By B.A )
Thanks - Baby Arthas !!!