Thiết lập Mono Develop để phát triển Desktop và Web Applications bằng ngôn ngữ C# trên CentOS 7

Giới thiệu

MonoDevelop (https://www.monodevelop.com/) là một open-source GNOME IDE (intergrated development environment) hỗ trợ lập trình đa ngôn ngữ (với mục tiêu ban đầu là .Net) trên các hệ điều hành Linux, Mac OS X và Windows.

Phiên bản hiện tại 7.6 (7.6.9.22) ra mắt vào đầu 2019.

Với giao diện tương tự Visual Studio, chúng ta có thể nhanh chóng làm quen và phát triển các dự án .Net trên những platform khác nhau.

Những chức năng chính

  • Multi-platform: Supports Linux, Windows and macOS.
  • Advanced Text Editing: Code completion support for C#, code templates, code folding.
  • Configurable workbench: Fully customizable window layouts, user defined key bindings, external tools.
  • Multiple language support: C#, F#, Visual Basic .NET, Vala.
  • Integrated Debugger: For debugging Mono and native applications.
  • GTK# Visual Designer: Easily build GTK# applications.
  • ASP.NET: Create web projects with full code completion support and test on XSP, the Mono web server.
  • Other tools: Source control, makefile integration, unit testing, packaging and deployment, localization.

Cài đặt MonoDevelop trên CentOS 7

Bước 1.

Chúng ta khởi động chương trình Terminal.

Chúng ta nhập chuỗi sau để cập nhật KEY vào CentOS 7:

sudo rpm --import "http://keyserver.ubuntu.com/pks/lookup? op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF"

Bước 2.

Chúng ta nhập mật khẩu của tài khoản hiện tại:

Bước 3.

Chúng ta thực hiện cài đặt repository tương ứng bằng chuỗi lệnh:

su -c 'curl https://download.mono-project.com/repo/centos7-vs.repo | tee /etc/yum.repos.d/mono-centos7-vs.repo'

Chúng ta lựa chọn phím Enter để thực hiện.

Bước 4.

Chúng ta nhập mật khẩu của tài khoản root.

Chúng ta lựa chọn phím Enter để thực hiện.

Bước 5.

Chúng ta thực hiện cài đặt MonoDevelop với chuỗi lệnh:

sudo yum install monodevelop

Chúng ta nhấn phím Enter để thực hiện.

Bước 6.

Hệ thống thực hiện lựa chọn gói sẽ download.

Bước 7.

Hệ thống yêu cầu chúng ta lựa chọn phím chứa ký tự y để đồng ý download những gói cài đặt.

Chúng ta lựa chọn phím Enter để tiếp tục.

Bước 8.

Hệ thống tiến hành download MonoDevelop.

Bước 9.

Hệ thống tiến hành cài đặt MonoDevelop.

Bước 10.

Hệ thống hoàn thành tiến trình cài đặt MonoDevelop.

Bước 11.

Chúng ta chọn chức năng Show Applications ở phía dưới cùng trên thanh Toolbars bên trái màn hình.

Chúng ta nhập chuỗi mono để lựa chọn ứng dụng MonoDevelop.

Bước 12.

Màn hình giao diện chính của MonoDevelop hiện ra:

Tổng kết

Trong bài này chúng ta đã cùng nhau thực hiện cài đặt MonoDevelop để phát triển Desktop và Web Applications bằng ngôn ngữ C# trên CentOS 7.

Thiết lập môi trường lập trình C# – Cài đặt dotNet Core trên CentOS 7

Giới thiệu

Trong bài này chúng ta cùng tìm hiểu việc cài đặt dotNet Core 3.1 trên Hệ điều hành CentOS 7.

dotNet là gì

.NET là một nền tảng phát triển mã nguồn mở, đa nền tảng, miễn phí để xây dựng nhiều loại ứng dụng khác nhau.

Với .NET, chúng ta có thể sử dụng nhiều ngôn ngữ, trình soạn thảo và thư viện để xây dựng cho web, thiết bị di động, máy tính để bàn, chơi game và IoT.

Cho dù chúng ta đang làm việc với ngôn ngữ C#, F# hoặc Visual Basic, mã nguồn sẽ chạy tự nhiên trên mọi hệ điều hành tương thích. Những triển khai .NET khác nhau xử lý các tác vụ nặng cho chúng ta:

  • .NET Core là một triển khai .NET đa nền tảng cho các trang web, máy chủ và ứng dụng bảng điều khiển trên Linux, Windows và macOS.
  • .NET Framework hỗ trợ các trang web, dịch vụ, ứng dụng máy tính để bàn và nhiều hơn nữa trên Windows.
  • Xamarin / Mono là một triển khai .NET để chạy các ứng dụng trên tất cả các hệ điều hành di động chính.

dotNet Core

.NET Core có các đặc điểm sau:

  • Đa nền tảng: Chạy trên các hệ điều hành Windows, macOS và Linux.
  • Nhất quán trên các kiến trúc: Chạy mã nguồn với cùng một hành vi trên nhiều kiến trúc, bao gồm x64, x86 và ARM.
  • Các công cụ dòng lệnh: Bao gồm các công cụ dòng lệnh dễ sử dụng có thể được sử dụng để phát triển cục bộ và trong các tình huống tích hợp liên tục.
  • Triển khai linh hoạt: Có thể được bao gồm trong ứng dụng riêng hoặc được cài đặt song song (cài đặt toàn người dùng hoặc toàn hệ thống).
  • Tương thích: .NET Core tương thích với .NET Framework, Xamarin và Mono, thông qua .NET Standard.
  • Nguồn mở: Nền tảng .NET Core là nguồn mở, sử dụng giấy phép MIT và Apache 2. .NET Core là một dự án .NET Foundation.
  • Được hỗ trợ bởi Microsoft: .NET Core được Microsoft hỗ trợ, theo Hỗ trợ .NET Core.

Các bước cài đặt dotNet Core 3.1 trên CentOS 7

Bước 1.

Chúng ta mở ứng dụng Terminal.

Trước khi cài đặt .NET, chúng ta sẽ cần phải đăng ký khóa Microsoft, đăng ký kho sản phẩm và cài đặt các phụ thuộc cần thiết.

Điều này chỉ cần được thực hiện một lần trên mỗi máy.

Chúng ta thực hiện công việc trên với chuỗi lệnh:

sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm

Chúng ta lựa chọn phím Enter để tiếp tục.

Bước 2.

Chúng ta nhập mật khẩu của tài khoản hiện tại để thực hiện.

Bước 3.

Chúng ta chuỗi lệnh để thực hiện download và cài đặt .NET Core 3.1:

sudo yum install dotnet-sdk-3.1

Chúng ta lựa chọn phím Enter để tiếp tục.

Bước 4.

Hệ thống tiến hành xác định các gói sẽ cài đặt.

Bước 5.

Hệ thống yêu cầu chúng ta nhập ký tự y để đồng ý download các gói cài đặt .NET Core 3.1:

Bước 6.

Hệ thống tiến hành download các gói cài đặt.

Bước 7.

Hệ thống yêu cầu chúng ta nhập ký tự y để đồng ý tích hợp Microsoft KEY.

Bước 8.

Hệ thống tiến hành cài đặt các gói đã được download.

Bước 9.

Hệ thống đã cài đặt xong các gói cần thiết.

Chúng ta kiểm tra tiếp theo bằng việc thử cài đặt ASP.NET Core runtime:

sudo yum install aspnetcore-runtime-3.1

Chúng ta lựa chọn phím Enter để tiếp tục.

Bước 10.

Hệ thống nhận thấy chúng ta đã cài đặt đầy đủ ASP.NET Core runtime.

Chúng ta tiếp tục kiểm tra bằng cách cài đặt .NET Core runtime:

sudo yum install dotnet-runtime-3.1

Bước 11.

Hệ thống nhận thấy chúng ta đã cài đặt đầy đủ .NET Core runtime.

Hệ thống cài đặt xong toàn bộ các gói:

Tổng kết

Trong bài này chúng ta đã thực hiện cài đặt dotNet Core SDK 3.1 trên Hệ điều hành CentOS 7.

Hi vọng rằng chúng ta có thể phát triển tốt Desktop và Web Applications bằng ngôn ngữ lập trình C# với nền tảng này.

Mọi tác vụ đều được thực hiện tương tự như trên Windows.

Phương pháp sinh – Csharp

Giới thiệu

Trong nội dung bài này, chúng ta cùng nhau tìm hiểu một số bài toán cơ bản về phương pháp sinh.

Phương pháp sinh có thể áp dụng để giải bài toán liệt kê tổ hợp.

Hai điều kiện để có thể áp dụng phương pháp sinh:

  • Xác định được một thứ tự trên tập các cấu hình tổ hợp. Từ đó suy ra cấu hình đầu tiên và cấu hình cuối cùng.
  • Xây dựng được thuật toán từ một cấu hình trung gian. Từ đó sinh ra cấu hình kế tiếp.

Những bài toán được tìm hiểu trong bài này:

  • Sinh các dãy nhị phân độ dài n.
  • Liệt kê các tập con k phần tử của tập {1, 2, …, n} theo thứ tự từ điển.
  • Liệt kê các hoán vị của {1, 2, …, n} theo thứ tự từ điển.

Thiết kế chương trình

Bước 1.

Chúng ta tạo một Console Project trong MonoDevelop và đặt tên là CsharpAlgorithmGenerationMethod.

Class Program.cs cùng phương thức main() mặc định.

Bước 2.

Chúng ta tạo folder Algorithmclass GenerationAlgorithm.cs.

Chúng ta cũng định nghĩa những phương thức chính để thực hiện các bài toán đặt ra.

Phương thức GenerateBinarySequences()

Phương thức GenerateBinarySequences() được đặc tả để sinh một dãy nhị phân độ dài n.

Một dãy nhị phân độ dài n là một dãy x[1…n] trong đó x[i] ∈ {0, 1} (∀i : 1 ≤ i ≤ n).

Ví dụ: Khi n = 3, chúng ta có 8 dãy nhị phân độ dài 3 được liệt kê lần lượt như sau:

{000; 001; 010; 011; 100; 101; 110; 111}

Như vậy dãy đầu tiên sẽ là 00…0 và dãy cuối cùng sẽ là 11…1.

Ý tưởng giải thuật:

  • Xét từ cuối dãy về đầu (xét từ hàng đơn vị lên), tìm số 0 gặp đầu tiên.
  • Nếu thấy thì thay số 0 đó bằng số 1 và đặt tất cả các phần tử phía sau vị trí đó bằng 0.
  • Nếu không thấy thì thì toàn dãy là số 1, đây là cấu hình cuối cùng.

Bước 1.

Chúng ta định nghĩa một mảng gồm n phần tử.

Bước 2.

Chúng ta gán giá trị 0 cho từng phần tử trong mảng.

Bước 3.

Chúng ta thực hiện thuật toán sinh trong vòng lặp while() {}.

Nội dung chính của thuật toán bao gồm các bước từ 3.1 đến 3.4.

Bước 3.1.

Tại từng bước lặp, chúng ta nhận được một dãy nhị phân.

Chúng ta thêm dãy nhị phân này vào danh sách sequences.

Bước 3.2.

Chúng ta duyệt các phần tử từ cuối dãy trở lại.

Bước 3.3.

Chúng ta thực hiện điều chỉnh giá trị của x[i] và những phần tử đứng sau trên dãy.

Bước 3.4.

Thuật toán sinh dừng lại khi đã sinh ra dãy 11…1.

Thử nghiệm

Chúng ta thử nghiệm phương thức GenerateBinarySequences() trong class Program.cs.

Phương thức GenerateSubSets()

Phương thức GenerateSubSets() được đặc tả để liệt kê các tập con k phần tử của tập {1, 2, …, n} theo thứ tự từ điển.

Ví dụ: với n = 5, k = 3, chúng ta ta phải liệt kê đủ 10 tập con:

1.{1, 2, 3} 2.{1, 2, 4} 3.{1, 2, 5} 4.{1, 3, 4} 5.{1, 3, 5} 6.{1, 4, 5} 7.{2, 3, 4} 8.{2, 3, 5} 9.{2, 4, 5} 10. {3, 4, 5}

Như vậy tập con đầu tiên là {1, 2, …, k}.

Tập con kết thúc là {n - k + 1, n - k + 2, …, n}.

Ý tưởng giải thuật:

  • Tìm từ cuối dãy lên đầu cho tới khi gặp một phần tử x[i] chưa đạt giới hạn trên n - k + i.
  • Nếu tìm thấy: (i) Tăng x[i] đó lên 1; (ii) Gán tất cả các phần tử sau x[i] bằng giới hạn dưới x[i-1] + 1.
  • Nếu không tìm thấy tức là mọi phần tử đã đạt giới hạn trên, đây là tập con cuối cùng.

Bước 1.

Chúng ta định nghĩa một mảng gồm k phần tử.

Bước 2.

Chúng ta gán giá trị là chỉ số vị trí tương ứng cho từng phần tử trong mảng.

Bước 3.

Chúng ta thực hiện thuật toán sinh trong vòng lặp while() {}.

Nội dung chính của thuật toán bao gồm các bước từ 3.1 đến 3.4.

Bước 3.1.

Tại từng bước lặp, chúng ta nhận được một tập con.

Chúng ta thêm tập con này vào danh sách sequences.

Bước 3.2.

Chúng ta duyệt các phần tử từ cuối dãy trở lại.

Bước 3.3.

Chúng ta thực hiện điều chỉnh giá trị của x[i] và những phần tử đứng sau trên dãy.

Bước 3.4.

Thuật toán sinh dừng lại khi tất cả các phần tử đã đạt giới hạn trên.

Thử nghiệm

Chúng ta thử nghiệm phương thức GenerateSubSets() trong class Program.cs.

Phương thức GeneratePermutation()

Phương thức GeneratePermutation() được đặc tả để liệt kê các hoán vị của tập {1, 2, …, n} theo thứ tự từ điển.

Ví dụ với n = 4, ta phải liệt kê đủ 24 hoán vị:

1.1234 2.1243 3.1324 4.1342 5.1423 6.1432 7.2134 8.2143 9.2314 10.2341 11.2413 12.2431 13.3124 14.3142 15.3214 16.3241 17.3412 18.3421 19.4123 20.4132 21.4213 22.4231 23.4312 24.4321

Như vậy hoán vị đầu tiên sẽ là <1, 2, …, n>.

Hoán vị cuối cùng là <n, n-1, ..., 1>.

Ý tưởng giải thuật:

  • Xác định đoạn cuối giảm dần dài nhất
  • Xác định chỉ số i của phần tử x[i] đứng liền trước đoạn cuối đó.
  • Nếu tìm thấy chỉ số i như trên: (i) tìm phần tử x[k] nhỏ nhất thoả mãn điều kiện x[k] > x[i]; (ii) Đảo giá trị x[k]x[i]; (iii) Lật ngược thứ tự đoạn cuối giảm dần (từ x[i+1] đến x[k]) trở thành tăng dần.
  • Nếu không tìm thấy tức là toàn dãy đã sắp giảm dần, đây là cấu hình cuối cùng

Bước 1.

Chúng ta định nghĩa một mảng gồm n phần tử.

Bước 2.

Chúng ta gán giá trị là chỉ số vị trí tương ứng cho từng phần tử trong mảng.

Bước 3.

Chúng ta thực hiện thuật toán sinh trong vòng lặp while() {}.

Nội dung chính của thuật toán bao gồm các bước từ 3.1 đến 3.4.

Bước 3.1.

Tại từng bước lặp, chúng ta nhận được một hoán vị.

Chúng ta thêm hoán vị này vào danh sách sequences.

Bước 3.2.

Chúng ta duyệt các phần tử từ cuối dãy trở lại.

Bước 3.3.

Chúng ta thực hiện xem xét nếu chưa gặp phải hoán vị cuối.

Việc kiểm tra được thực hiện từ Bước 3.3.1 đến 3.3.3.

Bước 3.3.1.

Chúng ta duyệt các phần tử từ cuối dãy trở lại.

Bước 3.3.2.

Chúng ta lùi dần k.

Bước 3.3.3.

Chúng ta thực hiện đổi chỗ x[k]x[i].

Bước 3.3.4.

Chúng ta điều chỉnh những phần tử sau x[i].

Bước 3.4.

Thuật toán sinh dừng lại khi toàn bộ dãy giảm dần.

Thử nghiệm

Chúng ta thử nghiệm phương thức GeneratePermutation() trong class Program.cs.

Kết luận

Trong nội dung bài này, chúng ta đã cùng tìm hiểu một số bài toán con đối với thuật toán sinh để liệt kê một danh sách theo yêu cầu cho trước.

Hi vọng chúng ta có thể hiểu thêm về tư duy thuật toán cũng như một số các kỹ thuật lập trình Csharp để áp dụng cho các bài khác.

Thiết kế mô hình 3 lớp kết hợp Kết nối và truy vấn Cơ sở dữ liệu theo phương pháp Prepared Statement – Nội dung 3 – Kỹ thuật lập trình – Phần 2 – Tầng 2 – Csharp

Giới thiệu

Trong nhóm bài này, chúng ta cùng nhau tìm hiểu việc thiết kế một kiến trúc để lập trình phần mềm theo mô hình 3 lớp.

Những nội dung chính sẽ được trình bày trong nhóm bài:

  • Thiết lập một cơ sở dữ liệu cơ bản trong PostgreSQL để áp dụng trong toàn bộ nhóm bài. Chúng ta có thể tham khảo để tự thực hiện đối với những hệ quản trị cơ sở dữ liệu khác như: MySQL / MariaDB; SQLServer; Oracle; …
  • Thiết kế kiến trúc lập trình phần mềm theo mô hình 3 lớp. Chúng ta cũng sẽ áp dụng một chút kiến thức về lập trình hướng đối tượng ở đây.
  • Kỹ thuật kết nối và truy vấn cơ sở dữ liệu theo phương pháp Prepared Statement. Đây là phương pháp được ưu tiên khuyến khích hơn phương pháp thông thường.
  • Những kỹ thuật lập trình cụ thể sẽ được trình bày lần lượt với các ngôn ngữ: Java / C# / Python / PHP.

Nội dung chính của bài này là trình bày phần thứ hai và tập trung vào Tầng 2 trong nội dung về kỹ thuật lập trình với ngôn ngữ Csharp:

  • Phần 1. Xây dựng kiến trúc tổng quan của mô hình 3 lớp.
  • Phần 2. Kỹ thuật lập trình cụ thể cho từng tầng trong kiến trúc mô hình 3 lớp.

Class BaseService

Bước 1.

Chúng ta thiết kế lớp cơ sở BaseService như sau:

Bước 2.

Chúng ta đặc tả phương thức createConnection() đối với tác vụ kết nối đến PostgreSQL:

Bước 3.

Chúng ta đặc tả các phương thức chính trong class BaseService:

Class CategoryService

Chúng ta thiết kế lớp dẫn xuất CategoryService như sau:

Class ProductService

Chúng ta thiết kế lớp dẫn xuất ProductService như sau:

Kết luận

Trong bài này, chúng ta cùng nhau tìm hiểu việc thực hiện kỹ thuật lập trình cho phần thứ hai và tập trung vào Tầng 2.

Chúng ta có thể áp dụng những kiến thức trong nhóm bài để thực hiện một số bài tập:

  • Thêm / xóa / sửa / truy vấn dữ liệu trong bảng categoryproduct theo những yêu cầu thực tế khác nhau.
  • Thay đổi cơ sở dữ liệu PostgreSQL bởi các cơ sở dữ liệu khác: MySQL / MariaDB; Oracle; …

Nhóm bài này sẽ trở thành một trong những kiến thức nền để thực hiện các dạng phần mềm: Desktop / Web Application.

Thiết kế mô hình 3 lớp kết hợp Kết nối và truy vấn Cơ sở dữ liệu theo phương pháp Prepared Statement – Nội dung 3 – Kỹ thuật lập trình – Phần 2 – Tầng 3 – Csharp

Giới thiệu

Trong nhóm bài này, chúng ta cùng nhau tìm hiểu việc thiết kế một kiến trúc để lập trình phần mềm theo mô hình 3 lớp.

Những nội dung chính sẽ được trình bày trong nhóm bài:

  • Thiết lập một cơ sở dữ liệu cơ bản trong PostgreSQL để áp dụng trong toàn bộ nhóm bài. Chúng ta có thể tham khảo để tự thực hiện đối với những hệ quản trị cơ sở dữ liệu khác như: MySQL / MariaDB; SQLServer; Oracle; …
  • Thiết kế kiến trúc lập trình phần mềm theo mô hình 3 lớp. Chúng ta cũng sẽ áp dụng một chút kiến thức về lập trình hướng đối tượng ở đây.
  • Kỹ thuật kết nối và truy vấn cơ sở dữ liệu theo phương pháp Prepared Statement. Đây là phương pháp được ưu tiên khuyến khích hơn phương pháp thông thường.
  • Những kỹ thuật lập trình cụ thể sẽ được trình bày lần lượt với các ngôn ngữ: Java / C# / Python / PHP.

Nội dung chính của bài này là trình bày phần thứ hai và tập trung vào Tầng 3 trong nội dung về kỹ thuật lập trình với ngôn ngữ Csharp:

  • Phần 1. Xây dựng kiến trúc tổng quan của mô hình 3 lớp.
  • Phần 2. Kỹ thuật lập trình cụ thể cho từng tầng trong kiến trúc mô hình 3 lớp.

Class BaseDAO – Kiến trúc tổng quan

Bước 1.

Chúng ta thiết kế lớp cơ sở BaseDAO thành abstract class như sau:

Bước 2.

Chúng ta định nghĩa các thuộc tính trong class BaseDAO:

Bước 3.

Chúng ta định nghĩa phương thức khởi tạo không có tham số của class BaseDAO:

Bước 4.

Chúng ta định nghĩa các phương thức chính trong class BaseDAO:

Class BaseDAO – Phương thức getConnection()

Chúng ta đặc tả phương thức getConnection() đối với tác vụ kết nối đến PostgreSQL:

Class BaseDAO – Phương thức selectDataFromOneTable()

Bước 1.

Chúng ta đặc tả phương thức selectDataFromOneTable() đối với tác vụ truy xuất dữ liệu từ một bảng trong PostgreSQL.

Chúng ta thực hiện kỹ thuật bắt lỗi kết nối và truy vấn cơ sở dữ liệu:

Bước 2.

Mã nguồn SQL tổng quan để thực hiện truy vấn dữ liệu:

SELECT column_i, …, column_j FROM table [WHERE column_k = value_k AND … AND column_l = value_l]

Chúng ta đặc tả phần thứ nhất của chuỗi SQL như sau:

Bước 3.

Chúng ta đặc tả phần thứ hai của chuỗi SQL như sau:

Kỹ thuật lập trình cần chú ý ở đây:

  • Giá trị của từng trường điều kiện được thể hiện bằng dấu “?”.
  • Chúng ta sẽ thay thế từng dấu “?” bằng giá trị tương ứng trong dataSet ở các bước sau.
  • Đây là bước đầu tiên của kỹ thuật Prepared Statement. Kỹ thuật này giúp truy xuất dữ liệu thuận tiện hơn, độc lập cơ sở dữ liệu và phần nào chống được kỹ thuật tấn công SQL Injection.

Bước 4.

Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:

Bước 5.

Chúng ta định nghĩa một thực thể của class NpgsqlCommand:

Đây là bước thứ hai của kỹ thuật Prepared Statement giúp chuẩn bị thay thế từng dấu “?” trong chuỗi SQL bởi giá trị tương ứng.

Bước 6.

Chúng ta gọi phương thức appendData() để thực hiện bước thứ ba của kỹ thuật Prepared Statement là thay thế từng dấu “?” trong chuỗi SQL bởi giá trị tương ứng:

Kỹ thuật lập trình cần chú ý ở đây:

  • Chúng ta định nghĩa phương thức appendData()abstract trong class BaseDAO.
  • Chúng ta đặc tả cụ thể các kỹ thuật lập trình của phương thức appendData() trong các lớp dẫn xuất là CategoryDAOProductDAO.

Bước 7.

Chúng ta thực hiện truy vấn dữ liệu và trả về kết quả là một thực thể của class NpgsqlDataReader.

Chúng ta tiếp tục gọi phương thức mappingData() để thực hiện việc chuyển đổi dữ liệu trong thực thể này về dạng mong muốn và thêm vào results.

Kỹ thuật lập trình cần chú ý ở đây:

  • Chúng ta định nghĩa phương thức mappingData()abstract trong class BaseDAO.
  • Chúng ta đặc tả cụ thể các kỹ thuật lập trình của phương thức mappingData() trong các lớp dẫn xuất là CategoryDAOProductDAO.

Bước 8.

Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:

Class BaseDAO – Phương thức insertData()

Bước 1.

Chúng ta đặc tả phương thức insertData() đối với tác vụ thêm dữ liệu vào một bảng trong PostgreSQL.

Chúng ta thực hiện kỹ thuật bắt lỗi kết nối và truy vấn cơ sở dữ liệu:

Bước 2.

Mã nguồn SQL tổng quan để thực hiện thêm dữ liệu:

INSERT INTO table (column_i, …, column_j) VALUE (value_i, …, value_j)

Chúng ta đặc tả phần thứ nhất của chuỗi SQL như sau:

Bước 3.

Chúng ta đặc tả phần thứ hai của chuỗi SQL như sau:

Bước 4.

Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:

Bước 5.

Chúng ta định nghĩa một thực thể của class NpgsqlCommand:

Bước 6.

Chúng ta gọi phương thức appendData() để thực hiện bước thứ ba của kỹ thuật Prepared Statement là thay thế từng dấu “?” trong chuỗi SQL bởi giá trị tương ứng:

Bước 7.

Chúng ta thực hiện thêm dữ liệu:

Bước 8.

Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:

Class BaseDAO – Phương thức updateData()

Bước 1.

Chúng ta đặc tả phương thức updateData() đối với tác vụ cập nhật dữ liệu trong một bảng trong PostgreSQL.

Chúng ta thực hiện kỹ thuật bắt lỗi kết nối và truy vấn cơ sở dữ liệu:

Bước 2.

Mã nguồn SQL tổng quan để thực hiện cập nhật dữ liệu:

UPDATE table SET (column_i = value_i, …, column_j = value_j) [WHERE column_k = value_k AND … AND column_l = value_l]

Chúng ta đặc tả phần thứ nhất của chuỗi SQL như sau:

Bước 3.

Chúng ta đặc tả phần thứ hai của chuỗi SQL như sau:

Bước 4.

Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:

Bước 5.

Chúng ta định nghĩa một thực thể của class NpgsqlCommand:

Bước 6.

Chúng ta gọi phương thức appendData() để thực hiện bước thứ ba của kỹ thuật Prepared Statement là thay thế từng dấu “?” trong chuỗi SQL bởi giá trị tương ứng:

Bước 7.

Chúng ta thực hiện cập nhật dữ liệu:

Bước 8.

Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:

Class BaseDAO – Phương thức deleteData()

Bước 1.

Chúng ta đặc tả phương thức deleteData() đối với tác vụ xóa dữ liệu trong một bảng trong PostgreSQL.

Chúng ta thực hiện kỹ thuật bắt lỗi kết nối và truy vấn cơ sở dữ liệu:

Bước 2.

Mã nguồn SQL tổng quan để thực hiện xóa dữ liệu:

DELETE FROM table WHERE column_k = value_k AND … AND column_l = value_l

Chúng ta đặc tả chuỗi SQL như sau:

Bước 3.

Chúng ta gọi phương thức getConnection() để thực hiện kỹ thuật kết nối cơ sở dữ liệu:

Bước 4.

Chúng ta định nghĩa một thực thể của class NpgsqlCommand:

Bước 5.

Chúng ta gọi phương thức appendData() để thực hiện bước thứ ba của kỹ thuật Prepared Statement là thay thế từng dấu “?” trong chuỗi SQL bởi giá trị tương ứng:

Bước 6.

Chúng ta thực hiện xóa dữ liệu:

Bước 7.

Chúng ta thực hiện đóng kết nối đến cơ sở dữ liệu:

Class CategoryDAO

Bước 1.

Chúng ta thiết kế lớp dẫn xuất CategoryDAO như sau:

Bước 2.

Chúng ta đặc tả kỹ thuật lập trình cho phương thức appendData() như sau:

Kỹ thuật lập trình cần chú ý:

  • Mỗi trường trong bảng category có định dạng khác nhau. Tương ứng là từng phần tử trong danh sách data cũng có định dạng khác nhau.
  • Theo quy định về kiểu dữ liệu List trong Csharp thì mọi phần tử đều phải có cùng một định dạng.
  • Như vậy chúng ta định nghĩa kiểu dữ liệu cho từng phần tử trong dataobject: List<object> data. Đây là một class nguyên thủy và là cha của mọi class được định nghĩa.

Bước 3.

Chúng ta đặc tả kỹ thuật lập trình cho phương thức mappingData() như sau:

Class ProductDAO

Bước 1.

Chúng ta thiết kế lớp dẫn xuất ProductDAO như sau:

Bước 2.

Chúng ta đặc tả kỹ thuật lập trình cho phương thức appendData() như sau:

Bước 3.

Chúng ta đặc tả kỹ thuật lập trình cho phương thức mappingData() như sau:

Kết luận

Trong bài này, chúng ta cùng nhau tìm hiểu việc thực hiện kỹ thuật lập trình cho phần thứ hai và tập trung vào Tầng 3.

Trong bài tiếp theo, chúng ta cùng tìm hiểu việc thực hiện kỹ thuật lập trình cho Tầng 2.

Thiết kế mô hình 3 lớp kết hợp Kết nối và truy vấn Cơ sở dữ liệu theo phương pháp Prepared Statement – Nội dung 2 – Kỹ thuật lập trình – Phần 1 – Xây dựng kiến trúc tổng quan – Csharp

Giới thiệu

Trong nhóm bài này, chúng ta cùng nhau tìm hiểu việc thiết kế một kiến trúc để lập trình phần mềm theo mô hình 3 lớp.

Những nội dung chính sẽ được trình bày trong nhóm bài:

  • Thiết lập một cơ sở dữ liệu cơ bản trong PostgreSQL để áp dụng trong toàn bộ nhóm bài. Chúng ta có thể tham khảo để tự thực hiện đối với những hệ quản trị cơ sở dữ liệu khác như: MySQL / MariaDB; SQLServer; Oracle; …
  • Thiết kế kiến trúc lập trình phần mềm theo mô hình 3 lớp. Chúng ta cũng sẽ áp dụng một chút kiến thức về lập trình hướng đối tượng ở đây.
  • Kỹ thuật kết nối và truy vấn cơ sở dữ liệu theo phương pháp Prepared Statement. Đây là phương pháp được ưu tiên khuyến khích hơn phương pháp thông thường.
  • Những kỹ thuật lập trình cụ thể sẽ được trình bày lần lượt với các ngôn ngữ: Java / C# / Python / PHP.

Nội dung chính của bài này là trình bày phần thứ nhất trong nội dung về kỹ thuật lập trình với ngôn ngữ Csharp:

  • Phần 1. Xây dựng kiến trúc tổng quan của mô hình 3 lớp.
  • Phần 2. Kỹ thuật lập trình cụ thể cho từng tầng trong kiến trúc mô hình 3 lớp.

Xây dựng kiến trúc tổng quan của mô hình 3 lớp

Bước 1.

Chúng ta tạo mới Console Project trong MonoDevelop và đặt tên là CsharpThreeTiersProject.

Chúng ta sẽ thực hiện các kỹ thuật lập trình về đặc tả giao diện Console ở Tầng 1.

Bước 2.

Chúng ta tạo class BaseService trong folder Service.

Đây là lớp cơ sở của Tầng 2 về xử lý các tác vụ trung gian.

Bước 3.

Chúng ta tạo class CategoryServiceProductService trong folder Service.

Đây là các lớp dẫn xuất của BaseService để thực thi cụ thể các tác vụ ở Tầng 2.

Bước 4.

Chúng ta tạo class BaseDAO trong folder Dao.

Đây là lớp cơ sở của Tầng 3 về xử lý các tác vụ kết nối và truy vấn cơ sở dữ liệu.

Bước 5.

Chúng ta tạo class CategoryDAOProductDAO trong folder Dao.

Đây là các lớp dẫn xuất của BaseDAO để thực thi cụ thể các tác vụ ở Tầng 3.

Thiết lập driver điều khiển để kết nối PostgreSQL

Bước 1.

Chúng ta download nuget npgsql 4.0.10 tại địa chỉ như trong hình.

Bước 2.

Chúng ta lựa chọn Edit → Preferences … trong project.

Bước 3.

Màn hình Preferences hiện ra.

Chúng ta lựa chọn NuGet → Sources ở cột bên trái.

Chúng ta lựa chọn nút Add để thêm nuget.

Bước 4.

Màn hình Add Package Source hiện ra.

Chúng ta nhập Name như trong hình và chỉ để file nuget download bên trên.

Chúng ta lựa chọn nút Add Source để thực hiện.

Bước 5.

Màn hình Preferences sau khi thêm nuget hiện ra.

Chúng ta lựa chọn nút OK để thực hiện.

Bước 6.

Chúng ta nhấn chuột phải vào tên project.

Chúng ta lựa chọn Add → Add NuGet Packages …

Bước 7.

Màn hình Add Packages hiện ra.

Chúng ta lựa chọn nuget source phù hợp trong combo box.

Chúng ta lựa chọn nutget Npgsql và chú ý đúng version 4.0.10 đã download bên trên.

Chúng ta lựa chọn nút Add Package để thực hiện.

Bước 8.

Màn hình chính của project sau khi được thêm nuget npgsql.

Kết luận

Trong bài này, chúng ta đã cùng nhau tìm hiểu việc xây dựng kiến trúc tổng quan của mô hình 3 lớp cho một Csharp Project.

Trong bài tiếp theo, chúng ta sẽ cùng thực hiện các tác vụ cụ thể.

Ước số / bội số – Csharp

Giới thiệu

Trong nội dung bài này, chúng ta cùng nhau tìm hiểu một số bài toán cơ bản về ước số và bội số:

  • Tìm ước số chung lớn nhất của hai số tự nhiên.
  • Tìm bội số chung nhỏ nhất của hai số tự nhiên.
  • Phân tích một số tự nhiên thành các thừa số nguyên tố.
  • Tính số lượng các ước số của một số tự nhiên.
  • Tính tổng các ước số của một số tự nhiên.

Ước số chung lớn nhất của hai số

Ý tưởng giải thuật

Ước số chung lớn nhất (USCLN) của 2 số được tính theo thuật toán Euclid:

UCLN (a, b) = UCLN (b, (a mod b))

Bước 1.

Chúng ta tạo một Console Project trong MonoDevelop và đặt tên là CsharpAlgorithmSecondProject.

Bước 2.

Chúng ta tạo folder Algorithmclass UocBoi.cs.

Bước 3.

Chúng ta thực hiện giải thuật bằng ngôn ngữ Csharp như sau:

Bội số chung nhỏ nhất của hai số

Ý tưởng giải thuật

Bội số chung nhỏ nhất (BSCNN) của hai số được tính theo công thức:

Bước 1.

Chúng ta thực hiện giải thuật bằng ngôn ngữ Csharp như sau:

Bước 2.

Chúng ta thực hiện thử nghiệm phương thức TinhUCLN()TinhBCNN() trong class Program.cs như sau:

Bước 3.

Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:

Phân tích thừa số nguyên tố

Ý tưởng giải thuật

Chúng ta thực hiện chia số N cho các số nguyên tố trong đoạn [2; N].

  • Với mỗi số nguyên tố đó, đếm số lần mà số N chia hết.
  • Sau mỗi lần chia cho số i, số N của chúng ta sẽ giảm đi i lần.
  • Chúng ta dừng quá trình chia khi số chia lớn hơn N.

Bước 1.

Chúng ta thực hiện giải thuật bằng ngôn ngữ Csharp như sau:

Những kỹ thuật lập trình cần chú ý:

  • Chúng ta sử dụng kiểu dữ liệu Dictionary của Csharp để lưu trữ tập hợp không giới hạn các phần tử theo từng cặp <từ_khóa, giá trị>. Mỗi phần tử là một cặp: từ_khóa là thừa số nguyên tố; giá_trị là số mũ tương ứng với thừa số nguyên tố này.
  • Do thừa số nguyên tố và số mũ đều là số nguyên, chúng ta định nghĩa kiểu dữ liệu tập hợp là Dictionary<int, int>.

Bước 2.

Chúng ta thực hiện thử nghiệm phương thức PhanTichTSNT() trong class Program.cs như sau:

Những kỹ thuật lập trình cần chú ý:

  • Chúng ta sử dụng lớp thư viện StringBuilder để xử lý một số tác vụ liên quan đến chuỗi.
  • Phương thức Append() của StringBuilder thực hiện nối một chuỗi mới vào chuỗi hiện có.
  • Cách thức duyệt từng phần tử trong Dictionary là sử dụng kiểu dữ liệu KeyValuePair<>. Từng phần tử được truy xuất sẽ có thể lấy ra được từ_khóaKeygiá_trịValue.

Bước 3.

Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:

Số các ước số của một số

Ý tưởng giải thuật

Giả sử N được phân tích thành thừa số nguyên tố như sau:

Số các ước số của N là

Bước 1.

Chúng ta thực hiện giải thuật bằng ngôn ngữ Csharp như sau:

Tổng các ước số của một số

Ý tưởng giải thuật

Tổng các ước của N là

Bước 1.

Chúng ta thực hiện giải thuật bằng ngôn ngữ Csharp như sau:

Bước 2.

Chúng ta thực hiện thử nghiệm phương thức TinhSoUocSo()TinhTongUocSo() trong class Program.cs như sau:

Bước 3.

Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:

Tổng kết

Trong bài này, chúng ta đã cùng nhau tìm hiểu một số giải thuật cơ bản xung quanh ước số và bội số của một số tự nhiên và thực hiện bằng ngôn ngữ Csharp.

Hy vọng rằng chúng ta có thể áp dụng phù hợp những kỹ thuật và chức năng này cho những bài tiếp theo.

Lập trình hướng đối tượng – Phần 3 – Tính chất đa hình (polymorphism), lớp trừu tượng (abstract class) và giao diện (interface) – Csharp

Giới thiệu

Trong nội dung bài viết này, chúng ta cùng nhau tìm hiểu cách thức mà Java hỗ trợ việc thực hiện những thuật ngữ về Lập trình hướng đối tượng: (i) tính chất trừu tượng – abstraction; (ii) tính chất đa hình – polymorphism; (iii) lớp trừu tượng – abstract class; (iv) giao diện – interface.

Chúng ta thiết kế một chương trình nhỏ bao gồm các lớp và giao diện như sau:

  • Lớp trừu tượng: PhuongTienGiaoThong.
  • Các lớp đối tượng ở tầng dưới thứ hai: PhuongTienDuongBo; PhuongTienDuongThuy; PhuongTienDuongKhong.
  • Các lớp đối tượng ở tầng dưới cùng: Oto; XeMay; XeDap; TauThuy; Thuyen; MayBay; KhinhKhiCau; ThuyPhiCo.
  • Giao diện ở cấp cao nhất: HoatDong.
  • Giao diện ở tầng dưới: CoTheChay; CoTheBay; CoTheBoi.

Thiết kế Lớp trừu tượng

Bước 1.

Chúng ta thực hiện tạo Console Project trong MonoDevelop và đặt tên là CsharpOOPThirdProject.

Mặc định thì class Program.cs được tạo ra với phương thức Main().

Bước 2.

Chúng ta thực hiện tạo folder Object.

Chúng ta thực hiện tạo class PhuongTienGiaoThong.

Bước 3.

Chúng ta thực hiện tạo class PhuongTienDuongBo là một dẫn xuất của class PhuongTienGiaoThong.

Bước 4.

Chúng ta thực hiện tạo class PhuongTienDuongThuy là một dẫn xuất của class PhuongTienGiaoThong.

Bước 5.

Chúng ta thực hiện tạo class PhuongTienDuongKhong là một dẫn xuất của class PhuongTienGiaoThong.

Thiết kế Lớp đối tượng

Bước 1.

Chúng ta thực hiện tạo class Oto là một dẫn xuất của class PhuongTienDuongBo.

Bước 2.

Chúng ta thực hiện tạo class XeMay là một dẫn xuất của class PhuongTienDuongBo.

Bước 3.

Chúng ta thực hiện tạo class XeDap là một dẫn xuất của class PhuongTienDuongBo.

Bước 4.

Chúng ta thực hiện tạo class Thuyen là một dẫn xuất của class PhuongTienDuongThuy.

Bước 5.

Chúng ta thực hiện tạo class TauThuy là một dẫn xuất của class PhuongTienDuongThuy.

Bước 6.

Chúng ta thực hiện tạo class MayBay là một dẫn xuất của class PhuongTienDuongKhong.

Bước 7.

Chúng ta thực hiện tạo class KhinhKhiCau là một dẫn xuất của class PhuongTienDuongKhong.

Bước 8.

Chúng ta thực hiện tạo class ThuyPhiCo là một dẫn xuất của class PhuongTienGiaoThong.

Thiết kế Giao diện

Bước 1.

Chúng ta thực hiện tạo folder action.

Chúng ta thực hiện tạo interface ICoTheChay.

Những điểm cần chú ý:

  • Chúng ta sử dụng từ khóa interface đứng trước định nghĩa tên của giao diện.
  • Riêng đối với Csharp, một quy tắc phổ biến là thêm chữ cái I đứng trước tên dự kiến được đặt cho giao diện. Ở đây chúng ta có ICoTheChay.

Bước 2.

Chúng ta thực hiện tạo interface ICoTheBoi.

Bước 3.

Chúng ta thực hiện tạo interface ICoTheBay.

Bước 4.

Chúng ta thực hiện tạo interface IHoatDong là giao diện cơ sở của các giao diện: ICoTheChay; ICoTheBay; ICoTheBoi.

Thiết kế Tính đa hình thứ nhất

Bước 1.

Chúng ta đặc tả những đặc trưng của abstract class PhuongTienGiaoThong:

  • Thuộc tính: soLuongBanhXe; soLuongChoNgoi.
  • Những phương thức get / set.
  • Phương thức trừu tượng: GioiThieu().

Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienGiaoThong trên cây gia phả.

Bước 2.

Chúng ta đặc tả những đặc trưng của class PhuongTienDuongBo:

  • Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 01 thuộc tính riêng biệt: loaiDongCo.
  • Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính loaiDongCo.
  • Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienDuongBo trên cây gia phả.

Bước 3.

Chúng ta đặc tả những đặc trưng của class PhuongTienDuongKhong:

  • Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 02 thuộc tính riêng biệt: soLuongCanh; soLuongQuat.
  • Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính soLuongCanh; soLuongQuat.
  • Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienDuongKhong trên cây gia phả.

Bước 4.

Chúng ta đặc tả những đặc trưng của class PhuongTienDuongThuy:

  • Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 01 thuộc tính riêng biệt: loaiBanhLai.
  • Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính loaiBanhLai.
  • Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Chú ý rằng những đặc trưng này sẽ được kế thừa lại hoàn toàn từ những lớp dẫn xuất của PhuongTienDuongThuy trên cây gia phả.

Bước 5.

Chúng ta đặc tả những đặc trưng của class Oto:

  • Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongBo.
  • Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Bước 6.

Chúng ta đặc tả những đặc trưng của class XeMay:

  • Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongBo.
  • Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Bước 7.

Chúng ta đặc tả những đặc trưng của class XeDap:

  • Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongBo.
  • Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Bước 8.

Chúng ta đặc tả những đặc trưng của class MayBay:

  • Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongKhong.
  • Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Bước 9.

Chúng ta đặc tả những đặc trưng của class KhinhKhiCau:

  • Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongKhong.
  • Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Bước 10.

Chúng ta đặc tả những đặc trưng của class TauThuy:

  • Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongThuy.
  • Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Bước 11.

Chúng ta đặc tả những đặc trưng của class Thuyen:

  • Thuộc tính. Kế thừa trọn vẹn những thuộc tính từ lớp cơ sở PhuongTienDuongThuy.
  • Phương thức. Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Bước 12.

Chúng ta đặc tả những đặc trưng của class ThuyPhiCo:

  • Thuộc tính. Đầu tiên là kế thừa những thuộc tính từ lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa thêm 02 thuộc tính riêng biệt: loaiBanhLai; soLuongCanh.
  • Phương thức. Đầu tiên là kế thừa trọn vẹn những phương thức get / set đối với những thuộc tính được đặc tả ở lớp cơ sở PhuongTienGiaoThong. Tiếp đến là định nghĩa các phương thức get / set đối với thuộc tính loaiBanhLai; soLuongCanh.
  • Kế thừa và đặc tả lại phương thức GioiThieu(). Đây là một phương thức được sử dụng trong ví dụ về tính chất đa hình.

Bước 13.

Chúng ta thực hiện thử nghiệm tính đa hình như bên dưới.

Chúng ta có thể nhận thấy những điểm rất rõ ở đây là:

  • Thực thể của đối tượng nào thì sẽ tự biết mình là ai.
  • Và như vậy sẽ tự thực hiện một cách chính xác phương thức GioiThieu() cũng như các phương thức get / set của các thuộc tính được đặc tả trong lớp trừu tượng PhuongTienGiaoThong.

Bước 14.

Kết quả thực hiện thử nghiệm đa hình thứ nhất như sau:

Thiết kế Tính đa hình thứ hai

Bước 1.

Chúng ta định nghĩa phương thức trừu tượng ThongBao() trong interface cơ sở IHoatDong.

Bước 2.

Chúng ta định nghĩa interface ICoTheChay kế thừa từ interface IHoatDong:

  • Kế thừa việc định nghĩa các phương thức trừu tượng từ interface IHoatDong.
  • Định nghĩa phương thức trừu tượng riêng biệt: Chay().

Bước 3.

Chúng ta định nghĩa interface ICoTheBoi kế thừa từ interface IHoatDong:

  • Kế thừa việc định nghĩa các phương thức trừu tượng từ interface IHoatDong.
  • Định nghĩa phương thức trừu tượng riêng biệt: Boi().

Bước 4.

Chúng ta định nghĩa interface ICoTheBay kế thừa từ interface IHoatDong:

  • Kế thừa việc định nghĩa các phương thức trừu tượng từ interface IHoatDong.
  • Định nghĩa phương thức trừu tượng riêng biệt: Bay().

Bước 5.

Chúng ta điều chỉnh class PhuongTienDuongBo để thuộc phạm vi ảnh hưởng của interface ICoTheChay:

  • Kế thừa và đặc tả lại toàn bộ các phương thức trừu tượng được định nghĩa trong interface IHoatDong cũng như ICoTheChay.

Bước 6.

Chúng ta điều chỉnh class PhuongTienDuongThuy để thuộc phạm vi ảnh hưởng của interface ICoTheBoi:

  • Kế thừa và đặc tả lại toàn bộ các phương thức trừu tượng được định nghĩa trong interface IHoatDong cũng như ICoTheBoi.

Bước 7.

Chúng ta điều chỉnh class PhuongTienDuongKhong để thuộc phạm vi ảnh hưởng của interface ICoTheBay:

  • Kế thừa và đặc tả lại toàn bộ các phương thức trừu tượng được định nghĩa trong interface IHoatDong cũng như ICoTheBay.

Bước 8.

Chúng ta điều chỉnh class ThuyPhiCo để thuộc phạm vi ảnh hưởng của interface ICoTheChayICoTheBoi.

  • Có thể thực thi cùng lúc nhiều interface. Có nghĩa rằng 1 lớp đối tượng có thể cùng lúc chịu ảnh hưởng của nhiều bộ quy tắc khác nhau.
  • Kế thừa và đặc tả lại toàn bộ các phương thức trừu tượng được định nghĩa trong interface IHoatDong cũng như ICoTheChay, ICoTheBoi.

Bước 9.

Chúng ta điều chỉnh lại ví dụ về tính đa hình như bên dưới.

Những điểm cần chú ý:

  • Những đối tượng thuộc phạm vi ảnh hưởng của những interface khác nhau sẽ thực thi những phương thức đặc trưng riêng của từng interface.
  • Chúng ta cần kiểm tra một chút để biết thực thể của đối tượng nào bằng cách sử dụng từ khóa is.

Tổng kết

Trong bài này, chúng ta đã cùng nhau tìm hiểu sự hỗ trợ của Csharp trong việc thực hiện tính chất đa hình trong Lập trình hướng đối tượng.

Hi vọng với bài này thì chúng ta đã có cái nhìn tổng quát hơn về cả 04 tính chất đặc trưng nhất của Lập trình hướng đối tượng.

Lập trình hướng đối tượng – Phần 2 – Tính chất kế thừa – Csharp

Giới thiệu

Trong nội dung bài này, chúng ta cùng nhau tìm hiểu tính chất kế thừa trong tư duy Lập trình hướng đối tượng.

Chúng ta sẽ thử nghiệm tính chất này qua một ví dụ đơn giản về hình chữ nhật và hình vuông.

Nhắc lại đặc điểm của tính chất kế thừa như sau:

  • Đặc tính này cho phép một đối tượng có thể có sẵn các đặc tính mà đối tượng khác đã có thông qua kế thừa.
  • Điều này cho phép các đối tượng chia sẻ hay mở rộng các đặc tính sẵn có mà không phải tiến hành định nghĩa lại.

Xây dựng lớp đối tượng HinhChuNhat

Bước 1.

Chúng ta tạo một Console Project trong MonoDevelop và đặt tên là CsharpOOPSecondProject.

Mặc định thì class Program.cs trong namespace CsharpOOPSecondProject với phương thức Main() được tạo ra.

Bước 2.

Chúng ta tạo class HinhChuNhat.cs và điều chỉnh namespace Object.

Bước 3.

Chúng ta định nghĩa 02 thuộc tính cơ bản của một hình chữ nhật:

Những kỹ thuật lập trình cần chú ý:

  • Như đã trình bày ở phần Giới thiệu về Tính chất kế thừa, một lớp đối tượng có thể được kế thừa và mở rộng những thuộc tính và phương thức nào đó của lớp cơ sở.
  • Trong ví dụ ở đây, chúng ta đều biết rằng mỗi hình vuông đều là một hình chữ nhật và đều có 02 thuộc tính là chiều dài và chiều rộng. Do vậy chúng ta định nghĩa 02 thuộc tính của class HinhChuNhat theo cách mà có thể được kế thừa.
  • Chúng ta sử dụng từ khóa protected được Csharp cung cấp. Từ khóa này quy định một thuộc tính hoặc một phương thức là ẩn, cho phép kế thừa và chỉ được truy xuất bên trong một lớp và những lớp con của nó.

Bước 4.

Chúng ta định nghĩa các constructor cho lớp đối tượng:

Bước 5.

Chúng ta định nghĩa các phương thức đặc biệt truy xuất và điều chỉnh dữ liệu, được gọi là các properties với gettersetter:

Những kỹ thuật lập trình cần chú ý:

  • Chúng ta biết rằng mỗi hình vuông là một hình chữ nhật đặc biệt trong đó chiều dài và chiều rộng là bằng nhau (nên được gọi chung là cạnh). Do vậy trong ví dụ ở đây, chúng ta sẽ cần kế thừa, mở rộng và điều chỉnh setter của properties ChieuDaiChieuRong.
  • Trước tiên, đối với phương thức ở lớp cơ sở mà dự kiến sẽ được kế thừa, mở rộng và điều chỉnh, chúng ta sử dụng từ khóa virtual do Csharp cung cấp.

Bước 6.

Chúng ta định nghĩa các phương thức tính chu vi, diện tích và đường chéo hình chữ nhật:

Những kỹ thuật lập trình cần chú ý:

  • Có lẽ cũng cần nhắc lại một chút về công thức tính đường chéo ở đây: (đường_chéo)^2 = (chiều_dài)^2 + (chiều_rộng)^2.
  • Kết quả của công thức tính đường chéo là một số thực có phần thập phân. Do vậy chúng ta sử dụng kiểu dữ liệu float hoặc double do Csharp cung cấp để đặc tả kết quả trả về này.
  • Tương tự như setter của properties ChieuDaiChieuRong, chúng ta có thể có nhu cầu kế thừa, mở rộng và điều chỉnh phương thức TinhDuongCheo() trong class HinhVuong. Do vậy chúng ta sử dụng từ khóa virtual ở đây.

Xây dựng lớp đối tượng HinhVuong

Bước 1.

Chúng ta tạo class HinhVuong.cs.

Những kỹ thuật lập trình cần chú ý:

  • Trong ví dụ ở đây, chúng ta sử dụng ký hiệu “:” phân tách giữa hai lớp để đặc tả sự kế thừa.
  • Như đã mô tả ở trên về định nghĩa 02 thuộc tính chieuDaichieuRong. Chúng ta không cần định nghĩa lại 02 thuộc tính này trong class HinhVuong mà kế thừa từ HinhChuNhat.
  • Nếu phân tích theo một hướng khác, chúng ta có thể định nghĩa thuộc tính canh cho class HinhVuong. Như vậy thì nên thiết lập lại phạm vi là private cho 02 thuộc tính của class HinhChuNhat để không cho kế thừa.

Bước 2.

Chúng ta định nghĩa các constructor cho lớp đối tượng:

Những kỹ thuật lập trình cần chú ý:

  • Chúng ta định nghĩa 02 constructor cho class HinhVuong tương ứng với 02 constructor cho class HinhChuNhat.
  • Trong từng constructor cho class HinhVuong, chúng ta có thể thực thi các tác vụ khởi tạo giá trị mặc định nào đó cho riêng class HinhVuong.
  • Nếu chúng ta muốn gọi constructor của lớp cơ sở để thực thi, ví dụ ở đây là class HinhChuNhat, chúng ta sử dụng phương thức base() và truyền tham số tương ứng với từng constructor cho class HinhChuNhat.

Bước 3.

Chúng ta thực hiện kế thừa và điều chỉnh phương thức setter:

Những kỹ thuật lập trình cần chú ý:

  • Thuật ngữ để kế thừa, điều chỉnh và mở rộng một phương thức của lớp cơ sở được gọi là nạp chồng hàm (override). Csharp cung cấp một kiểu từ khóa override để đặc tả một phương thức như vậy trong lớp dẫn xuất.
  • Trong ví dụ ở đây, chúng ta cần điều chỉnh phương thức setter vì trong hình vuông thì chiều dài và chiều rộng là bằng nhau (nên được gọi chung là cạnh).
  • Cú pháp để thực hiện kế thừa, mở rộng và điều chỉnh properties được thể hiện rõ nét trong ví dụ này. Chúng ta chỉ cần áp dụng tương tự cho những bài tập khác.
  • Chú ý rằng chúng ta sử dụng phương thức base để gọi đến properties đã được định nghĩa ở lớp dẫn xuất.

Bước 4.

Chúng ta thực hiện kế thừa và điều chỉnh phương thức TinhDuongCheo():

Những kỹ thuật lập trình cần chú ý:

  • Chúng ta không cần điều chỉnh các phương thức về tính chu vi và diện tích vì thực ra công thức là như nhau. Do vậy trong class HinhVuong chúng ta không đặc tả lại mà kế thừa hoàn toàn từ class HinhChuNhat đối với 02 phương thức TinhChuVi()TinhDienTich().
  • Đối với tác vụ tính đường chéo, chúng ta có 03 lựa chọn. Lựa chọn thứ nhất. Tương tự như 02 phương thức TinhChuVi()TinhDienTich(), chúng ta không đặc tả lại mà kế thừa hoàn toàn từ class HinhChuNhat. Lựa chọn thứ hai. Chúng ta thực hiện kế thừa lại với từ khóa override nhưng sẽ gọi phương thức của class HinhChuNhat để thực thi: base.TinhDuongCheo(). Lựa chọn thứ ba. Chúng ta thực thi theo công thức thu gọn dành riêng cho hình vuông: (đường_chéo) ^2 = 2 * (cạnh)^2.

Thử nghiệm chương trình

Bước 1.

Chúng ta thực hiện thử nghiệm tạo mới 01 hình chữ nhật, 02 hình vuông và tính chu vi, diện tích, đường chéo:

Những kỹ thuật lập trình cần chú ý:

  • Đối với việc khởi tạo một đối tượng hình vuông. Chúng ta có 02 sự lựa chọn: (i) HinhChuNhat hinhVuong = new HinhVuong(); (ii) HinhVuong hinhVuong = new HinhVuong(). Thực ra cả 02 sự lựa chọn này là như nhau vì class HinhVuong là lớp dẫn xuất của lớp cơ sở class HinhChuNhat.
  • Chúng ta được khuyến khích là áp dụng sự lựa chọn thứ nhất như trong ví dụ ở đây. Lý do chính là để hiểu rõ hơn về tính chất trừu tượng và đa hình của Lập trình hướng đối tượng mà sẽ được trao đổi kỹ hơn trong các bài tiếp theo.

Bước 2.

Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:

Tổng kết

Trong bài này, chúng ta đã cùng nhau tìm hiểu tính chất kế thừa trong Lập trình hướng đối tượng.

Chúng ta đã cùng nhau thực hiện một ví dụ nhỏ về tính chất kế thừa với ngôn ngữ Csharp.

Trong các bài tiếp theo, chúng ta sẽ tiếp tục tìm hiểu những kiến thức khác xung quanh lập trình hướng đối tượng.

Lập trình hướng đối tượng – Phần 1 – Cơ bản về lớp đối tượng – Csharp

Giới thiệu

Lập trình hướng đối tượng (tiếng Anh: Object-oriented programming, viết tắt: OOP) là một mô hình kiến trúc lập trình dựa trên khái niệm “công nghệ đối tượng”, mà trong đó, đối tượng chứa đựng các dữ liệu: (i) thuộc tính của đối tượng; (ii) phương thức để thực thi các hành động của đối tượng.

OOP được xem là giúp tăng năng suất, đơn giản hóa độ phức tạp khi bảo trì cũng như mở rộng phần mềm bằng cách cho phép lập trình viên tập trung vào các đối tượng phần mềm ở bậc cao hơn.

Một số khái niệm cơ bản

Khái niệm đầu tiên là “đối tượng”, được hiểu như là 1 thực thể: người, vật hoặc 1 bảng dữ liệu, . . .

Một đối tượng bao gồm 2 thông tin chính:

  • Thuộc tính. Là những thông tin, đặc điểm của đối tượng. Ví dụ: một hình chữ nhật sẽ có chiều dài, chiều rộng, . . .
  • Phương thức. Là những thao tác, hành động mà đối tượng đó có thể thực hiện. Ví dụ: một hình chữ nhật sẽ có thao tác tính chu vi, diện tích, . . .

Khái niệm thứ hai là “lớp”, được hiểu như là một khuôn mẫu mà từng đối tượng là một thể hiện cụ thể dựa trên khuôn mẫu đó.

Ví dụ một lớp hình chữ nhật sẽ định nghĩa: (i) các thuộc tính chiều dài / chiều rộng; (ii) các phương thức tính chu vi, tính diện tích. Còn từng đối tượng hình chữ nhật sẽ có số đo cụ thể cho từng thuộc tính cũng như chu vi và diện tích riêng.

Các tính chất của lập trình hướng đối tượng

Tính đóng gói (encapsulation) và che giấu thông tin (information hiding):

  • Tính chất này không cho phép tác nhân bên ngoài thay đổi trạng thái nội tại của một đối tượng.
  • Chỉ có các phương thức nội tại của đối tượng cho phép thay đổi trạng thái của nó.
  • Đây là tính chất đảm bảo sự toàn vẹn của đối tượng.

Tính trừu tượng (abstraction):

  • Là phương pháp trừu tượng hóa định nghĩa lên những hành động, tính chất của loại đối tượng nào đó cần phải có.
  • Mỗi đối tượng có thể hoàn tất các công việc một cách nội bộ, báo cáo, thay đổi trạng thái của nó và liên lạc với các đối tượng khác mà không cần cho biết làm cách nào đối tượng tiến hành được các thao tác.
  • Tính chất này thường được gọi là sự trừu tượng của dữ liệu.

Tính kế thừa (inheritance):

  • Đặc tính này cho phép một đối tượng có thể có sẵn các đặc tính mà đối tượng khác đã có thông qua kế thừa.
  • Điều này cho phép các đối tượng chia sẻ hay mở rộng các đặc tính sẵn có mà không phải tiến hành định nghĩa lại.

Tính đa hình (polymorphism):

  • Thể hiện thông qua việc gửi các thông điệp (message).
  • Việc gửi các thông điệp này có thể so sánh như việc gọi các phương thức bên trong của một đối tượng.
  • Các phương thức dùng trả lời cho một thông điệp sẽ tùy theo đối tượng mà thông điệp đó được gửi tới sẽ có phản ứng khác nhau.

Xây dựng lớp đối tượng độc lập

Trong nội dung bài này, chúng ta cùng tìm hiểu cách xây dựng một lớp đối tượng độc lập cùng với tính chất đóng gói (encapsulation) bằng ngôn ngữ Csharp.

Bước 1.

Chúng ta tạo một Console Project trong MonoDevelop và đặt tên là CsharpOOPFirstProject.

Mặc định thì class Program.cs trong namespace CsharpOOPFirstProject với phương thức Main() được tạo ra.

Bước 2.

Chúng ta tạo class HinhChuNhat.cs và điều chỉnh namespace Object.

Những kỹ thuật lập trình cần chú ý:

  • Như đã trình bày ở phần Giới thiệu về Tính đóng gói (encapsulation) và che giấu thông tin (information hiding). Mỗi namespace có thể được xem như là một hình thức để gom nhóm các lớp đối tượng có cùng chung những đặc điểm nào đó.
  • Là một ngôn ngữ lập trình hướng đối tượng hoàn toàn, Csharp yêu cầu tất cả các lớp được định nghĩa phải thuộc một namespace nào đó.
  • Trong ví dụ hiện tại, chúng ta có thể đặt tên namespaceObject (nghĩa là đối tượng nói chung) hoặc Shape (nghĩa là hình vẽ nói chung).

Bước 3.

Chúng ta định nghĩa 02 thuộc tính cơ bản của một hình chữ nhật:

Những kỹ thuật lập trình cần chú ý:

  • Như đã trình bày ở phần Giới thiệu về đặc trưng của một lớp đối tượng. Các thuộc tính nội tại của một đối tượng thì chỉ có thể được trông thấy và điều chỉnh bởi các phương thức nội tại của chính đối tượng đó.
  • Chúng ta sử dụng từ khóa private được Csharp cung cấp. Thuộc tính này quy định một thuộc tính hoặc một phương thức là ẩn bên trong một lớp.

Bước 4.

Chúng ta định nghĩa các constructor cho lớp đối tượng:

Những kỹ thuật lập trình cần chú ý:

  • Constructor là một dạng đặc biệt của phương thức, được sử dụng để khởi tạo các đối tượng.
  • Constructor được gọi tại thời điểm tạo đối tượng. Nó khởi tạo các giá trị để cung cấp dữ liệu cho các đối tượng, đó là lý do tại sao nó được gọi là constructor.
  • Chú ý trong Csharp: (i) tên của constructor phải trùng với tên của lớp; (ii) constructor không có kiểu trả về.
  • Có 02 kiểu constructor: (i) kiểu mặc định không có tham số truyền vào; (ii) kiểu có tham số.
  • Từ khóa this giúp chúng ta liên hệ đến thuộc tính hoặc phương thức nội tại của lớp đối tượng. Chúng ta sử dụng từ khóa này để phân biệt khi muốn định nghĩa các biến có cùng tên với các thuộc tính hoặc phương thức nội tại của lớp.

Bước 5.

Chúng ta định nghĩa các phương thức đặc biệt truy xuất và điều chỉnh dữ liệu, được gọi là các properties với gettersetter:

Những kỹ thuật lập trình cần chú ý:

  • Csharp cung cấp một hình thức được gọi là properties để định nghĩa kiểu dữ liệu riêng cho việc truy xuất và điều chỉnh thông tin của các thuộc tính nội tại. Chúng ta có thể sử dụng các properties này như là một thuộc tính của đối tượng.
  • Theo quy tắc chung, tên của từng properties nên được đặt trùng với tên của thuộc tính, chỉ có một điểm khác là chữ cái đầu viết hoa.
  • Mỗi thuộc tính nên được theo kèm bởi một properties với cặp get / set tương ứng.

Bước 6.

Chúng ta định nghĩa các phương thức tính chu vi và diện tích hình chữ nhật:

Bước 7.

Chúng ta thực hiện thử nghiệm tạo mới 02 hình chữ nhật và tính chu vi, diện tích:

Những kỹ thuật lập trình cần chú ý:

  • Để truy xuất đến những lớp đối tượng ở một namespace khác, chúng ta sử dụng từ khóa using. Ví dụ ở đây là using object.
  • Chúng ta khởi tạo một đối tượng thực bằng cách gọi constructor của lớp đối tượng với toán tử new. Với constructor được gọi thì thuộc tính nội tại sẽ được khởi tạo với giá trị mặc định của nó.
  • Ví dụ ở đây. Đối tượng hinhChuNhatA được khởi tạo với constructor mặc định không có tham số. Như vậy sẽ sử dụng properties để điều chỉnh thông tin cho thuộc tính của đối tượng. Đối tượng hinhChuNhatB được khởi tạo với constructor có tham số.

Bước 8.

Chúng ta thực thi toàn bộ project để kiểm tra kết quả thử nghiệm:

Tổng kết

Trong bài này, chúng ta đã cùng nhau tìm hiểu những kiến thức cơ bản về lớp đối tượng cũng như những tính chất về lập trình hướng đối tượng.

Chúng ta đã cùng nhau thực hiện một ví dụ nhỏ về lớp đối tượng với ngôn ngữ Csharp.

Trong các bài tiếp theo, chúng ta sẽ tiếp tục tìm hiểu những kiến thức khác xung quanh lập trình hướng đối tượng.