24/05/2018, 23:22

Thực hành, thảo luận và tổng quan về lập trình

Bài thực hành làm quen với máy tính, hệ thống tính toán Thảo luận về các bước giải quyết bài toán trên máy tính Giới thiệu phương pháp học Các ngôn ngữ lập trình ra đời và ...

Bài thực hành làm quen với máy tính, hệ thống tính toán Thảo luận về các bước giải quyết bài toán trên máy tính

Giới thiệu phương pháp học

Các ngôn ngữ lập trình ra đời và lỗi thời nhanh một cách đáng kinh ngạc trong ngành Khoa học Máy tính. Các ngôn ngữ lập trình mới thường chứa đựng những quy tắc khác nhau làm cho mọi người phải thường xuyên thay đổi cách dùng các công cụ cũng như thói quen lập trình. Nhưng việc học một ngôn ngữ lập trình mới để cung cấp thêm kiến thức cho nghề nghiệp của mình cũng là một nhu cầu chính đáng.

Trước khi học một ngôn ngữ mới, bạn thường đặt ra câu hỏi: Làm sao để học ngôn ngữ lập trình này được hiệu quả? Có một vài gợi ý nhỏ sau có thể giúp bạn học các ngôn ngữ lập trình dễ dàng hơn:

  • Nắm vững các kiểu dữ liệu cơ bản mà ngôn ngữ lập trình cung cấp. Hầu hết các ngôn ngữ đều cung cấp kiểu số nguyên integer. Bạn phải tìm hiểu thêm thế nào là long integer hoặc short integer? Thế nào là kiểu liệt kê (Enumerated)? Thế nào là kiểu kí tự (Character)? Thế nào là kiểu chuỗi (String)? Ngôn ngữ có hỗ trợ kiểu số thực dấu chấm động hay không, và tầm giá trị của mỗi kiểu dữ liệu là bao nhiêu? Và khi một ngôn ngữ nào đó không hỗ trợ kiểu dữ liệu mà bạn cần dùng thì tốt hơn bạn nên chuyển sang dùng một ngôn ngữ khác.
  • Nắm vững cấu trúc dữ liệu cơ bản được ngôn ngữ cung cấp. Chẳng hạn Pascal có cấu trúc mảng (array), Lisp có thể thao tác rất dễ dàng với cấu trúc danh sách (list), còn Java thì có thể làm việc với các lớp và các giao tiếp.…Và những vấn đề bạn nghĩ trong đầu cuối cùng phải được biểu diễn bằng các kiểu dữ liệu mà ngôn ngữ cung cấp, việc hiểu rõ mối quan hệ giữa chúng là nền tảng để giải quyết các vấn đề.
  • Ngôn ngữ cung cấp những toán tử dựng sẵn nào? Ví dụ: Prolog xem tìm kiếm là một thao tác cơ bản, Snobol xem thao tác đối sánh mẫu trên các chuỗi (string pattern matching) là một toán tử cơ sở, các ngôn ngữ hàm (ML, Haskell) cho phép bạn tạo ra một giá trị mới nhưng không làm thay đổi cấu trúc hiện tại, APL cung cấp toán tử ma trận, … Danh sách các toán tử dựng sẵn của một ngôn ngữ sẽ cho ta biết những vấn đề mà những chuyên gia thiết kế ngôn ngữ đó cho là quan trọng nhất.
  • Nắm vững loại vấn đề mà ngôn ngữ có thể trợ giúp giải quyết. Các ngôn ngữ thường được phát triển vì một lý do nào đó, thường là để giải quyết một loại vấn đề mang tính đặc trưng. Do đó, bạn nên cố gắng nắm rõ những chức năng đặc trưng của ngôn ngữ để giải quyết vấn đề đồng thời cũng nên tìm hiểu tại sao cùng một vấn đề nhưng dùng ngôn ngữ này để giải quyết lại dễ dàng hơn dùng ngôn ngữ khác.
  • Tìm hiểu những thư viện có sẵn trong ngôn ngữ. Các ngôn ngữ thường có các thư viện do nhiều người đã phát triển để giải quyết những vấn đề khác nhau, bạn có thể sử dụng lại để giải quyết một vấn đề mới. Smalltalk có một thư viện đồ sộ với lượng mã luôn sẵn sàng để người lập trình sử dụng. C++ với thư viện chuẩn STL chứa nhiều cấu trúc dữ liệu thường dùng. Java có các thư viện cung cấp các tác vụ về mạng. Bạn hãy cố gắng tìm và sẽ thấy những gì cần thiết sẵn có.
  • Hãy học hỏi, mô phỏng lại! Bắt đầu với việc mô phỏng lại các chương trình hiện có. Phải làm cho chúng có thể hoạt động trên hệ thống của bạn, bởi vì hệ thống mà nó được phát triển có thể không giống với hệ thống của bạn, và khi bạn có thể làm cho nó hoạt động tốt trên hệ thống của mình thì tức là bạn đã hiểu rõ về nó. Học các chương trình để hình dung được các tính năng khác nhau của ngôn ngữ.
  • Hãy thử nghiệm và rút ra kết luận! Khi bạn đã có một vài chương trình có thể chạy tốt, bạn thử nghiệm bằng cách tạo ra một vài thay đổi. Bạn có thể lấy ra một chương trình và sửa lại nó để giải quyết một vấn đề sai khác chút ít so với chương trình ban đầu hay không? Bạn có thể lấy ra một phần nhỏ của chương trình và diễn đạt lại bằng cách khác hay không?
  • Hiện thực lại các vấn đề đã hiểu rõ bằng một ngôn ngữ mới. Lấy một vài chương trình đã được viết trong một ngôn ngữ rồi cố gắng viết lại chúng trong ngôn ngữ mới. Không nên dịch từng câu lệnh sang ngôn ngữ mới mà hãy xem xét những tính năng đặc trưng nào của ngôn ngữ mới có thể dùng để giải quyết vấn đề. Cẩn thận xem xét những vấn đề nào dễ dàng hiện thực trong ngôn ngữ mới và những vấn đề nào khó khăn hơn. (Chương trình truyền thống đầu tiên nên viết là chương trình in ra chuỗi "hello world").
  • Khi gặp một vấn đề mới thì nên nghĩ về những vấn đề đã biết trước đó có cùng đặc điểm với

Ngôn ngữ lập trình

Khái niệm ngôn ngữ lập trình

Ngôn ngữ lập trình là một ngôn ngữ dùng để viết chương trình cho máy tính. Ta có thể chia ngôn ngữ lập trình thành các loại sau: ngôn ngữ máy, hợp ngữ và ngôn ngữ cấp cao.

Ngôn ngữ máy (machine language): Là các chỉ thị dưới dạng nhị phân, can thiệp trực tiếp vào trong các mạch điện tử. Chương trình được viết bằng ngôn ngữ máy thì có thể được thực hiện ngay không cần qua bước trung gian nào. Tuy nhiên chương trình viết bằng ngôn ngữ máy dễ sai sót, cồng kềnh và khó đọc, khó hiểu vì toàn những con số 0 và 1.

Hợp ngữ (assembly language): Bao gồm tên các câu lệnh và quy tắc viết các câu lệnh đó. Tên các câu lệnh bao gồm hai phần: phần mã lệnh (viết tựa tiếng Anh) chỉ phép toán cần thực hiện và địa chỉ chứa toán hạng của phép toán đó. Ví dụ:

INPUT a ; Nhập giá trị cho a từ bàn phím

LOAD a ; Đọc giá trị a vào thanh ghi tổng A

PRINT a; Hiển thị giá trị của a ra màn hình.

INPUT b

ADD b; Cộng giá trị của thanh ghi tổng A với giá trị b

Trong các lệnh trên thì INPUT, LOAD, PRINT, ADD là các mã lệnh còn a, b là địa chỉ. Để máy thực hiện được một chương trình viết bằng hợp ngữ thì chương trình đó phải được dịch sang ngôn ngữ máy. Công cụ thực hiện việc dịch đó được gọi là Assembler.

Ngôn ngữ cấp cao (High level language): Ra đời và phát triển nhằm phản ánh cách thức người lập trình nghĩ và làm. Rất gần với ngôn ngữ con người (Anh ngữ) nhưng chính xác như ngôn ngữ toán học. Cùng với sự phát triển của các thế hệ máy tính, ngôn ngữ lập trình cấp cao cũng được phát triển rất đa dạng và phong phú, việc lập trình cho máy tính vì thế mà cũng có nhiều khuynh hướng khác nhau: lập trình cấu trúc, lập trình hướng đối tượng, lập trình logic, lập trình hàm... Một chương trình viết bằng ngôn ngữ cấp cao được gọi là chương trình nguồn (source programs). Để máy tính "hiểu" và thực hiện được các lệnh trong chương trình nguồn thì phải có một chương trình dịch để dịch chuơng trình nguồn (viết bằng ngôn ngữ cấp cao) thành dạng chương trình có khả năng thực thi.

Chương trình dịch

Như trên đã trình bày, muốn chuyển từ chương trình nguồn sang chương trình đích phải có chương trình dịch. Thông thường mỗi một ngôn ngữ cấp cao đều có một chương trình dịch riêng nhưng chung quy lại thì có hai cách dịch: thông dịch và biên dịch.

Thông dịch (interpreter): Là cách dịch từng lệnh một, dịch tới đâu thực hiện tới đó. Chẳng hạn ngôn ngữ LISP sử dụng trình thông dịch.

Biên dịch (compiler): Dịch toàn bộ chương trình nguồn thành chương trình đích rồi sau đó mới thực hiện. Các ngôn ngữ sử dụng trình biên dịch như Pascal, C...

Giữa thông dịch và biên dịch có khác nhau ở chỗ: Do thông dịch là vừa dịch vừa thực thi chương trình còn biên dịch là dịch xong toàn bộ chương trình rồi mới thực thi nên chương trình viết bằng ngôn ngữ biên dịch thực hiện nhanh hơn chương trình viết bằng ngôn ngữ thông dịch.

Một số ngôn ngữ sử dụng kết hợp giữa thông dịch và biên dịch chẳng hạn như Java. Chương trình nguồn của Java được biên dịch tạo thành một chương trình đối tượng (một dạng mã trung gian) và khi thực hiện thì từng lệnh trong chương trình đối tượng được thông dịch thành mã máy.

Các phương pháp lập trình

Lập trình tuyến tính

Máy tính đầu tiên được lập trình bằng mã nhị phân, sử dụng các công tắt cơ khí để nạp chương trình. Cùng với sự xuất hiện của các thiết bị lưu trữ lớn và bộ nhớ máy tính có dung lượng lớn nên các ngôn ngữ lập trình cấp cao đầu tiên được đưa vào sử dụng . Thay vì phải suy nghĩ trên một dãy các bit và byte, lập trình viên có thể viết một loạt lệnh gần với tiếng Anh và sau đó chương trình dịch thành ngôn ngữ máy.

Các ngôn ngữ lập trình cấp cao đầu tiên được thiết kế để lập các chương trình làm các công việc tương đối đơn giản như tính toán. Các chương trình ban đầu chủ yếu liên quan đến tính toán và không đòi hỏi gì nhiều ở ngôn ngữ lập trình. Hơn nữa phần lớn các chương trình này tương đối ngắn, thường ít hơn 100 dòng.

Khi khả năng của máy tính tăng lên thì khả năng để triển khai các chương trình phức tạp hơn cũng tăng lên. Các ngôn ngữ lập trình ngày trước không còn thích hợp đối với việc lập trình đòi hỏi cao hơn. Các phương tiện cần thiết để sử dụng lại các phần mã chương trình đã viết hầu như không có trong ngôn ngữ lập trình tuyến tính. Thật ra, một đoạn lệnh thường phải được chép lặp lại mỗi khi chúng ta dùng trong nhiều chương trình do đó chương trình dài dòng, logic của chương trình khó hiểu. Chương trình được điều khiển để nhảy đến nhiều chỗ mà thường không có sự giải thích rõ ràng, làm thế nào để chương trình đến chỗ cần thiết hoặc tại sao như vậy.

Ngôn ngữ lập trình tuyến tính không có khả năng kiểm soát phạm vi nhìn thấy của các dữ liệu. Mọi dữ liệu trong chương trình đều là dữ liệu toàn cục nghĩa là chúng có thể bị sửa đổi ở bất kỳ phần nào của chương trình. Việc dò tìm các thay đổi không mong muốn đó của các phần tử dữ liệu trong một dãy mã lệnh dài và vòng vèo đã từng làm cho các lập trình viên rất mất thời gian.

Lập trình cấu trúc

Rõ ràng là các ngôn ngữ mới với các tính năng mới cần phải được phát triển để có thể tạo ra các ứng dụng tinh vi hơn. Vào cuối các năm trong 1960 và 1970, ngôn ngữ lập trình có cấu trúc ra đời. Các chương trình có cấu trúc được tổ chức theo các công việc mà chúng thực hiện.

Về bản chất, chương trình chia nhỏ thành các chương trình con riêng rẽ (còn gọi là hàm hay thủ tục) thực hiện các công việc rời rạc trong quá trình lớn hơn, phức tạp hơn. Các hàm này được giữ càng độc lập với nhau càng nhiều càng tốt, mỗi hàm có dữ liệu và logic riêng.Thông tin được chuyển giao giữa các hàm thông qua các tham số, các hàm có thể có các biến cục bộ mà không một ai nằm bên ngoài phạm vi của hàm lại có thể truy xuất được chúng. Như vậy, các hàm có thể được xem là các chương trình con được đặt chung với nhau để xây dựng nên một ứng dụng.

Mục tiêu là làm sao cho việc triển khai các phần mềm dễ dàng hơn đối với các lập trình viên mà vẫn cải thiện được tính tin cậy và dễ bảo quản chương trình. Một chương trình có cấu trúc được hình thành bằng cách bẻ gãy các chức năng cơ bản của chương trình thành các mảnh nhỏ mà sau đó trở thành các hàm. Bằng cách cô lập các công việc vào trong các hàm, chương trình có cấu trúc có thể làm giảm khả năng của một hàm này ảnh hưởng đến một hàm khác. Việc này cũng làm cho việc tách các vấn đề trở nên dễ dàng hơn. Sự gói gọn này cho phép chúng ta có thể viết các chương trình sáng sủa hơn và giữ được điều khiển trên từng hàm. Các biến toàn cục không còn nữa và được thay thế bằng các tham số và biến cục bộ có phạm vi nhỏ hơn và dễ kiểm soát hơn. Cách tổ chức tốt hơn này nói lên rằng chúng ta có khả năng quản lý logic của cấu trúc chương trình, làm cho việc triển khai và bảo dưỡng chương trình nhanh hơn và hữu hiện hơn và hiệu quả hơn.

Một khái niệm lớn đã được đưa ra trong lập trình có cấu trúc là sự trừu tượng hóa (Abstraction). Sự trừu tượng hóa có thể xem như khả năng quan sát một sự việc mà không cần xem xét đến các chi tiết bên trong của nó. Trong một chương trình có cấu trúc, chúng ta chỉ cần biết một hàm đã cho có thể làm được một công việc cụ thể gì là đủ. Còn làm thế nào mà công việc đó lại thực hiện được là không quan trọng, chừng nào hàm còn tin cậy được thì còn có thể dùng nó mà không cần phải biết nó thực hiện đúng đắn chức năng của mình như thế nào. Điều này gọi là sự trừu tượng hóa theo chức năng (Functional abstraction) và là nền tảng của lập trình có cấu trúc.

Ngày nay, các kỹ thuật thiết kế và lập trình có cấu trúc được sử rộng rãi. Gần như mọi ngôn ngữ lập trình đều có các phương tiện cần thiết để cho phép lập trình có cấu trúc. Chương trình có cấu trúc dễ viết, dễ bảo dưỡng hơn các chương trình không cấu trúc.

Sự nâng cấp như vậy cho các kiểu dữ liệu trong các ứng dụng mà các lập trình viên đang viết cũng đang tiếp tục diễn ra. Khi độ phức tạp của một chương trình tăng lên, sự phụ thuộc của nó vào các kiểu dữ liệu cơ bản mà nó xử lý cũng tăng theo. Vấn đề trở rõ ràng là cấu trúc dữ liệu trong chương trình quan trọng chẳng kém gì các phép toán thực hiện trên chúng. Điều này càng trở rõ ràng hơn khi kích thước của chương trình càng tăng. Các kiểu dữ liệu được xử lý trong nhiều hàm khác nhau bên trong một chương trình có cấu trúc. Khi có sự thay đổi trong các dữ liệu này thì cũng cần phải thực hiện cả các thay đổi ở mọi nơi có các thao tác tác động trên chúng. Đây có thể là một công việc tốn thời gian và kém hiệu quả đối với các chương trình có hàng ngàn dòng lệnh và hàng trăm hàm trở lên.

Một yếu điểm nữa của việc lập trình có cấu trúc là khi có nhiều lập trình viên làm việc theo nhóm cùng một ứng dụng nào đó. Trong một chương trình có cấu trúc, các lập trình viên được phân công viết một tập hợp các hàm và các kiểu dữ liệu. Vì có nhiều lập trình viên khác nhau quản lý các hàm riêng, có liên quan đến các kiểu dữ liệu dùng chung nên các thay đổi mà lập trình viên tạo ra trên một phần tử dữ liệu sẽ làm ảnh hưởng đến công việc của tất cả các người còn lại trong nhóm. Mặc dù trong bối cảnh làm việc theo nhóm, việc viết các chương trình có cấu trúc thì dễ dàng hơn nhưng sai sót trong việc trao đổi thông tin giữa các thành viên trong nhóm có thể dẫn tới hậu quả là mất rất nhiều thời gian để sửa chữa chương trình.

Sự trừu tượng hóa dữ liệu

Sự trừu tượng hóa dữ liệu (Data abstraction) tác động trên các dữ liệu cũng tương tự như sự trừu tượng hóa theo chức năng. Khi có trừu tượng hóa dữ liệu, các cấu trúc dữ liệu và các phần tử có thể được sử dụng mà không cần bận tâm đến các chi tiết cụ thể. Chẳng hạn như các số dấu chấm động đã được trừu tượng hóa trong tất cả các ngôn ngữ lập trình, Chúng ta không cần quan tâm cách biểu diễn nhị phân chính xác nào cho số dấu chấm động khi gán một giá trị, cũng không cần biết tính bất thường của phép nhân nhị phân khi nhân các giá trị dấu chấm động. Điều quan trọng là các số dấu chấm động hoạt động đúng đắn và hiểu được.

Sự trừu tượng hóa dữ liệu giúp chúng ta không phải bận tâm về các chi tiết không cần thiết. Nếu lập trình viên phải hiểu biết về tất cả các khía cạnh của vấn đề, ở mọi lúc và về tất cả các hàm của chương trình thì chỉ ít hàm mới được viết ra, may mắn thay trừu tượng hóa theo dữ liệu đã tồn tại sẵn trong mọi ngôn ngữ lập trình đối với các dữ liệu phức tạp như số dấu chấm động. Tuy nhiên chỉ mới gần đây, người ta mới phát triển các ngôn ngữ cho phép chúng ta định nghĩa các kiểu dữ liệu trừu tượng riêng.

Lập trình hướng đối tượng

Khái niệm hướng đối tượng được xây dựng trên nền tảng của khái niệm lập trình có cấu trúc và sự trừu tượng hóa dữ liệu. Sự thay đổi căn bản ở chỗ, một chương trình hướng đối tượng được thiết kế xoay quanh dữ liệu mà chúng ta có thể làm việc trên đó, hơn là theo bản thân chức năng của chương trình. Điều này hoàn toàn tự nhiên một khi chúng ta hiểu rằng mục tiêu của chương trình là xử lý dữ liệu. Suy cho cùng, công việc mà máy tính thực hiện vẫn thường được gọi là xử lý dữ liệu. Dữ liệu và thao tác liên kết với nhau ở một mức cơ bản (còn có thể gọi là mức thấp), mỗi thứ đều đòi hỏi ở thứ kia có mục tiêu cụ thể, các chương trình hướng đối tượng làm tường minh mối quan hệ này.

Lập trình hướng đối tượng (Object Oriented Programming - gọi tắt là OOP) hay chi tiết hơn là Lập trình định hướng đối tượng, chính là phương pháp lập trình lấy đối tượng làm nền tảng để xây dựng thuật giải, xây dựng chương trình. Thực chất đây không phải là một phương pháp mới mà là một cách nhìn mới trong việc lập trình. Để phân biệt, với phương pháp lập trình theo kiểu cấu trúc mà chúng ta quen thuộc trước đây, hay còn gọi là phương pháp lập trình hướng thủ tục (Procedure-Oriented Programming), người lập trình phân tích một nhiệm vụ lớn thành nhiều công việc nhỏ hơn, sau đó dần dần chi tiết, cụ thể hoá để được các vấn đề đơn giản, để tìm ra cách giải quyết vấn đề dưới dạng những thuật giải cụ thể rõ ràng qua đó dễ dàng minh hoạ bằng ngôn ngữ giải thuật (hay còn gọi các thuật giải này là các chương trình con). Cách thức phân tích và thiết kế như vậy chúng ta gọi là nguyên lý lập trình từ trên xuống (top-down), để thể hiện quá trình suy diễn từ cái chung cho đến cái cụ thể.

Các chương trình con là những chức năng độc lập, sự ghép nối chúng lại với nhau cho chúng ta một hệ thống chương trình để giải quyết vấn đề đặt ra. Chính vì vậy, cách thức phân tích một hệ thống lấy chương trình con làm nền tảng, chương trình con đóng vai trò trung tâm của việc lập trình, được hiểu như phương pháp lập trình hướg về thủ tục. Tuy nhiên, khi phân tích để thiết kế một hệ thống không nhất thiết phải luôn luôn suy nghĩ theo hướng “làm thế nào để giải quyết công việc”, chúng ta có thể định hướng tư duy theo phong cách “với một số đối tượng đã có, phải làm gì để giải quyết được công việc đặt ra” hoặc phong phú hơn, “làm cái gì với một số đối tượng đã có đó”, từ đó cũng có thể giải quyết được những công việc cụ thể. Với phương pháp phân tích trong đó đối tượng đóng vai trò trùng tâm của việc lập trình như vậy, người ta gọi là nguyên lý lập trình từ dưới lên (Bôttm-up).

Lập trình hướng đối tượng liên kết cấu trúc dữ liệu với các thao tác, theo cách mà tất cả thường nghĩ về thế giới quanh mình. Chúng ta thường gắn một số các hoạt động cụ thể với một loại hoạt động nào đó và đặt các giả thiết của mình trên các quan hệ đó.

Ví dụ1.1: Để dễ hình dùng hơn, chúng ta thủ nhìn qua các công trình xây dựng hiện đại, như sân vận động có mái che hình vòng cung, những kiến trúc thẩm mĩ với đường nét hình cong. Tất cả những sản phẩm đó xuất hiện cùng với những vật liệu xây dựng. Ngày nay, không chỉ chồng lên nhau những viên gạch, những tảng đá để tạo nên những quần thể kiến trúc (như Tháp Chàm Nha Trang, Kim Tự Tháp,...), mà có thể với bêtông, sắt thép và không nhiều lắm những viên gạch, người xây dựng cũng có thể thiết kế những công trình kiến trúc tuyệt mỹ, những toà nhà hiện đại. Chính các chất liệu xây dựng đã làm ảnh hưởng phương pháp xây dựng, chất liệu xây dựng và nguyên lý kết dính caá chất liệu đó lại với nhau cho chúng ta một đối tượng để khảo sát, Chất liệu xây dựng và nguyên lý kết dính các chất liệu lại với nhau được hiểu theo nghĩa dữ liệu và chương trình con tác động trên dữ liệu đó.

Ví dụ1.2: Chúng ta biết rằng một chiếc xe có các bánh xe, di chuyển được và có thể đổi hướng của nó bằng cách quẹo tay lái. Tương tự như thế, một cái cây là một loại thực vật có thân gỗ và lá. Một chiếc xe không phải là một cái cây, mà cái cây không phải là một chiếc xe, chúng ta có thể giả thiết rằng cái mà chúng ta có thể làm được với một chiếc xe thì không thể làm được với một cái cây. Chẳng hạn, thật là vô nghĩa khi muốn lái một cái cây, còn chiếc xe thì lại chẳng lớn thêm được khi chúng ta tưới nước cho nó.

Lập trình hướng đối tượng cho phép chúng ta sử dụng các quá trình suy nghĩ như vậy với các khái niệm trừu tượng được sử dụng trong các chương trình máy tính. Một mẫu tin (record) nhân sự có thể được đọc ra, thay đổi và lưu trữ lại; còn số phức thì có thể được dùng trong các tính toán. Tuy vậy không thể nào lại viết một số phức vào tập tin làm mẫu tin nhân sự và ngược lại hai mẫu tin nhân sự lại không thể cộng với nhau được. Một chương trình hướng đối tượng sẽ xác định đặc điểm và hành vi cụ thể của các kiểu dữ liệu, điều đó cho phép chúng ta biết một cách chính xác rằng chúng ta có thể có được những gì ở các kiểu dữ liệu khác nhau.

Chúng ta còn có thể tạo ra các quan hệ giữa các kiểu dữ liệu tương tự nhưng khác nhau trong một chương trình hướng đối tượng. Người ta thường tự nhiên phân loại ra mọi thứ, thường đặt mối liên hệ giữa các khái niệm mới với các khái niệm đã có, và thường có thể thực hiện suy diễn giữa chúng trên các quan hệ đó. Hãy quan niệm thế giới theo kiểu cấu trúc cây, với các mức xây dựng chi tiết hơn kế tiếp nhau cho các thế hệ sau so với các thế hệ trước. Đây là phương pháp hiệu quả để tổ chức thế giới quanh chúng ta. Các chương trình hướng đối tượng cũng làm việc theo một phương thức tương tự, trong đó chúng cho phép xây dựng các các cơ cấu dữ liệu và thao tác mới dựa trên các cơ cấu có sẵn, mang theo các tính năng của các cơ cấu nền mà chúng dựa trên đó, trong khi vẫn thêm vào các tính năng mới.

Lập trình hướng đối tượng cho phép chúng ta tổ chức dữ liệu trong chương trình theo một cách tương tự như các nhà sinh học tổ chức các loại thực vật khác nhau. Theo cách nói lập trình đối tượng, xe hơi, cây cối, các số phức, các quyển sách đều được gọi là các lớp (Class).

Một lớp là một bản mẫu mô tả các thông tin cấu trúc dữ liệu, lẫn các thao tác hợp lệ của các phần tử dữ liệu. Khi một phần tử dữ liệu được khai báo là phần tử của một lớp thì nó được gọi là một đối tượng (Object). Các hàm được định nghĩa hợp lệ trong một lớp được gọi là các phương thức (Method) và chúng là các hàm duy nhất có thể xử lý dữ liệu của các đối tượng của lớp đó. Một thực thể (Instance) là một vật thể có thực bên trong bộ nhớ, thực chất đó là một đối tượng (nghĩa là một đối tượng được cấp phát vùng nhớ).

Mỗi một đối tượng có riêng cho mình một bản sao các phần tử dữ liệu của lớp còn gọi là các biến thực thể (Instance variable). Các phương thức định nghĩa trong một lớp có thể được gọi bởi các đối tượng của lớp đó. Điều này được gọi là gửi một thông điệp (Message) cho đối tượng. Các thông điệp này phụ thuộc vào đối tượng, chỉ đối tượng nào nhận thông điệp mới phải làm việc theo thông điệp đó. Các đối tượng đều độc lập với nhau vì vậy các thay đổi trên các biến thể hiện của đối tượng này không ảnh hưởng gì trên các biến thể hiện của các đối tượng khác và việc gửi thông điệp cho một đối tượng này không ảnh hưởng gì đến các đối tượng khác.

Như vậy, đối tợng được hiểu theo nghĩa là một thực thể mà trong đó caá dữ liệu và thủ tục tác động lên dữ liệu đã được đóng gói lại với nhau. Hay “đối tượng được đặc trưng bởi một số thao tác (operation) và các thông tin (information) ghi nhơ sự tác động của caá thao tác này.”

Ví dụ 1.3: Khi nghiên cứ về ngăn xếp (stack), ngoài các dữ liệu vùng chứa ngăn xếp, đỉnh của ngăn xếp, chúng ta phải cài đặt kèm theo các thao tác như khởi tạo (creat) ngăn xếp, kiểm tra ngăn xếp rỗng (empty), đẩy (push) một phần tử vào ngăn xếp, lấy (pop) một phần tử ra khỏi ngăn xếp. Trên quan điểm lấy đối tượng làm nền tảng, rõ ràng dữ liệu và các thao tác trên dữ liệu luôn gắn bó với nhau, sự kết dính chúng chính là đối tượng chúng ta cần khảo sát.

Các thao tác trong đối tượng được gọi là các phương thức hay hành vi của đối tượng đó. Phương thức và dữ liệu của đối tượng luôn tác động lẫn nhau và có vai trò ngang nhau trong đối tượng, Phương thức của đối tượng được qui định bởi dữ liệu và ngược lại, dữ liệu của đối tượng được đặt trưng bởi các phương thức của đối tượng. Chính nhờ sự gắn bó đó, chúng ta có thể gởi cùng một thông điệp đến những đối tượng khác nhau. Điều này giúp người lập trình không phải xử lý trong chương trình của mình một dãy các cấu trúc điều khiển tuỳ theo thông điệp nhận vào, mà chương trình được xử lý vào thời điểm thực hiện.

Tóm lại, so sánh lập trình cấu trúc với chương trình con làm nền tảng:

Chương trình = Cấu trúc dữ liệu + Thuật giải

Trong lập trình hướng đối tượng chúng ta có:

Đối tượng = Phương thức + Dữ liệu

Đây chính là 2 quan điểm lập trình đang tồn tại và phát triển trong thế giới ngày nay.

Một số ngôn ngữ lập trình

  • Ngôn ngữ lập trình Pascal

Đây là ngôn ngữ do giáo sư Niklaus Wirth thiết kế vào năm 1970 với mục đích giảng dạy ý niệm lập trình có cấu trúc. Nhưng sau một thời gian do tính ưu việt của nó nên PASCAL đã được sử dụng rộng dãi.

PASCAL là ngôn ngữ lập trình bậc cao. Trước khi PASCAL được phát triển thì việc lập trình được thực hiện trên các ngôn ngữ cấp thấp, các lập trình viên rất khó khăn trong việc xây dựng các chương trình lớn. PASCAL dùng ngôn ngữ sát với ngôn ngữ tự nhiên hơn do đó nó thân thiện với người lập trình hơn. Do vậy nó giảm bớt các công việc nặng nhọc cho người lập trình.

PASCAL kết hợp giữa đặc tính gọn, dễ nhớ, khả năng truy cập cấp thấp, và các cấu trúc giữ liệu đa dạng. PASCAL còn hỗ trợ khả năng đưa các chương trình viết bằng ASSEMBLER vào chương trình của bạn, khả năng đồ hoạ và hướng đối tượng.PASCAL là ngôn ngữ lập trình có cấu trúc. Tính cấu trúc của PASCAL được thể hiện qua 3 yếu tố: cấu trúc trong dữ liệu, cấu trúc trong các toán tử và cấu trúc trong công cụ thủ tục.

• Tính cấu trúc của dữ liệu được thể hiện qua phần mô tả. Cũng như các ngôn ngữ lập trình khác, PASCAL có một số kiểu dữ liệu được định nghĩa sẵn và các phép toán trên các kiểu dữ liệu này. Từ các kiểu dữ liệu đó, người lập trình có thể xây dựng các kiểu dữ liệu phức tạp hơn. Sau đó để khai báo đối tượng thuộc kiểu dữ liệu phức tạp đó ta không cần trình bày lại cấu trúc thiết lập, mà chỉ cần tham chiếu đến kiểu đó.

• Tính cấu trúc của các toán tử được thể hiện ở chỗ bên trong các toán tử thực hiện một động tác, còn có các toán tử thực hiện nhiều động tác, song sự quan trọng nhất của PASCAL là toán tử hợp thành. Toán tử hợp thành được xây dựng bắt đầu bằng từ khoá BEGIN, sau đó đến dãy các toán tử thành phần và kết thúc bằng từ khoá END.

• Tính cấu trúc trong công cụ thủ tục thể hiện thông qua khả năng phân tích chương trình thành các modul độc lập và lời gọi đệ quy thủ tục. PASCAL không phải là ngôn ngữ khó học hơn ngôn ngữ dành cho những người mới bắt đầu làm quen với lập trình (BASIC) nhưng nó lại tỏ ra có những đặc tính cấu trúc hoá tốt hơn và không có những cú pháp mang lỗi.

PASCAL không phân biệt chữ hoa và chữ thường, do vậy người lập trình có thể thoải mái hơn trong việc viết các câu lệnh và đặt tên cho các đối tượng của mình.Việc dịch một chương trình viết bằng PASCAL được thực hiện bằng một trình biên dịch. Khi chương trình chứa một lỗi cú pháp nào đó thì mã máy sẽ không được sinh ra. Còn nếu không có lỗi thì sau khi dịch xong sẽ nhận được một bản mã đối tượng.Với những chương trình lớn thì dùng ngôn ngữ lập trình có cấu trúc để quản lý sẽ là rất khó khăn, vì vậy để đáp ứng nhu cầu của người lập trình những phiên bản của PASCAL về sau này đã có hỗ trợ lập trình hướng đối tượng.

Do mục đích ban đầu của PASCAL và các đặc điểm của nó, PASCAL rất thích hợp dùng để giảng dạy trong các nhà trường và cho những người mới bắt đầu học lập trình. Còn đối với những bài toán ứng dụng trong thực tế thì PASCAL ít được sử dụng.

  • Ngôn ngữ lập trình Java

JAVA được tạo ra trước năm 1990 bởi nhóm các nhà phát triển của Sun Microsystem có nhiệm vụ phải viết phầm mềm hệ thống để nhúng vào các sản phẩm điện tử của khách hàng. Họ đã khắc phục một số hạn chế của C++ để tạo ra ngôn ngữ lập trình JAVA.

Do được phát triển từ C++ nên JAVA rất giống C++. Nhưng JAVA là ngôn ngữ hướng đối tượng hoàn toàn, còn C++ là ngôn ngữ đa hướng.JAVA là ngôn ngữ lập trình mạnh vì nó hội tụ được các yếu tố sau:

• JAVA là ngôn ngữ hướng đối tượng (object oriented programming): Các ngôn ngữ lập trình hướng đối tượng có các modul có thể thay đổi và được xác định trước mà người lập trình có thể gọi ra để thực hiện những nhiệm vụ cụ thể. Trong JAVA các modul này gọi là các lớp (class) và chúng được lưu trữ trong thư viện lớp tạo nên cơ sở của bộ công cụ phát triển JAVA (Java Development Kit). Trong JAVA tất cả các hàm và biến đều phải là thành phần của một lớp.

• Đơn giản (simple): Mặc dù dựa trên cơ sở của C++ nhưng JAVA đã được lược bỏ các tính năng khó nhất của C++ làm cho ngôn ngữ này dễ dùng hơn. Do vậy việc đào tạo một lập trình viên JAVA ngắn hơn và JAVA trở nên thân thiện với người sử dụng hơn. Trong JAVA không có các con trỏ, không hỗ trợ toán tử Overloading, không có tiền xử lý. Tất cả mọi đối tượng trong một chương trình JAVA đều được tạo trên heap bằng toán tử new - chúng không bao giờ được tạo trên stack. JAVA cũng là ngôn ngữ gom rác (garbage - collected language), vì vậy nó không cần đếm từng new với delete - một nguồn bộ nhớ chung để thất thoát trong các chương trình của C++. Trong thực tế không có toán tử delete trong JAVA.

• Đa luồng (multithread): Có nghĩa là JAVA cho phép xây dựng các trình ứng dụng, trong đó, nhiều quá trình có thể xảy ra đồng thời. Tính đa luồng cho phép các nhà lập trình có thể biên soạn các phần mềm đáp ứng tốt hơn, tương tác hơn và thực hiện theo thời gian thực.

• JAVA độc lập với cấu trúc máy: Đây là thuộc tính đặc sắc nhất của JAVA. Có nghĩa là JAVA không phụ thuộc vào hệ máy, các ứng dụng bằng JAVA có thể dùng được trên hầu như mọi máy tính.

Có thể nói JAVA là ngôn ngữ lập trình cho Web:

• Hiểu mạng: JAVA được viết ra để hoạt động trên mạng và có các thủ tục để có thể quản lý các giao thức TCP/IP, FTP, HTTP. Nói cách khác JAVA được xây dựng để hoàn toàn tương thích trên Internet.

• JAVA cho phép tạo ra các trang Web động, các ứng dụng nhúng.

• An toàn: Đặc tính an toàn của ngôn ngữ lập trình này bắt nguồn từ việc nó có những phần hạn chế được cài đặt sẵn nhằm đề phòng các chương trình JAVA thực hiện các chức năng như ghi vào ổ cứng hoặc cho phép vi rút xâm nhập vào từ mạng.

  • Visual Basic

VISUAL BASIC là một môi trường lập trình được phát triển bởi Microsoft nhằm cung cấp cho những người lập trình một phương pháp phát triển các ứng dụng trên Windows nhanh và dễ nhất.

VISUAL BASIC cung cấp cho người lập trình một môi trường tích hợp, nơi mà người lập trình có thể sử dụng các công cụ để tạo ra giao diện người sử dụng một cách nhanh chóng và dễ dàng tạo ra mã để trả lời lại các tác động từ phái người sử dụng. VISUAL BASIC cung cấp cho người lập trình cả kỹ thuật lập trình hướng sự kiện và kỹ thuật lập trình hướng đối tượng.

Môi trường phát triển của VISUAL BASIC có những công cụ soạn thảo và gỡ rối tinh vi, nó cho phép người lập trình gắn mã với giao diện một cách nhanh chóng cho mỗi sự kiện.

VISUAL BASIC cung cấp cho bạn một giao diện nhanh nhất nhưng bù lại bạn phải cũng phải trả giá về tốc độ. Do vậy nếu yêu cầu bài toán cần đến tốc độ thì bạn nên dùng C+.

  • Ngôn ngữ lập trình C/C++

Ngôn ngữ C được phát triển từ ngôn ngữ B trên máy UNIX. Đến nay ANSI ban hành chuẩn về C. Cũng giống như PASCAL, C là ngôn ngữ lập trình có cấu trúc. Nhưng nói chặt chẽ về mặt kỹ thuật thì C không phải là ngôn ngữ lập trình có câud trúc chính cống vì trong C không cho phép các khối **********g nhau (chẳng hạn bạn không thể khai báo hàm này trong hàm khác).

C là ngôn ngữ cấp trung vì nó cho phép thao tác trên các bit, byte, và địa chỉ. C kết hợp các yếu tố mềm dẻo của ngôn ngữ bậc cao và khả năng điều khiển mạnh của ASSEMBLER. Do vậy, C tỏ ra thích hợp với lập trình hệ thống.

Chương trình viết bằng C là tập hợp các hàm riêng biệt, giúp cho việc che giấu mã và giữ liệu trở nên dễ dàng. Hàm được viết bởi những người lập trình khác nhau không ảnh hưởng đến nhau và có thể được biên dịch riêng biệt trước khi ráp nối thành chương trình.

So với PASCAL thì C thoáng hơn, chẳng hạn C không kiểm tra kiểu khi chay, điều này do người lập trình đảm nhiệm.

C tỏ ra ít gắn bó hơn so với các ngôn ngữ bậc cao, nhưng C lại thực tế hơn so với các ngôn ngữ khác.

Một đặc điểm nổi bật của C là C có tính tương thích cao. Chương trình viết bằng C cho một loại máy hoặc hệ điều hành này có thể chuyển dễ dàng sang loại máy hoặc hệ điều hành khác. Hiện nay hầu hết các loại máy tính đều có trình biên dịch C.Một chương trình được viết bằng C sẽ cõ tối ưu, chạy với tốc độ cao và tiết kiệm bộ nhớ.Tuy vậy, C chỉ thích hợp với những chương trình hệ thống hoặc những chương trình đòi hỏi tốc độ. Còn nếu bài toán lớ và phức tạp thì cũng như PASCAL, C cũng rất khó kiểm soát chương trình.

Ngôn ngữ lập trình C là một ngôn ngữ mệnh lệnh được phát triển từ đầu thập niên 1970 bởi Ken Thompson và Dennis Ritchie để dùng trong hệ điều hành UNIX. Từ dó, ngôn ngữ này đã lan rộng ra nhiều hệ điều hành khác và trở thành một những ngôn ngữ phổ dụng nhất. C là ngôn ngữ rất có hiệu quả và được ưa chuộng nhất để viết các phần mềm hệ thống, mặc dù nó cũng được dùng cho việc viết các ứng dụng. Ngoài ra, C cũng thường được dùng làm phương tiện giảng dạy trong khoa học máy tính mặc dù ngôn ngữ này không dược thiết kế dành cho người nhập môn.

C là một ngôn ngữ lập trình tương đối nhỏ gọn vận hành gần với phần cứng và nó giống với ngôn ngữ Assembler hơn hầu hết các ngôn ngữ bậc cao. Hơn thế, C đôi khi được đánh giá như là "có khả năng di động", cho thấy sự khác nhau quan trọng giữa nó với ngôn ngữ bậc thấp như là Assembler, đó là việc mã C có thể được dịch và thi hành trong hầu hết các máy tính, hơn hẳn các ngôn ngữ hiện tại trong khi đó thì Assembler chỉ có thể chạy trong một số máy tính đặc biệt. Vì lý do này C được xem là ngôn ngữ bậc trung.

Những trình dịch về C ngày nay thương được cung cấp kèm chung với C++ và ngay cả trình dịch cho ngôn ngữ Assmebly. Những sản phẩm trình dịch được bán phổ biến trên thị trường cũng thường cung cấp thêm nhiều công cụ trợ giúp cho người lập trình như là IDE, debuger, ...

0