Vài vấn đề cơ bản khi học lập trình .NET

Bài viết này mô tả vài khía cạnh, vài khái niệm quan trọng cho những người bắt đầu học ngôn ngữ lập trình .NET như C#, VB, v.v. Có thể hình dung bài viết như một tấm bản đồ đơn giản để người học có thể hình dung sơ lượt về những vấn đề cơ bản mà mình sẽ gặp khi học một ngôn ngữ lập trình .NET cụ thể.

Multiprocessing

Multitasking (đa nhiệm vụ)

Mutitasking là khả năng thực hiện nhiều nhiệm vụ nhưng chỉ một nhiệm vụ tại một thời điểm và các nhiệm vụ khác phải dừng để chờ nhiệm vụ này hoàn tất. Hệ điều hành chuyển các nhiệm vụ với tốc độ rất nhanh làm người dùng có cảm giác các nhiệm vụ này được thực hiện đồng thời.

Multiprocessing (đa tiến trình)

Tiến trình (process) hay nhiệm vụ (task) có thể được hiểu giống nhau, nhưng trong hệ thống dùng đa tiến trình thì nhiều nhiệm vụ hay tiến trình được xử lý tại cùng thời điểm hay đồng thời. Ngày nay, với sự phát triển của các bộ xử lý đa lõi (multicore) tức nhiều lõi trên cùng một bộ xử lý đã hỗ trợ sức mạnh máy tính thực hiện đa tiến trình hiệu quả hơn.

Multithreading (đa tiểu trình)

Một tiến trình (process) là một thể hiện (instance) của một chương trình, như vậy một chương trình có thể có nhiều tiến trình ví dụ có thể mở đồng thời nhiều cửa sổ Notepad hay trình duyệt web. Một tiểu trình (thread) là các lệnh thực thi trong một tiến trình và có thể thực hiện song song với các tiểu trình (hay các lệnh) khác. Thỉnh thoảng chúng ta cần thực hiện nhiều tiểu trình đồng thời trong cùng một tiến trình, mỗi tiểu trình có thể dùng mã chương trình mà không ảnh hưởng đến tiểu trình khác. Cơ chế này được gọi là đa tiểu trình.

Các vấn đề với cơ chế song song (paralleism)

Khi thực hiện nhiều tiểu trình song song, chúng ta có thể bắt gặp các vấn đề như tranh chấp tài nguyên (contention for resources), điều kiện tương tranh (race conditions), và khoá chết (deadlock).

Tranh chấp tài nguyên

Khi thực hiện song song, thỉnh thoảng các tiểu trình cần sử dụng chung tài nguyên như cùng truy cập đến ổ đĩa cứng, CD hay DVD, hay các tài nguyên khác. Vấn đề tranh chấp tài nguyên có thể dẫn tới nhiều ứng xử không như mong đợi, ví dụ như vấn đề điều kiện tương tranh.

Điều kiện tương tranh

Trong quá trình thực hiện song song, khi kết quả tính toán phụ thuộc vào việc tính toán của nhiều tiểu trình thì xuất hiện điều kiện tương tranh.

Ví dụ chúng ta muốn tính tổng của 2 triệu số. Chúng ta có thể lặp qua các số và cộng dồn mỗi số một lần, hay để tiết kiệm thời gian chúng ta dùng cơ chế đa tiểu trình bằng cách tách thành hai tiểu trình – mỗi tiểu trình tính tổng 1 triệu số – thực hiện song song. Thuật toán của mỗi tiểu trình như sau:

1
2
3
4
5
6
7
For i = start To finish
 
Get total
 
Calculate result = total + value[i]
 
Save result In total

Hai tiểu trình có cùng thuật toán chỉ khác giá trị khởi đầu start và giá trị kết thúc finish cho vòng lặp for. Tiểu trình đầu có start =1 và finish = 1000000, tiểu trình thứ hai có start = 1000001 và finish = 2000000.

Nếu hai tiểu trình (tạm gọi là Thread 1 và Thread 2) thực hiện tại cùng một thời điểm thì sẽ xuất hiện điều kiện tương tranh. Ví dụ:

1
2
3
4
5
6
7
8
9
10
11
Thread 1:    Get total  (1)
 
Thread 2:    Get total  (2)
 
Thread 1:    Calculate result = total + value[i]   (3)
 
Thread 1:    Save result In total  (4)
 
Thread 2:    Calculate result = total + value[i]   (5)
 
Thread 2:    Save result In total (6)

Với cách hoạt động của hai tiểu trình như trên, giả sử ban đầu tổng total là 100 và qua hai lệnh (1) và (2) thì cả hai tiểu trình đều nhận cùng giá trị total là 100. Giả sử tiểu trình Thread 1 muốn cộng thêm 20 và tiểu trình Thread 2 muốn cộng thêm 30 vào total. Với lệnh (3) và (4), Thread 1 cộng 20 vào total và lưu kết quả thành 120. Kế tiếp, Thread 2 với total ban đầu là 100 sẽ cộng thêm 30 và lưu kết quả  là 130 thay vì 150 như mong đợi.

Một cách để ngăn chặn điều kiện tương tranh là dùng khoá (lock).

Khoá (lock)

Dùng khoá để đảm bảo một tiểu trình truy cập độc quyền đến mã, bộ nhớ, hay các tài nguyên khác nhằm ngăn chặn điều kiện tương tranh hay lỗi truy cập. Trong ví dụ trên, chúng ta có thể dùng khoá để truy cập độc quyền đến biến total trong khi tính toán. Đoạn mã trên có thể viết lại:

1
2
3
4
5
6
7
8
9
For i = start To finish
 
Lock total
 
Get total
 
Calculate result = total + value[i]
 
Save result In total

Bây giờ, nếu Thread 1 đang dùng total thì Thread 2 không thể dùng nó và phải chờ cho đến khi Thread 1 giải phóng khoá.

Tuy nhiên, dùng khoá có thể làm cho chương trình chậm hơn do phụ thuộc vào thời gian giải phóng của các tiểu trình và có thể dẫn đến tình huống không như mong đợi – tình huống khoá chết (deadlock).

Khoá chết (deadlock)

Khoá chết xuất hiện khi cả hai tiểu trình cùng chờ tài nguyên bị chiếm giữ bởi mỗi bên,ví dụ Thread 1 chiếm giữ tài nguyên A (bị khoá) và chờ tài nguyên B, và Thread 2 chiếm giữ tài nguyên B (bị khoá) và chờ tài nguyên A.

Việc phát hiện và phá vỡ khoá chết là khó khăn trong cơ chế đa tiểu trình.

Task Parallel Library

Microsoft cung cấp một thư viện (Task Parallel Library hay gọi tắt là TPL) các công cụ để tạo các tiểu trình chạy song song dùng trong các ứng dụng .NET.

Một vài công cụ chính được cung cấp bởi TPL:

  • Invoke: thực hiện vài đoạn mã đồng thời.
  • For: thực hiện cùng một đoạn mã với số các tham số khác nhau vài lần theo cơ chế song song.
  • ForEach: thực hiện cùng một đoạn mã với số các tham số khác nhau vài lần theo cơ chế song song.

Môi trường lập trình

Từ phần mềm (software) đến phần cứng (hardware)

Bộ xử lý máy tính chỉ hiểu được các bit (0 hay 1). Việc viết bằng ngôn ngữ máy (dùng bit 0 hay 1) là rất khó khăn cho con người nên các nhà lập trình đã dùng các ngôn ngữ cấp cao để viết chương trình. Ngôn đầu tiên được phát triển là ngôn ngữ Assembly dễ đọc hơn với con người, ví dụ đoạn mã sao chép giá trị 61h vào thanh ghi AL như sau:

1
MOV AL, 61h

Một chương trình gọi là assembler sẽ chuyển đoạn mã trên thành ngôn ngữ máy (tức các bit 0 hay 1) để bộ xử lý máy tính có thể thực hiện lệnh.

Mặc dù dễ đọc hơn ngôn ngữ máy nhưng ngôn ngữ Assembly vẫn còn khó để viết hay sửa lỗi chương trình.

Các ngôn ngữ cấp cao như Fortran, Pascal, C++ được phát triển với các câu lệnh phức tạp làm việc ở mức trừu tượng cao hơn so với ngôn ngữ Assembly. Một trình biên dịch (compiler) được dùng để chuyển chương trình mức cao sang ngôn ngữ máy để thực thi như hình minh hoạ sau:

Một vài ngôn ngữ như Java, C#, hay Visual Basic, thêm một bước khác vào trong quá trình chuyển sang ngôn ngữ máy để tăng tính di động (portable) cho chương trình. Thay vì biên dịch trực tiếp đến ngôn ngữ máy, mã chương trình được chuyển thành ngôn ngữ trung gian, thỉnh thoảng được gọi là bytecode. Sau đó, tại thời điểm chạy chương trình (run time), mã trung gian sẽ được biên dịch thành mã máy để thực thi. Bước chuyển từ mã trung gian đến mã máy còn được gọi là biên dịch Just – in – time (JIT).

Đến thời điểm này chúng ta cần phân biệt 3 khái niệm quan trọng:

  • Run time: thời điểm chương trình đang chạy.
  • Design time: thời điểm thiết kế hay xây dựng chương trình (viết mã, thiết kế giao diện, v.v.).
  • Biên dịch Just –in-time: bước chuyển từ mã trung gian đến mã máy.

Trong các ngôn ngữ .NET như C# hay VB, ngôn ngữ trung gian được gọi là Common Intermediate Language (CIL) và thành phần chuyển ngôn ngữ trung gian sang ngôn ngữ máy được gọi là Common Language Runtime (CLR).

Trong Java, ngôn ngữ trung gian gọi là Java bytecode và thành phần chuyển ngôn ngữ trung gian sang ngôn ngữ máy gọi là Java Virtual Machine (JVM).

Hình ảnh minh hoạ chuyển mã từ ngôn ngữ cấp cao (Java, C# hay VB) sang ngôn ngữ trung gian và cuối cùng là ngôn ngữ máy:

Việc chuyển thành ngôn ngữ trung gian để tăng tính động cho chương trình vì các chương trình có thể chuyển từ máy này sang máy khác miễn là các máy đó có cài chương trình trung gian như JVM hay CLR.

Môi trường lập trình

Để chương trình có thể được viết, kiểm tra, hay sửa lỗi dễ dàng, cần một môi trường lập trình chứa nhiều công cụ hữu ích còn được gọi là Môi trường phát triển tích hợp (Integrated Development Environment – IDE) như:

  • Code Editor: dùng để soạn thảo mã chương trình.
  • Debugger: dùng để phát hiện, chỉnh sửa lỗi chương trình.
  • Compiler: biên dịch chương trình thành ngôn ngữ trung gian hay máy.
  • Build automation tools: cho phép biên dịch tuỳ chọn.
  • Testing tools: kiểm tra chương trình.
  • Source code management tools: quản lý mã chương trình.
  • Object – oriented tools: tổ chức các lớp để dễ hiểu, dễ quản lý hơn.

Visual Studio

Visual Studio là IDE của Microsoft hỗ trợ các ngôn ngữ như C#, Visual Basic, C/C++, F#, v.v. Một vài đặc trưng cơ bản được cung cấp bởi Visual Studio IDE:

  • Customizable menus and toolbars :các thực đơn và thanh công cụ tuỳ chọn.
  • Customizable windows: các cửa sổ tuỳ chọn.
  • Auto hiding windows: các cửa sổ ẩn tự động.
  • IntelliSense: hỗ trợ cho viết mã chương trình, dùng để phân biệt hoa thường ví dụ first và First là khác nhau.
  • Call stack: hiển thị một loạt các hàm gọi để dẫn đến điểm thực thi hiện tại.
  • Sequence diagrams and dependency graphs: cung cấp trong các phiên bản Pro của Visual Studio dùng để cung cấp thông tin về cách các hàm gọi các hàm khác.

Các thành phần của chương trình Windows

Thực đơn (menu)

Một trong những thành phần quan trọng nhất trong một chương trình Windows là các thực đơn (menu). Một vài khía cạnh quan trọng:

Các phím kết hợp (accelerators): là các phím kết hợp giữa các phím điều khiển như Alt, Ctrl, v.v. dùng để điều hướng đến các mục thực đơn nhanh hơn, ví dụ tổ hợp phím Alt + F để điều hướng đến File.

Các phím tắt (shortcut): là các phím tắt thực hiện ngay một lệnh của một mục thực đơn nào đó. Bởi vì một shortcut thực hiện trực tiếp một lệnh nên không có hai lệnh nào có cùng một shortcut. Các phím điều khiển có thể dùng trong shortcut là Alt, Shift, và Ctrl.

Các mục thực đơn chuẩn: thường thấy trong trình soạn thảo Word, Notepad, v.v. như File, New, Open, Save, Save As, v.v.

Một vài nguyên tắc khi thiết kế thực đơn:

  • Không nên ẩn các lệnh không cần dùng mà nên vô hiệu hoá nó (hay làm mờ) để người dùng hiểu rằng nó không được dùng thời điểm này nhưng sẽ được dùng lúc khác. Ví dụ:

  • Hạn chế tối đa việc dùng thực đơn cấp thấp, tốt nhất là hai cấp, ví dụ Main > Sub1. Dùng thực đơn mức thấp chỉ khi thật sự cần thiết, ví dụ Main > Sub1 > Sub2. Một giải pháp thay vì dùng các mục thực đơn cấp thấp hơn thì chúng ta có thể dùng hộp thoại. Ví dụ thay vì Main > Sub1 > Sub2 > Sub3 thì khi đến Sub2 chúng ta gọi một hộp thoại chứa chức năng của Sub3.

Thực đơn ngữ cảnh (context menu): hay thỉnh thoảng gọi là thực đơn pop-up xuất hiện khi người dùng kích chuột phải lên một đối tượng trong giao diện người dùng.

Thanh công cụ (toolbar) và ribbon

Thanh công cụ (toolbar) chứa hầu hết các lệnh để người dùng có thể sử dụng mà không cần dùng thực đơn hay thực đơn ngữ cảnh.  Ví dụ thanh Toolbox trong Visual Studio chứa các điều khiển có thể đặt vào Form:

Ribbon (có thể thấy kể từ MS Office 2007) là một khái niệm kết hợp giữa thanh thực đơn (menu) và thanh công cụ như hình dưới đây:

Các tabs FileHomeInsert, v.v. được xem như các mục thực đơn, và khi chọn mỗi tab sẽ hiển thị các chức năng bên trong như trên thanh công cụ.

Hộp thoại (dialog box)

Một hộp thoại là một form dùng để hiển thị thông báo đến người dùng hay dùng để thu thập thông tin từ người dùng. Có hai kiểu hộp thoại là modal và modeless.

Hộp thoại modal chỉ tập trung vào ứng dụng và không cho phép tương tác với các phần khác cho đến khi thoát khỏi hộp thoại. Ví dụ khi chọn Open trong Word để mở một tài liệu có sẵn sẽ xuất hiện hộp thoại Open và hộp thoại này sẽ chiếm toàn bộ quyền ưu tiên tức không cho phép tương tác các phần khác cho đến khi đóng hộp thoại Open.

Hộp thoại modeless, ngược với modal, cho phép người dùng tương tác các phần khác mà không cần phải đóng hộp thoại. Ví dụ chọn chứa năng Replace trong Word sẽ xuất hiện hộp thoại Find and Replace và chúng ta có thể tương tác các phần khác mà không cần đóng Find and Replace:

Tuỳ theo ứng dụng mà chúng ta thiết kế hộp thoại modal hay modeless.

Thiết kế giao diện người dùng (User Interface Design)

Thiết kế giao diện người dùng là một chủ đề phức tạp không thể đề cập ở đây nhưng có một vài nguyên tắc cơ bản cần chú ý khi thiết kế giao diện:

Thứ tự các điều khiển

Các điều khiển (controls) được sắp xếp theo thứ tự phù hợp, thông thường ưu tiên từ trên xuống (top – bottom) và từ trái sang phải (left – right). Như vậy, các điều khiển quan trọng nhất sẽ được bố trí góc trái trên và các trường hay các ô để người dùng đọc hay nhập thông tin đặt ở dưới và bên phải.

Tuỳ theo ứng dụng, thứ tự các điều khiển phải được sắp xếp sao cho thuận tiện nhất cho người dùng.

Nhóm các điều khiển liên quan

Các điều khiển có liên quan với nhau cần phải được gộp vào một nhóm. Điều này giúp người dùng hiểu và điền chính xác thông tin hơn.Trong thanh Toolbox của Visual Studio có hỗ trợ điều khiển GroupBox để gộp các điều khiển liên quan. Ví dụ như Form sau gồm các nhóm điều khiển Login, Address, Other Contact Information, và Account:

Nhìn vào Form trên dễ thấy nhóm điều khiển quan trọng nhất là nhóm Login, nằm góc trái trên và được làm nổi bật với màu nền sáng. Những button như OK hay Cancel là những lựa chọn cuối cùng nên được bố trí góc dưới phải (hay nói cách khác các thông tin không quan trọng càng lệch về phía dưới bên phải).

Luật số 7

Người dùng chỉ có thể nhớ được tối đa 7 lựa chọn tại cùng một thời điểm, do đó, khi thiết kế giao diện cần cung cấp không quá 7 tuỳ chọn cho người dùng.

Hợp lệ dữ liệu và cung cấp các gợi ý cho người dùng

Cần kiểm soát dữ liệu người dùng một cách cẩn thận và cung cấp các gợi ý hay hướng dẫn cho người dùng trong trường hợp họ nhập sai hay thiếu thông tin.

Các điều khiển (controls)

Một chương trình Windows được tạo thành bởi các điều khiển như Label, button, textbox, v.v. Các điều khiển trong Windows có 3 đặc trưng cơ bản là:

  • Thuộc tính (properties): các yếu tố như màu sắc, kiểu chữ, kích cỡ chữ hay điều khiển, v.v. Hay nói cách khác, thuộc tính là các yếu tố làm cho điều khiển xuất hiện như thế nào.
  • Chức năng (methods): mỗi điều khiển khi xuất hiện trên giao diện người dùng luôn gắn liền với một chức năng nào đó.
  • Sự kiện (events): là cách thức để kích hoạt các điều khiển thực hiện chức năng của mình hay thực hiện một vài ứng xử nào đó.

Trong ứng dụng Windows, Microsoft cung cấp hai tập điều khiển, một được dùng cho các ứng dụng Windows Form và một dùng cho các ứng dụng WPF (Windows Presentation Foundation) và Silverlight. Ứng dụng Windows Form được triển khai từ những phiên bản .NET Framework đầu tiên; WPF được triển khai từ .NET Framework 3.0 giúp cho việc thiết kế giao diện đồ hoạ người dùng Windows trở nên hiệu quả hơn nhờ nhiều điều khiển mới với các tính năng đồ hoạ mới và tận dụng tối đa sức mạnh của các thiết bị đồ hoạ.

Biến (variables)

Biến là một khái niệm rất quan trọng trong lập trình nói chung và lập trình .NET nói riêng. Các vấn đề cơ bản khi làm việc với biến trong .NET:

Tên biến (variable name): biến có thể hiểu là một vùng nhớ. Mỗi vùng nhớ khi được bộ xử lý cấp phát sẽ có một kích thước và một địa chỉ. Để tiện cho việc lập trình hay quản lý biến, biến được khai báo cùng với tên biến.

Kiểu dữ liệu (data type): nếu biến là một vùng nhớ và có thể được quản lý bởi tên biến thì kiểu dữ liệu xác định kích cỡ vùng nhớ cũng như nội dung bên trong vùng nhớ đó.

  • Kiểu dữ liệu sơ cấp: .NET cung cấp hệ thống các kiểu dữ liệu chung CTS (Common Types System). Mỗi ngôn ngữ lập trình sẽ định nghĩa cho mình các kiểu dữ liệu và chúng tham chiếu đến kiểu dữ liệu chung trong CTS.
  • Kiểu dữ liệu cấu trúc hay kiểu do người dùng định nghĩa: array, enumeration, structure, class.
  • Kiểu tham chiếu, kiểu tham trị: một biến có kiểu tham trị (ví dụ kiểu int) khi nó chứa dữ liệu thực bên trong nó, và nó có kiểu tham chiếu (ví dụ kiểu string) khi nó chứa địa chỉ hay một tham chiếu đến vị trí khác, nơi chứa dữ liệu thực.

Chuyển kiểu (Type Conversion): một biến có một kiểu dữ liệu được khai báo trước nhưng nó có thể được chuyển sang kiểu khác. Trong .NET, kiểu dữ liệu có thể được chuyển đổi qua lại theo hai cách là chuyển đổi tường minh (explicit conversion) và chuyển đổi ngầm định (implicit conversion)Chuyển đổi tường minh dùng cú pháp hay phương thức (tương ứng với ngôn ngữ lập trình); chuyển đổi ngầm định được thực hiện tự động tuỳ theo tình huống cụ thể.

Phạm vi (scope) và chu kỳ sống: module, structure – class, routine, block.

Khả năng truy cập (Accessibility): public, private, protected, internal (hay Friend), protected internal (hay protected Friend).

Lệnh điều khiển

Xét ví dụ viết chương trình in ra màn hình các số tự nhiên liên tiếp, các số tự nhiên chẵn, các số tự nhiên lẻ từ 1 đến 1000. Giải pháp thông thường là viết 1000 lần lệnh in các số ra màn hình, 500 lần các lệnh in số chẵn, và 500 lần các lệnh in số lẻ. Đây là giải pháp tồi. May mắn là, trong hầu hết các ngôn ngữ lập trình đều có các câu lệnh điều khiển. Các lệnh điều khiển có thể là các lệnh lặp hay các lệnh điều kiện. Ở ví dụ trên chúng ta có thể dùng lệnh lặp để tính tổng từ 1 đến 1000 và dùng lệnh lặp kết hợp với lệnh điều kiện để kiểm tra tính chẵn, lẻ và tính tổng các số chẵn và số lẻ từ 1 đến 1000.

Các ngôn ngữ .NET cung cấp các lệnh lặp sau:

  • For: lặp qua một loạt các bước với số lần lặp biết trước.
  • For Each: lặp qua các đối tượng trong một danh sách cho trước (ví dụ mảng).
  • Do While: thực hiện lặp chừng nào điều kiện còn đúng và thực hiện lệnh ít nhất một lần (để phân biệt với While).
  • While: thực hiện lặp chừng nào điều kiện còn đúng.
  • Until: là dạng khác của While hay Do While.

Các ngôn ngữ .NET cung cấp các lệnh điều kiện sau:

  • IF: thực hiện lệnh nếu điều kiện là đúng.
  • IF ELSE: thực hiện khối lệnh A nếu điều kiện là đúng, ngược lại thực hiện khối lệnh B.
  • ELSE IF: dùng trong trường hợp cần kiểm tra nhiều điều kiện (từ 3 trở lên).
  • CASE: đưa ra nhiều trường hợp và lệnh sẽ thực thi nếu một trong các trường hợp thoả.

Các ngôn ngữ .NET cung cấp các lệnh nhảy: là thực hiện nhảy từ khối lệnh này đến khối lệnh khác nếu thoả một điều kiện nào đó. Các lệnh nhảy:

  • GO TO: nhảy ngay lập tức đến một dòng lệnh nào đó nếu thoả điều kiện.
  • CONTINUE: bỏ qua một đoạn mã trong lệnh lặp và thực hiện lệnh lặp kế tiếp.
  • EXIT: ngừng và thoát khỏi vòng lặp, thực hiện lệnh kế tiếp (sau khối lệnh lặp).
  • RETURN: thoát chương trình.

Bắt lỗi: các ngôn ngữ .NET cung cấp khối lệnh Try Catch để bắt lỗi.

Toán tử (operator)

Toán tử (operator) là một kí hiệu (symbol) mà chương trình dùng để nói với máy tính cách kết hợp các giá trị để tạo ra một kết quả. Các giá trị được kết hợp bởi toán tử để cho ra một kết quả gọi là các toán hạng (operand). Ví dụ 3 + 2 = 5 thì 3, 2 là các toán hạng, + là toán tử, và 5 là kết quả.

Các ngôn ngữ .NET (VB, C#, v.v.) cung cấp các toán tử phổ biến (như hầu hết các ngôn ngữ lập trình cấp cao khác) như toán tử gán, toán tử số học, toán tử luận lý, v.v. tuy nhiên cần chú ý một vài khía cạnh quan trọng:

  • Độ ưu tiên giữa các toán tử: khi kết hợp các toán tử thì độ ưu tiên (thực hiện trước hay sau) của các toán tử là quan trọng.
  • Các ngôn ngữ .NET có khả năng quá tải toán tử (operator overloading) tức là cho phép toán tử kết hợp các toán hạng có những kiểu dữ liệu khác với kiểu dữ liệu mà toán tử được định nghĩa ban đầu trong ngôn ngữ. Ví dụ toán tử + ban đầu chỉ cho phép cộng hai toán hạng kiểu số nhưng ta có thể quá tải lại toán tử + cho phép cộng hai toán hạng có kiểu đối tượng bất kỳ.

Routine

Routine hay còn gọi là chương trình con (subprogram), thủ tục (procedure), hàm (function), hay phương thức (method). Routine là một khối lệnh có thể được gọi bởi một hay nhiều lệnh khác. Tiện ích của routine:

  • Giảm việc lặp lại các đoạn mã
  • Dùng lại các đoạn mã
  • Làm cho chương trình trở nên đơn giản hơn
  • Ẩn dấu các chi tiết phức tạp (đóng gói)
  • Dễ dàng trong làm việc nhóm (chia sẻ thông tin)
  • Dễ dàng kiểm tra phát hiện lỗi

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

Theo cách nhìn của các ngôn ngữ lập trình hiện đại (như C#, VB, Java), một chương trình chỉ là một nhóm các đối tượng tương tác với nhau để thực hiện một nhiệm vụ nào đó. Các khái niệm quan trọng trong lập trình hướng đối tượng là:

Lớp (class): là một kiểu dữ liệu đặc biệt. Lớp chứa các thành phần chính (hay còn gọi là các thành viên – members) gồm các thuộc tính (properties)các phương thức (methods), và các sự kiện (events). Các tiện ích của lớp:

  • Tính đóng gói (encapsulation): khả năng ẩn dấu thông tin.
  • Tính thừa kế (inheritance): khả năng tái sử dụng các đoạn mã.
  • Tính đa hình (polymorphism): cho phép chương trình xem một lớp như là lớp cha mà nó thừa kế. Tính đa hình cũng cho phép khả năng tái sử dụng các đoạn mã.

Đối tượng (object) hay thể hiện (instance): sau khi tạo lớp chúng ta có thể dùng lớp bằng cách tạo ra các đối tượng hay thể hiện. Như vậy, từ một lớp có thể tạo ra nhiều đối tượng hay thể hiện.

Các thành viên của lớp:

  • Sẽ được áp dụng đến mỗi đối tượng hay thể hiện. Ví dụ lớp SINHVIEN có phương thức thongbaodiem() dùng để thông báo điểm đến từng sinh viên cụ thể. Nhưng trong một vài trường hợp có thể cho phép chia sẻ các thành viên giữa các thể hiện.
  • Quá tải các thành viên (overriding members): là khả năng cho phép lớp con tạo ra các phiên bản mới (hay quá tải) cho các thành viên được thừa kế từ lớp cha bằng cách giữ nguyên tên thành viên (chính xác gọi là signature). Ví dụ lớp con thừa kế phương thức thongbaodiem() từ lớp SINHVIEN và tạo ra phiên bản mới cho phương thức này bằng cách vẫn giữ nguyên tên phương thức và thay đổi danh sách tham số của phương thức hay thay đổi nội dung bên trong.
  • Bóng các thành viên (shadow member): các thành viên ở lớp con có thể là bóng của các thành viên ở lớp cha nghĩa là chúng có cùng tên (và cả tham số ) nhưng một biến của lớp cha tham chiếu đến một đối tượng của lớp con sẽ không dùng được các thành viên này.

Interface: các ngôn ngữ .NET không cho phép đa thừa kế nhưng hỗ trợ interface.

Phương thức constructor và destructor: là hai phương thức quan trọng trong chu kỳ sống của một đối tượng. Phương thức constructor được tạo một cách tự động khi một thể hiện mới của một lớp được tạo và khi một đối tượng bị huỷ thì phương thức destructor được gọi.

Garbage Collection: khi một chương trình tạo ra một đối tượng và sau đó giải phóng các biến trỏ đến nó (đối tượng), chương trình sẽ mất khả năng tham chiếu đến vùng nhớ mà đối tượng chiếm giữ và không thể dùng lại vùng nhớ này. Garbage Collection (GC) là chức năng cho phép phục hồi các vùng nhớ đã mất để chương trình có thể sử dụng.

IDisposable: là một interface cho phép chúng ta giải phóng tài nguyên (chủ động thay vì ngồi chờ GC) bằng cách thực hiện phương thức Dispose.

Các vấn đề khác

Khi lập trình .NET, chúng ta cần chú ý một số vấn đề khác bên cạnh các vấn đề đã đề cập ở trên như sau:

Chú thích (comment): rất quan trọng cho chính người lập trình cũng như người khác (cùng nhóm làm việc hay những người muốn xem mã chương trình, v.v.). NET hỗ trợ chú thích XML có nhiều tiện ích rất tuyệt vời.

Quy ước tên: tên biến, tên routine, tên lớp, v.v. phải được đặt theo quy ước để giúp cho việc xây dựng chương trình được tiện lợi hơn.

Các kĩ thuật phát triển:

  • Hướng dữ liệu (Data centric Viewpoint)
  • Hướng người dùng (User centric Viewport)
  • Phương pháp Agile (Agile Development)
  • Hướng kiểm tra (Test driven development)

Vấn đề toàn cầu hoá (globalization)

Ngày nay với sự phát triển mạnh mẽ của Internet, việc phát triển các ứng dụng không còn mang tính địa phương hay quốc gia, mà phải tương thích với nhiều địa phương, quốc gia trên thế giới. Microsoft cung cấp nhiều công cụ giúp người lập trình dễ dàng thay đổi ngôn ngữ, định dạng, thời gian, các quy ước, v.v. để phát triển các ứng dụng tương thích với môi trường toàn cầu hoá.

Lưu trữ dữ liệu (data storage)

Có nhiều hình thức lưu trữ, phổ biến nhất:

  • Tập tin (file): tập tin văn bản, tập tin truy cập ngẫu nhiên, tập tin XML, tập tin INI, tập tin cấu hình (config).
  • Hệ thống registry
  • Cơ sở dữ liệu : cơ sở dữ liệu quan hệ, mạng, hướng đối tượng, v.v.

Thư viện .NET (.NET libraries)

.NET Framework cung cấp các thư viện chứa nhiều công cụ hữu ích phục vụ việc phát triển ứng dụng, cụ thể là các thư viện .NET chứa một số lượng lớn các lớp (hàng ngàn) phục vụ cho nhiều nhu cầu khác nhau và chúng được chứa trong các không gian tên hay namspaces. Có hai dạng namespaces:

  • Microsoft namspaces:
    • Csharp
    • VisualBasic
    • Win32
    • Windows.Themes
  • System namespaces: gồm một tập các namspaces như System, System.CodeDom, v.v.

Trên đây là những khía cạnh cơ bản và quan trọng nhất mà chúng ta sẽ gặp khi bắt đầu học một ngôn ngữ .NET cụ thể như C# hay VB. Ngoài ra, mỗi ngôn ngữ còn nhiều tính năng, dịch vụ, công cụ, v.v. cung cấp đến người học cũng như người phát triển. Tìm hiểu sâu sắc hơn có thể truy cập thư viện MSDN của Microsoft.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *