--------------- <> -----------------
--- KHOA HỌC - CÔNG NGHỆ - GIÁO DỤC - VIỆC LÀM ---
--- Học để đi cùng bà con trên thế giới ---

Tìm kiếm trong Blog

Web back-end (14) - Lập trình hướng sự kiện

Bài trước: Web back-end (13) - Lập trình client-server

-----
14. Lập trình hướng sự kiện

Như bạn đã trải nghiệm ở các bài học trước, quan sát mã nguồn của index.js, bạn sẽ thấy: hàm app.listen() luôn được viết ở cuối tập tin, và mặc dù viết ở cuối tập tin, nhưng dường như nó lại luôn luôn được chạy trước? Nó chạy trước thì mới lắng nghe được các request từ client, để gọi các hàm xử lý tương ứng? Các hàm xử lý request lại được viết ở phía trên hàm app.listen().

Bạn đã thấy: logic xử lý của chương trình không phải luôn luôn thực thi tuần tự từ trên xuống dưới?

Để giải đáp hiện tượng trên, chúng ta cùng tìm hiểu một số chủ đề liên quan.

14.1 Lập trình hướng sự kiện

Lập trình hướng sự kiện (event-driven) là một mô hình lập trình mà luồng thực thi của chương trình được quyết định bởi các sự kiện (events). Các sự kiện này có thể là:

- Hành động của người dùng (nhấp chuột, gõ phím).

- Các thông điệp từ các chương trình khác.

- Các sự kiện do hệ thống tạo ra (nhận được request, thao tác đọc/ghi tập tin).

Thay vì chạy theo thứ tự mã nguồn từ trên xuống dưới, chương trình sẽ chờ đợi các sự kiện xảy ra và thực thi các hàm xử lý sự kiện (event handler) tương ứng.

14.2 Lập trình hướng sự kiện trong Nodejs

Nodejs là một môi trường được xây dựng dựa trên mô hình lập trình hướng sự kiện. Đây là một trong những đặc điểm cốt lõi giúp Node.js hoạt động hiệu quả và có khả năng xử lý nhiều kết nối đồng thời, đặc biệt phù hợp với các ứng dụng thời gian thực, các ứng dụng chuyên về I/O như ứng dụng web, API, hoặc ứng dụng mạng.

Ứng dụng chuyên về I/O (I/O-intensive application) là các ứng dụng mà phần lớn thời gian xử lý hoặc tài nguyên được dành cho các hoạt động nhập/xuất (Input/Output), tức là các tác vụ liên quan đến việc đọc/ghi dữ liệu từ hoặc đến các nguồn bên ngoài như tập tin, cơ sở dữ liệu, mạng, hoặc thiết bị phần cứng, thay vì tập trung nhiều vào tính toán (CPU-intensive).

Các thành phần của Mô hình lập trình hướng sự kiện

Mô hình lập trình hướng sự kiện trong Nodejs gồm các thành phần:

- Event: sự kiện

- Event Emitter: bộ quản lý sự kiện

- Event loop: vòng lặp sự kiện

- Event handler: hàm xử lý sự kiện

Xem hình minh họa:


Mô tả cách hoạt động của mô hình:

[1] EventEmitter

Trong hệ thống sẽ có một thành phần điều khiển, nó quản lý việc phát ra sự kiện của các đối tượng và gửi sự kiện tới nơi cần nghe (các đối tượng đang lắng nghe sự kiện tương ứng). Thành phần này được gọi là EventEmitter - Bộ quản lý sự kiện). 

Các phương thức chính của EventEmitter:

- on(eventName, listener): khai báo một tên sự kiện (eventName) sẽ phát ra, và đăng ký một hàm lắng nghe và xử lý đi kèm.

- emit(eventName, [arguments...]): phát ra một sự kiện, có tên là eventName, và các tham số đi kèm (nếu có).

[2] Event

Event là một hành động hoặc sự thay đổi trạng thái xảy ra trong ứng dụng, gọi chung là sự kiện (Event). Ví dụ:

- Yêu cầu HTTP đến máy chủ (GET request, POST request).

- Hoàn thành việc đọc/ghi tập tin.

- Hết thời gian chờ (timeout).

- Sự kiện lỗi.

[3] Event Loop (Vòng lặp sự kiện)

- Event Loop là cơ chế cốt lõi của Nodejs, cho phép nó xử lý các sự kiện không đồng bộ một cách hiệu quả.

- Event Loop liên tục kiểm tra hàng đợi sự kiện (event queue) và thực thi các hàm callback khi có sự kiện xảy ra.

- Điều này cho phép Nodejs xử lý nhiều yêu cầu đồng thời mà không bị chặn (blocking).

[4] Event Handler (Hàm xử lý sự kiện)

- Event handler là một hàm được gọi khi một sự kiện xảy ra. 

- Event handler thường được đăng ký với một EventEmitter bằng phương thức on().

14.3 Thực hành lập trình hướng sự kiện

Chúng ta cùng thực hành để làm quen với lập trình hướng sự kiện.

Chúng ta sẽ viết một chương trình đơn giản như sau:

- Sử dụng module events của Nodejs để lập trình hướng sự kiện

- Tạo một bộ quản lý sự kiện (EventEmitter)

- Sử dụng EventEmitter để khai báo một sự kiện, và đăng ký hàm xử lý đi kèm

- Phát sinh sự kiện (đã khai báo), để kiểm tra hoạt động của các thành phần

Để cho dễ hiểu, chúng ta sẽ viết chương trình theo 2 cách: [1] viết theo kiểu hàm thông thường (cách này viết để hiểu cơ chế làm việc) và [2] viết theo kiểu hàm mũi tên (arrow function) (cách này viết theo kiểu lập trình trong ứng dụng thực tế).

[1] Viết theo kiểu hàm thông thường

[index.js]

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

 

// gọi module events

const events = require('events');

// tạo ra một EventEmitter

const eventEmitter = new events.EventEmitter();

// đăng ký tên sự kiện, gắn với hàm lắng nghe và

// xử lý sự kiện tương ứng - xuLythongBao là event handler

eventEmitter.on('hetGio', xuLyThongBao);

// định nghĩa hàm xuLyThongBao

function xuLyThongBao(tb) {

    console.log(tb);

}

// phát ra sự kiện, kèm theo thông điệp

setTimeout(()=> {

    eventEmitter.emit('hetGio','Hết giờ học rồi, về thôi!!!!!!!')

}, 2000);

// khoi dong web server

app.listen(port, () => {

    console.log(`server dang chay tren cong ${port}`);

});

[2] Viết theo kiểu hàm mũi tên

[index.js]

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

 

// gọi module events

const events = require('events');

// tạo ra một EventEmitter

const eventEmitter = new events.EventEmitter();

// đăng ký tên sự kiện, gắn với hàm lắng nghe và

// xử lý sự kiện tương ứng

eventEmitter.on('hetGio', (thongBao) => {

    console.log(thongBao);

});

// phát ra sự kiện, kèm theo thông điệp

setTimeout(()=> {

    eventEmitter.emit('hetGio','Hết giờ học rồi, về thôi!!!!!!!')

}, 2000);

 

// khoi dong web server

app.listen(port, () => {

    console.log(`server dang chay tren cong ${port}`);

});

Kết quả: khi chạy, sau 2 giây, cửa sổ console trên web server sẽ có dòng thông báo sau

server dang chay tren cong 9000

Hết giờ học rồi, về thôi!!!!!!!

14.4 Bài tập

Bài tập 14.1 Viết lại các đoạn mã trong bài học.

Bài tập 14.2 Sử dụng module events của Nodejs để lập trình hướng sự kiện. Viết một chương trình đơn giản như sau:

- Khai báo sự kiện vaoLop (vào lớp), với hàm xử lý đi kèm là xuLyVaoLop

- Sử dụng hàm setTimeOut() để hẹn giờ vào lớp là 5 giây

- Hết 5 giây, web server sẽ thông báo “Đã đến giờ học” tới cửa sổ console của web server

- Viết bằng 2 cách: hàm thông thường và hàm mũi tên.

Câu hỏi 14.3 Mô hình lập trình hướng sự kiện trong Node.js là gì? Phát biểu nào sau đây không đúng?

A. Event Emitter liên tục kiểm tra hàng đợi sự kiện và thực thi các hàm callback khi có sự kiện xảy ra.

B. Event là các hành động hoặc sự thay đổi trạng thái xảy ra trong ứng dụng.

C. Event Loop liên tục kiểm tra hàng đợi sự kiện và thực thi các hàm callback khi có sự kiện xảy ra.

D. Event Handler là các hàm được gọi khi một sự kiện xảy ra.

-----
Cập nhật: 31/3/2025
-----

Web back-end (13) - Lập trình client-server

Bài trước: Web back-end (12) - Ứng dụng client-server

-----
13. Lập trình client-server
13.1 Gửi request tới web server

Ở các phần trước, chúng ta đã có trải nghiệm với lập trình client-server. Tuy nhiên, chúng ta mới chỉ dừng lại mức độ làm theo hướng dẫn, mà chưa hiểu được cơ chế giao tiếp, cách thức xử lý giữa client và server. 

Phần này, chúng ta sẽ tìm hiểu chi tiết hơn về lập trình giao tiếp giữa client và server.

Như đã đề cập, các bước xử lý ở web server gồm 7 bước, như hình sau:

Cụ thể, 7 bước xử lý gồm:

[1] nhận request

[2] phân tích request, gửi tới ứng dụng web để xử lý

[3] đọc dữ liệu từ cơ sở dữ liệu

[4] đổ dữ liệu vào trang HTML (các template HTML)

[5] gửi trang HTML (đã bao gồm dữ liệu) (response) về trình duyệt người dùng

[6] trình duyệt người dùng hiển thị nội dung response

[7] trình duyệt gửi riêng một request khác để lấy các nội dung tĩnh của ứng dụng web (HTML, CSS, JavaScript, hình ảnh, và các tài nguyên khác)

Để đơn giản, chúng ta sẽ lập trình theo tình huống sau:

- Bước 1: web server luôn ở trạng thái đang hoạt động, sẵn sàng chờ client gửi yêu cầu (request) tới.

- Bước 2: một người dùng bất kỳ, sử dụng trình duyệt web, gửi request tới web server.

- Bước 3: web server nhận request

- Bước 4: web server phân tích, xử lý request

- Bước 5: web server gửi response về client

- Bước 6: client (trình duyệt) nhận response, hiển thị thông tin lên trình duyệt.

Chúng ta cùng lập trình từng bước.

Bước 1: web server luôn ở trạng thái đang hoạt động, sẵn sàng chờ client gửi yêu cầu (request) tới

Mở tập tin index.js nhập đoạn mã sau:

[index.js]

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

 

 

// khoi dong web server

app.listen(port, () => {

    console.log(`server dang chay tren cong ${port}`);

});

Dòng mã app.listen() luôn được đặt ở cuối tập tin index.js. Dòng mã này sẽ khởi chạy web server, mở cổng có số hiệu là port (ví dụ 9000) để chờ đón các request từ client; đồng thời xuất một dòng thông báo server dang chay tren cong ${port}.  Hiểu nôm na, hàm app.listen() giống như hành động mở cửa của tiệm bán quần áo, mời bà con vào mua. Tiệm quần áo là một kiot trong chợ, có số hiệu là 9000. Trong chợ có rất nhiều kiot bán quần áo, với các số hiệu khác nhau.

Mở cửa sổ dòng lệnh, chạy lệnh node index.js hoặc nodemon để thực thi mã nguồn index.js.

Lưu ý dòng thông báo server dang chay tren cong ${port} sẽ xuất ở cửa sổ console tại máy web server, chứ không phải cửa sổ console của máy client. Bạn không tắt cửa sổ console này, vì tắt nó là web server sẽ ngừng hoạt động.

Bước 2: một người dùng bất kỳ, sử dụng trình duyệt web, gửi request tới web server

Khi web server đang chạy, và sẵn sàng nhận request. Chúng ta sẽ sử dụng trình duyệt để gửi các request về web server.

Để gửi request về web server, bạn có thể sử dụng thanh địa chỉ của trình duyệt, web form, hoặc dùng hàm JavaScript (AJAX, fetch). Để đơn giản, chúng ta sẽ sử dụng thanh địa chỉ của trình duyệt.

Mở trình duyệt web (tuy nhiên, bạn phải hiểu là mở trình duyệt trên máy tính của người dùng, vì đang trong giai đoạn phát triển phần mềm, nên máy web server và máy người dùng sẽ chạy chung trên một máy), gõ vào thanh địa chỉ URL sau:

http://localhost:9000/?name=shoes&size=40

Bấm Enter, bạn sẽ nhận được thông báo trên trình duyệt là:

Cannot GET /

Lý do có thông báo trên: client gửi request về web server, tuy nhiên, server mới chỉ mở cổng (9000) để lắng nghe request, nhận request, nhưng chưa có xử lý request và gửi trả lời (response) cho client. Nó giống như kiot đã mở bán, nhưng bên trong chưa có sản phẩm, chưa có người bán (kiot trống).

URL (Uniform Resource Locator) là địa chỉ duy nhất, dùng để định vị tài nguyên trên web, như trang HTML, API, hoặc tập tin tài nguyên tĩnh (ví dụ hình ảnh, âm thanh). Bạn có thể xem URL giống như địa chỉ của kiot.

Ví dụ một số URL:

- Định vị một trang web: https://www.example.com/index.html

- Gọi một API: https://api.example.com/v1/users/123

- Trỏ tới một hình ảnh: https://www.example.com/images/logo.png

- Định vị một ứng dụng web (trên máy cục bộ): http://localhost:9000/

Cú pháp của một URL:

protocol://domain:port/path?query#fragment

Giải thích các thành phần của một URL:

- protocol (giao thức): xác định phương thức giao tiếp mà trình duyệt sử dụng để giao tiếp với server. Các giao thức phổ biến bao gồm http (Hypertext Transfer Protocol) và https (Hypertext Transfer Protocol Secure).

- domain (tên miền): tên của máy server. Ví dụ: google.com, wikipedia.org, localhost.

- port (cổng) (tùy chọn): số cổng mà server sử dụng để lắng nghe yêu cầu (request). Cổng mặc định cho http là 80 và cho https là 443.

- path (đường dẫn): đường dẫn đến một vị trí (thư mục, tập tin, API) trên server. Ví dụ: /images/logo.png, /articles/how-to-use-url, /users.

- query (truy vấn) (tùy chọn): chuỗi các tham số được sử dụng để truyền dữ liệu đến server. Ví dụ: ?name=shoes&size=40.

- fragment (phân mảnh) (tùy chọn): một phần cụ thể của tài nguyên, thường là một phần của trang HTML. Ví dụ: #section-2.

Như vậy, URL http://localhost:9000/?name=shoes&size=40

Có nghĩa là:

- Client sử dụng giao thức http để gửi request tới web server

- Web server có địa chỉ là localhost

- Gửi request vào cổng 9000 của web server

- Gửi request, có kèm theo 2 tham số là name=shoes và size=40

Ngoài việc dùng thanh địa chỉ của trình duyệt để gửi request, chúng ta còn có 2 cách khác để gửi request là web form và hàm JavaScript (AJAX, fetch). Chúng ta sẽ tìm hiểu về web form, AJAX, fetch ở các phần sau.

13.2 Gửi response về client

Bước 3: web server nhận request, Bước [4] phân tích, xử lý request, Bước [5] gửi kết quả (response) về cho client

Tại web server, chúng ta sử dụng phương thức GET của Express để nhận và xử lý các HTTP request kiểu GET (request gửi bằng giao thức HTTP) do client gửi tới.

Cú pháp:

app.get(path, callback)

Trong đó:

- path: luồng dùng để xử lý các request kiểu GET (GET request). 

- callback: hàm sẽ được thực thi khi có GET request đến luồng tương ứng. Hàm này thường có dạng (req, res) => { ... }, trong đó: 

  + req (request): đối tượng chứa thông tin request từ client.

  + res (response): đối tượng dùng để gửi response về client.

Client có thể gửi nhiều loại request về web server, ví dụ: GET, POST, PUT, DELETE. Chúng ta dùng thanh địa chỉ của trình duyệt để gửi request, mặc định đó là request kiểu GET.

Dấu “/” trong http://localhost:9000/?name=shoes&size=40, có nghĩa là thư mục gốc.

Chúng ta sẽ viết đoạn mã xử lý như sau:

[index.js]

'use strict'

const express = require('express')

const app = express();

const port = process.env.PORT || 9000

//xử lý khi người dùng gửi

//request kiểu GET tới thư mục gốc (/)

app.get("/", (req,res) => {

    //dùng phương thức query của req để lấy thông tin

    //của GET request

    const product = req.query.name;

    const size = req.query.size;

    //dùng hàm send() của đối tượng res

    //để gửi dữ liệu về client

    res.send(`Bạn muốn mua ${product} cỡ ${size}`);

});

//khoi dong web server

app.listen(port,() => {

    console.log(`server dang chay tren cong ${port}`);

});

Lưu lại mã nguồn, khởi động lại web server (nếu dùng Nodemon thì không cần).

Bước 6: client (trình duyệt) nhận response, hiển thị thông tin lên trình duyệt

Mở trình duyệt, nhập đường vào đường dẫn URL: http://localhost:9000/?name=shoes&size=40

Trên trình duyệt sẽ xuất hiện dòng chữ.

Bạn muốn mua shoes cỡ 40

Bạn có để ý là: đoạn mã app.listen() luôn được chạy trước, mặc dù nó nằm phía dưới đoạn mã app.get(). Về mặt xử lý: có thể hiểu nôm na app.listen() là động tác mở cửa kiot, chào đón khách tới mua hàng. Trong khi các đoạn mã phía trên là việc trưng bày hàng hóa, bán hàng, thanh toán. Như vậy, chúng ta sẽ trưng bày hàng hóa, sau đó, mở cửa hàng (app.listen()). Chờ có khách tới mua (request) thì sẽ thực hiện việc bán hàng, thanh toán.

Chúng ta sẽ tìm hiểu về kiến trúc của Nodejs, Express, lập trình hướng sự kiện ở các phần sau để hiểu rõ hơn về cách xử lý mã nguồn của ứng dụng web trên nền Express và Nodejs.

13.3 Bài tập

Bài tập 13.1 Viết đoạn mã thực hiện yêu cầu sau:

Từ trình duyệt, người dùng gửi GET request, có kèm theo MSSV, HoTen, DiemTrungBinh của một sinh viên. Ví dụ:

MSSV:11223344

HoTen:Nguyễn Văn Tèo

DiemTrungBinh:7.0 

Web server nhận request trên, lấy thông tin từ request và gửi về client dòng thông báo có nội dung và định dạng như sau:

Chào bạn Nguyễn Văn Teo

MSSV: 11223344

Điểm trung bình của bạn là: 70

Chúc bạn học chăm!

Câu hỏi 13.2 URL (Uniform Resource Locator) là gì? Phát biểu nào sau đây không đúng?

A. URL là một địa chỉ duy nhất xác định vị trí của một tài nguyên trên Internet.

B. URL bao gồm các thành phần như giao thức, tên miền, đường dẫn, truy vấn và phân mảnh.

C. Phần "truy vấn" (query) trong URL được sử dụng để truyền dữ liệu đến máy chủ thông qua các tham số.

D. Giao thức "FTP" là giao thức phổ biến nhất được sử dụng trong URL để truy cập các trang web.

-----

Cập nhật: 31/3/2025
-----
Bài sau: Web back-end (14) - Lập trình hướng sự kiện

Web back-end (12) - Ứng dụng client-server

Bài trước: Web back-end (11) - Lập trình giao diện
-----
12. Ứng dụng client-server
12.1 Ứng dụng kiểu cục bộ

Trước khi tìm hiểu về ứng dụng kiểu client-server, chúng ta cùng tìm hiểu về ứng dụng kiểu cục bộ (gọi tắt là ứng dụng cục bộ).

Ứng dụng cục bộ

Ứng dụng cục bộ (local application) là các ứng dụng chạy trực tiếp trên thiết bị của người dùng, như máy tính cá nhân, điện thoại hoặc máy tính bảng, mà không cần kết nối liên tục với máy chủ ở xa.

Một số đặc điểm của ứng dụng cục bộ:

- Chạy độc lập: ứng dụng cục bộ được cài đặt và chạy trực tiếp trên thiết bị của người dùng, không phụ thuộc vào kết nối internet để thực hiện các chức năng cơ bản.

- Truy cập tài nguyên thiết bị: ứng dụng cục bộ có thể truy cập trực tiếp vào các tài nguyên của thiết bị, chẳng hạn như hệ thống tập tin, phần cứng và các ứng dụng khác.

- Hiệu suất cao: do chạy trực tiếp trên thiết bị, ứng dụng cục bộ thường có hiệu suất cao hơn so với các ứng dụng web hoặc ứng dụng dựa trên đám mây.

- Khả năng ngoại tuyến: nhiều ứng dụng cục bộ có thể hoạt động mà không cần kết nối Internet, cho phép người dùng làm việc khi không có mạng.

- Bảo mật: dữ liệu của ứng dụng cục bộ thường được lưu trữ trên thiết bị của người dùng, giúp tăng cường bảo mật và quyền riêng tư.

Ví dụ một số ứng dụng cục bộ: Microsoft Word, Excel, Photoshop, Premiere, Notepad, các trò chơi máy tính.

Lập trình ứng dụng cục bộ

Có thể bạn đã rất quen thuộc với lập trình ứng dụng cục bộ, ví dụ khi bạn làm các bài tập của môn Nhập môn lập trình, Kỹ thuật lập trình, Lập trình hướng đối tượng, dùng ngôn ngữ C, C++, C#, Java hoặc Python.

Dù bạn lập trình theo kiểu hướng cấu trúc hay hướng đối tượng thì cấu trúc của một chương trình thường là: 

- Có một điểm vào chương trình (entry point) là hàm main().

- Khi chạy hàm main() sẽ xuất ra một menu, hoặc một màn hình chính (main window).

- Chờ các tương tác của người dùng để xử lý, thực thi các xử lý logic, đọc dữ liệu, xuất kết quả.

- Sử dụng một trình dịch (trình thông dịch hoặc biên dịch) trên máy cục bộ để chuyển từ mã nguồn thành mã thực thi.

- Sử dụng các bộ thư viện cục bộ, truy cập cơ sở dữ liệu trên máy cục bộ.

12.2 Ứng dụng kiểu client-server

Ứng dụng kiểu client-server (gọi tắt là ứng dụng client-server) là một ứng dụng, trong đó công việc được phân chia giữa hai thành phần chính là client và server.

- Client (máy khách): gửi yêu cầu (request) để truy cập dịch vụ hoặc tài nguyên. Client là giao diện người dùng (UI) trên máy tính, điện thoại, hoặc trình duyệt.

- Server (máy chủ): nhận yêu cầu, xử lý, và gửi phản hồi (response) về client. Server lưu trữ dữ liệu, thực hiện xử lý logic, và cung cấp dịch vụ.

- Giao tiếp giữa client và server được thực hiện qua mạng (thường dùng giao thức HTTP, TCP/IP). Client và server chạy trên các thiết bị khác nhau. Tuy nhiên, trong giai đoạn phát triển phần mềm, client và server có thể chạy trên cùng một máy tính.

Đặc điểm của một ứng dụng client-server:

- Phân vai trò: client tập trung hiển thị, server tập trung xử lý logic, xử lý dữ liệu.

- Kết nối mạng: yêu cầu giao tiếp qua giao thức mạng như HTTP, WebSocket, TCP/IP.

Một số ứng dụng client-server: ứng dụng web, ứng dụng email, trò chơi trực tuyến, hệ quản trị cơ sở dữ liệu.

12.3 Ứng dụng web dưới góc nhìn của lập trình viên

Ứng dụng web dưới góc nhìn của lập trình viên:

- Là ứng dụng kiểu client-server. Client là trình duyệt web, server là web server.

- Giao diện của ứng dụng được hiển thị trên trình duyệt web.

- Hầu hết các xử lý logic, xử lý dữ liệu được thực hiện tại server.

- Để lập trình phía client (client-side) cần các ngôn ngữ HTML, CSS, JavaScript, các thư viện và framework. Lập trình phía client được gọi là lập trình front-end. Người làm mảng công việc này được gọi là lập trình viên front-end (front-end developer).

- Để lập trình phía server (server-side) cần một trong các ngôn ngữ lập trình phía back-end (C#, Java, Python, Ruby, PHP, Go, JavaScript), SQL, các thư viện, và framework. Lập trình phía server được gọi là lập trình back-end. Người làm mảng này được gọi là lập trình viên back-end (back-end developer)

- Người làm được cả front-end và back-end được gọi là full-stack developer.

- Tùy theo khả năng, một lập trình viên có thể chọn làm ở mảng front-end, hoặc back-end hoặc cả hai (full-stack). Dù làm ở mảng front-end thì bạn cũng phải biết căn bản về mảng back-end và ngược lại.

Xem hình minh họa.

Trình duyệt web thường gồm 3 vùng sau:

- [1] Menu, và thanh công cụ của trình duyệt web

- [2] Thanh địa chỉ (address bar): cho phép người dùng gửi yêu cầu (request) tới một trang web, website hoặc ứng dụng web.

- [3] Giao diện của trang web, website hoặc ứng dụng web.

Xem hình minh họa: giao diện của một ứng dụng web.

12.4 Bài tập

Câu hỏi 12.1 Ứng dụng cục bộ là gì? Phát biểu nào sau đây không đúng?

A. Ứng dụng cục bộ chạy trực tiếp trên thiết bị của người dùng mà không cần kết nối liên tục với máy chủ ở xa.

B. Ứng dụng cục bộ luôn yêu cầu kết nối internet ổn định để hoạt động hiệu quả.

C. Ứng dụng cục bộ có thể truy cập trực tiếp vào các tài nguyên của thiết bị như hệ thống tập tin và phần cứng.

D. Dữ liệu của ứng dụng cục bộ thường được lưu trữ trên thiết bị của người dùng, giúp tăng cường bảo mật và quyền riêng tư.

Câu hỏi 12.2 Ứng dụng kiểu client-server là gì? Phát biểu nào sau đây không đúng?

A. Client tập trung chủ yếu vào việc hiển thị giao diện người dùng, trong khi server tập trung xử lý logic và dữ liệu.

B. Giao tiếp giữa client và server thường được thực hiện qua mạng, sử dụng các giao thức như HTTP, WebSocket hoặc TCP/IP.

C. Client và server luôn phải chạy trên các thiết bị riêng biệt, không bao giờ có thể cùng chạy trên một máy tính.

D. Server có nhiệm vụ nhận yêu cầu từ client, xử lý chúng, và gửi phản hồi lại cho client.

-----
Cập nhật: 28/3/2025
-----
Bài sau: Web back-end (13) - Lập trình client-server

Python (4) - Cú pháp của Python

Bài trước: Python (3) - Một số Trình viết mã cho Python

-----

4. Cú pháp của Python

Tới bài học này, bạn đã:

- Cài đặt được trình thông dịch (Python.exe)

- Biết cách viết mã (lập trình) Python trên các môi trường khác nhau (CMD, IDLE, Notepad, VS Code)

- Đã biết cách dịch và chạy chương trình Python

Phần này, chúng ta bắt đầu học về ngôn ngữ Python.

Học ngôn ngữ Python cũng giống như khi bạn học một ngoại ngữ (tiếng Anh). Mục tiêu sau cùng của học ngoại ngữ là dùng được nó, ví dụ bạn học tiếng Anh, thì bạn phải đọc hiểu được tài liệu tiếng Anh, nói chuyện được với người Anh, người Mỹ. Vậy học Python cũng vậy, phải biết dùng “tiếng Python” để nói chuyện được với máy tính, dùng Python ra lệnh được cho máy tính làm những gì bạn muốn; đọc một đoạn mã nguồn bằng Python thì phải hiểu được nó làm gì, tạo ra kết quả gì?

4.1 Chương trình là gì

Lập trình là tạo ra các chương trình. Vậy,

Chương trình là gì?

Chương trình (program) là một tập hợp các chỉ dẫn (các câu lệnh) được viết bằng ngôn ngữ lập trình (ví dụ Python), được sắp xếp theo một trật tự nhất định để máy tính thực hiện một nhiệm vụ cụ thể (ví dụ: mở một trò chơi, tính toán, hiển thị thông báo).

Ví dụ:

# Đây là một chương trình Python đơn giản: 

print("Chào bạn!") # Chỉ dẫn 1: Yêu cầu máy tính in ra chữ "Chào bạn!" 

print("Hôm nay là thứ mấy?") # Chỉ dẫn 2: Yêu cầu máy tính in ra câu hỏi 

# Chương trình này thực hiện nhiệm vụ giao tiếp cơ bản

Bạn có thể hình dung Chương trình Python giống như một cuốn sách công thức pha chế nước uống. Máy tính sẽ đọc và thực thi từng chỉ dẫn trong công thức để tạo ra một món nước uống.

Câu lệnh là gì?

Nếu Chương trình Python là cuốn sách công thức pha chế nướng uống, thì Câu lệnh chính là mỗi bước trong công thức đó.

Câu lệnh (statement) là một chỉ thị đơn lẻ (single instruction) hoàn chỉnh mà bạn đưa cho máy tính. Mỗi câu lệnh yêu cầu máy tính thực hiện một hành động cụ thể.

Mỗi câu lệnh nằm trên một dòng, kết thúc câu lệnh bằng việc xuống dòng, không cần dấu chấm phẩy (;) khi kết thúc câu lệnh.

Ví dụ minh họa:

- Lệnh xuất chuỗi: print("Chào bạn!") là một lệnh

- Lệnh gán giá trị: ten = "Tèo" là một lệnh, yêu cầu máy tính lưu chữ "Tèo" dưới cái tên ten

- Lệnh tính toán: tong = 5 + 3 là một lệnh, yêu cầu máy tính tính tổng và lưu kết quả

Khối lệnh là gì?

Đôi khi, để thực hiện một hành động lớn hơn, bạn cần nhóm nhiều bước nhỏ lại với nhau.

Khối lệnh (đoạn lệnh, code block) là một nhóm các câu lệnh có liên quan, đặt chung với nhau và thường được thực thi như một đơn vị thống nhất (ví dụ: chỉ chạy khi thỏa mãn một điều kiện nào đó)

Trong Python, các khối lệnh được xác định bằng cách thụt lề (Indent). Các lệnh có cùng mức thụt lề sẽ thuộc cùng một khối.

Bạn hãy lập trình và chạy đoạn mã sau.

Ví dụ minh họa (khối lệnh IF):

diem = 9


# Đây là lệnh điều kiện

if diem >= 8:

    # 2 lệnh sau thuộc cùng một khối lệnh

    # Vì chúng đều được thụt lề vào trong

    print("Bạn đạt điểm Giỏi!")

    print("Xin chúc mừng!")

4.2 Quá trình thông dịch và thực thi lệnh

Phần cứng máy tính không hiểu được ngôn ngữ Python, nó chỉ hiểu mã nhị phân (0 và 1). Do vậy, để thực thi chương trình của bạn, máy tính phải thực hiện một bước trung gian là Thông dịch lệnh.

Quá trình thông dịch lệnh là công việc của Trình thông dịch (Interpreter). Nó giống như một phiên dịch viên làm việc theo thời gian thực: nó đọc từng dòng lệnh Python bạn viết, dịch dòng đó sang ngôn ngữ máy tính, và yêu cầu máy tính thực hiện ngay lập tức, sau đó mới chuyển sang dòng lệnh tiếp theo.

Các bước diễn ra:

- Bạn viết lệnh Python (ví dụ: print("Xin chào"))

- Trình thông dịch Python (python.exe) đọc dòng lệnh này

- Nó dịch lệnh này sang mã máy tính (0s và 1s)

- Máy tính thực thi mã máy (hiển thị "Xin chào" lên màn hình)

- Quá trình này lặp lại cho đến hết chương trình

Vì Python là ngôn ngữ thông dịch, nó giúp việc kiểm tra và gỡ lỗi (debug) dễ dàng hơn. Nếu có lỗi ở dòng nào, chương trình sẽ dừng lại ngay tại dòng đó và báo lỗi.

Bạn hãy lập trình lại đoạn mã sau trong IDLE (chế độ soạn thảo tập tin). Sau đó dịch và thực thi.

# 1. Khai báo các biến lưu trữ thông tin 


ho_ten = "Nguyễn Văn A"

toan = 9.0

van = 8.5 

anh = 9.5 


# 2. Tính điểm trung bình 

# Sử dụng công thức: Tổng điểm / Số môn 


diem_trung_binh = (toan + van + anh) / 3 


# 3. Xuất các nội dung theo yêu cầu 


print("--- KẾT QUẢ HỌC TẬP ---") 

print(f"Họ tên đầy đủ: {ho_ten}") 

print(f"Điểm môn Toán: {toan}") 

print(f"Điểm môn Văn: {van}") 

print(f"Điểm môn Anh: {anh}") 


# Sử dụng hàm round() để làm tròn điểm trung bình đến 2 chữ số thập phân cho dễ nhìn


print(f"Điểm Trung bình (DTB): {round(diem_trung_binh, 2)}") 


# 4. Kiểm tra điều kiện và đưa ra thông báo xếp loại 

# Điều kiện: Nếu điểm trung bình lớn hơn 8.5 


if diem_trung_binh > 8.5: 

print("\n CHÚC MỪNG! Bạn đạt loại: GIỎI!")

4.3 Thụt lề

Thụt lề là gì?

Trong các ngôn ngữ lập trình khác, người ta dùng dấu ngoặc nhọn { } để nhóm các câu lệnh lại. Nhưng trong Python, chúng ta sử dụng Thụt lề (tiếng Anh là Indentation) để làm việc này.

Thụt lề là việc bạn dịch chuyển một đoạn mã vào bên trong (thường là dùng 4 dấu cách hoặc 1 phím Tab) so với lề bên trái.

Thụt lề giúp Python biết được câu lệnh nào thuộc về nhóm nào (gọi là Khối lệnh hay Code Block). Đây là cách duy nhất để Python xác định cấu trúc chương trình.

Ví dụ minh họa: Phân biệt giữa “có” thụt lề và “không” thụt lề.

Bạn hãy tưởng tượng bạn đang đưa ra một điều kiện: "Nếu tôi có tiền, tôi sẽ mua một cái bánh và một hộp sữa."

Bạn hãy lập trình đoạn mã ví dụ sau bằng Notepad (hoặc một trình soạn thảo văn bản tương tự).

Trường hợp 1: Thụt lề đúng (Python hiểu là khối lệnh)

# Khai báo biến

co_tien = True


# Câu lệnh điều kiện (IF)

if co_tien:

    # HAI LỆNH SAU ĐƯỢC THỤT LỀ VÀO TRONG

    # Python hiểu: Nếu co_tien là True, hãy thực hiện cả hai lệnh này.

    print("Mua một cái bánh")

    print("Mua một hộp sữa")

# Lệnh này không thụt lề, nên nó sẽ luôn chạy, không phụ thuộc vào điều kiện IF.

print("Về nhà")

Kết quả chạy:

Mua một cái bánh

Mua một hộp sữa

Về nhà

Trường hợp 2: Thiếu thụt lề (Python báo lỗi cú pháp)

Nếu bạn bỏ quên việc thụt lề, chương trình sẽ báo lỗi ngay lập tức vì Python không biết lệnh print("Mua một cái bánh.) thuộc về điều kiện if hay không.

co_tien = True


if co_tien:

print("Mua một cái bánh") # LỖI: Cần phải thụt lề ở đây!

print("Mua một hộp sữa")


Kết quả chạy:

IndentationError: expected an indented block

Quy tắc về Thụt lề trong lập trình

- Thống nhất: Bạn phải sử dụng thống nhất việc thụt lề trong toàn bộ chương trình (thường là 4 dấu cách cho mỗi lần thụt vào).

- Khi nào cần Thụt lề? Bất cứ khi nào bạn dùng các câu lệnh tạo ra khối lệnh mới, như:

    + Điều kiện: if, elif, else

    + Vòng lặp: for, while

    + Hàm: def

    + Lớp: class

Tóm lại: Thụt lề không chỉ giúp mã Python dễ đọc hơn mà còn là một phần bắt buộc của cú pháp. Nếu bạn làm sai Thụt lề, chương trình sẽ không chạy được.

4.4 Chú thích

Chú thích là gì?

Bạn có thể hình dung Chú thích giống như những ghi chú nhanh bạn viết vào lề sách hoặc một dòng giải thích nhỏ trong vở bài tập.

Chú thích (comment) là những dòng văn bản bạn viết trong chương trình Python, nhưng những dòng này chỉ dành cho con người đọc (bạn, đồng nghiệp, bạn bè, hoặc giáo viên). Trình thông dịch Python sẽ hoàn toàn bỏ qua chúng khi chạy chương trình.

Tác dụng quan trọng nhất

- Giải thích mã: Giúp bạn (hoặc người khác) hiểu được đoạn mã phức tạp đang làm gì, hoặc tại sao bạn lại viết nó như vậy

- Ngăn thực thi mã: Giúp bạn tắt tạm thời một câu lệnh nào đó để kiểm tra lỗi, mà không cần xóa nó đi.

Cách tạo Chú thích trong Python

Trong Python, có hai cách chính để tạo chú thích:

Chú thích một dòng

Để biến một dòng thành Chú thích, bạn chỉ cần đặt dấu thăng (#) vào đầu dòng hoặc phía sau một câu lệnh.

Bạn hãy lập trình đoạn mã sau trong VS Code hoặc một trình soạn mã nguồn bất kỳ.

Ví dụ minh họa:

# Đây là một chú thích, Python sẽ không chạy dòng này.


ten = "Bình"

diem = 10 # Chú thích ngay bên cạnh câu lệnh: Gán điểm tuyệt đối

print(f"Họ tên: {ten}")

print(f"Điểm số: {diem}")

Chú thích nhiều dòng

Nếu bạn có nhiều dòng muốn ghi chú (ví dụ: mô tả chi tiết cả chương trình hoặc một hàm lớn), bạn có thể dùng ba dấu ngoặc kép (""") ở đầu và cuối đoạn chú thích.

Bạn hãy lập trình đoạn mã sau trong VS Code hoặc một trình soạn mã nguồn bất kỳ.

Ví dụ minh họa:

"""

Chương trình này được viết vào ngày 18/11/2025.

Mục đích: Tính tổng và hiệu của hai số.

Người lập trình: Học sinh lớp 8A.

"""

so_a = 5

so_b = 3

tong = so_a + so_b

print(f"Tổng là: {tong}")

Tóm lại: Chú thích là công cụ giúp mã của bạn dễ hiểu, dễ bảo trì hơn rất nhiều, và máy tính sẽ không thực thi chúng.

4.5 Bài tập và câu hỏi

Bài tập 4a. Viết và chạy lại các đoạn mã trong phần lý thuyết.

Câu hỏi 4.1 Chương trình là gì? Phát biểu nào không đúng?

A. Chương trình là một tập hợp các câu lệnh

B. Câu lệnh (statement) là một chỉ thị đơn lẻ (single instruction) hoàn chỉnh mà bạn đưa cho máy tính

C. Mỗi câu lệnh yêu cầu máy tính thực hiện một hành động cụ thể

D. Chương trình Python bao gồm các số 0 và 1

Câu hỏi 4.2 Quá trình thông dịch và thực thi lệnh là gì? Phát biểu nào không đúng?

A. Bạn viết lệnh Python (ví dụ: print("Xin chào")). Trình thông dịch Python (python.exe) đọc dòng lệnh này

B. Trình thông dịch sẽ dịch lệnh Python sang tiếng Anh

C. Máy tính thực thi mã máy (hiển thị "Xin chào" lên màn hình)

D. Quá trình này lặp lại cho đến hết chương trình

Câu hỏi 4.3 Phát biểu về thụt lề, và chú thích. Phát biểu nào không đúng?

A. Thụt lề là việc bạn dịch chuyển một đoạn mã vào bên trong (thường là dùng 4 dấu cách hoặc 1 phím Tab) so với lề bên phải.

B. Chú thích được dùng để giải thích mã nguồn

C. Chú thích được dùng để ngăn thực thi mã

D. Thụt lề là việc bạn dịch chuyển một đoạn mã vào bên trong (thường là dùng 4 dấu cách hoặc 1 phím Tab) so với lề bên trái.

-----

4.1 (D), 4.2 (B), 4.3 (A)

4. Python Syntax

By this lesson, you have already:

- Successfully installed the interpreter (Python.exe)

- Learned how to write Python code (programming) in different environments (CMD, IDLE, Notepad, VS Code)

- Known how to interpret and run a Python program

In this section, we begin learning about the Python language itself.

Learning the Python language is similar to learning a foreign language (like English). The ultimate goal of learning a foreign language is to be able to use it—for instance, if you learn English, you must be able to read English documents and talk to English or American people. The same applies to Python: you must know how to use "Python language" to communicate with the computer, to use Python to command the computer to do what you want, and to read a piece of Python source code and understand what it does and what result it produces.

4.1 What is a Program?

Programming is the process of creating programs. So, what is a program?

A Program is a collection of instructions (statements) written in a programming language (e.g., Python), arranged in a specific order for the computer to perform a specific task (e.g., launching a game, performing a calculation, displaying a message).

Example:

# This is a simple Python program: 

print("Chào bạn!") # Instruction 1: Asks the computer to print the text "Chào bạn!"

print("Hôm nay là thứ mấy?") # Instruction 2: Asks the computer to print the question

# This program performs the task of basic communication

You can think of a Python Program as a book of drink recipes. The computer reads and executes each instruction in the recipe to create a drink.

What is a Statement?

If a Python Program is the book of drink recipes, then a Statement is each step in that recipe.

A Statement is a single, complete instruction that you give to the computer. Each statement asks the computer to perform a specific action.

Examples:

- String Output Statement: print("Chào bạn!") is a statement

- Assignment Statement: ten = "Tèo" is a statement, asking the computer to store the string "Tèo" under the name ten

- Calculation Statement: tong = 5 + 3 is a statement, asking the computer to calculate the sum and store the result.

What is a Code Block?

Sometimes, to perform a larger action, you need to group many small steps together.

A Code Block (or block of code) is a group of related statements placed together, which are usually executed as a unified unit (e.g., only running when a certain condition is met).

In Python, code blocks are defined using Indentation. Statements with the same level of indentation belong to the same block.

Example (IF Code Block):

diem = 9


# This is the conditional statement

if diem >= 8:

    # The 2 statements below belong to the same code block

    # Because they are both indented inwards

    print("Bạn đạt điểm Giỏi!")

    print("Xin chúc mừng!")

4.2 The Interpretation and Execution Process

Computer hardware cannot understand the Python language; it only understands binary code (0s and 1s). Therefore, to execute your program, the computer must perform an intermediate step called Interpretation.

The process of interpretation is the job of the Interpreter. It acts like a real-time translator: it reads each line of Python code you write, translates that line into machine language, and commands the computer to execute it immediately, before moving to the next line.

Steps Involved:

- You write a Python statement (e.g., print("Xin chào"))

- The Python Interpreter (python.exe) reads this line of code

- It translates this statement into machine code (0s and 1s)

- The computer executes the machine code (displays "Xin chào" on the screen)

- This process repeats until the end of the program.

Because Python is an interpreted language, it makes checking and debugging easier. If an error occurs on a certain line, the program will stop immediately at that line and report the error.

4.3 Indentation

What is Indentation?

In other programming languages, curly braces { } are used to group statements. But in Python, we use Indentation to do this.

Indentation is the act of shifting a piece of code inwards (usually by 4 spaces or 1 Tab key) relative to the left margin.

Indentation helps Python determine which statement belongs to which group (called a Code Block). This is the only way for Python to define the structure of the program.

Example: Distinguishing between CORRECT and MISSING Indentation.

Imagine you are setting a condition: "If I have money, I will buy a cake and a carton of milk."

Case 1: Correct Indentation (Python understands it as a Code Block)

# Declare variable

co_tien = True


# Conditional statement (IF)

if co_tien:

    # THE TWO STATEMENTS BELOW ARE INDENTED

    # Python understands: If co_tien is True, execute both of these statements.

    print("Mua một cái bánh")

    print("Mua một hộp sữa")

# This statement is not indented, so it will always run, regardless of the IF condition.

print("Về nhà")

Run Result:

Mua một cái bánh

Mua một hộp sữa

Về nhà

Case 2: Missing Indentation (Python reports a Syntax Error) If you forget to indent, the program will immediately report an error because Python doesn't know if the statement print("Mua một cái bánh") belongs to the if condition or not.

co_tien = True


if co_tien:

print("Mua một cái bánh") # ERROR: Indentation is required here!

print("Mua một hộp sữa")

Run Result:

IndentationError: expected an indented block

Programming Rules for Indentation:

- Consistency: You must use indentation consistently throughout the entire program (usually 4 spaces for each level of indentation)

- When is Indentation Needed? Whenever you use statements that create a new code block, such as:

    + Conditionals: if, elif, else

    + Loops: for, while

    + Functions: def

    + Classes: class In summary: Indentation not only makes Python code more readable but is also a mandatory part of the syntax. If you indent incorrectly, the program will not run.

4.4 Comments

What is a Comment?

You can imagine a Comment as the quick notes you write in the margin of a book or a small explanation in your exercise notebook.

A Comment is text that you write in a Python program, but these lines are only for human readers (you, colleagues, friends, or the teacher). The Python Interpreter will completely ignore them when running the program.

Most Important Uses:

- Explain Code: Helps you (or others) understand what a complex piece of code is doing, or why you wrote it that way

- Temporarily Disable Code: Helps you temporarily turn off a statement to check for bugs, without having to delete it.

How to Create Comments in Python

In Python, there are two main ways to create comments:

Single-line Comment (Using the # sign)

To turn a line into a Comment, simply place the hash sign (#) at the beginning of the line or after a statement.

Example:

# This is a comment, Python will not execute this line.


ten = "Bình"

diem = 10 # Comment next to the statement: Assigns the maximum score

print(f"Họ tên: {ten}")

print(f"Điểm số: {diem}")

Multi-line Comment (Using three double quotes """)

If you have many lines you want to annotate (e.g., describing the entire program or a large function in detail), you can use three double quotes (""") at the start and end of the comment block.

Example:

"""

This program was written on 18/11/2025.

Purpose: Calculate the sum and difference of two numbers.

Programmer: Student 8A.

"""

so_a = 5

so_b = 3

tong = so_a + so_b

print(f"Tổng là: {tong}")

In summary: Comments are tools that make your code easier to understand and maintain, and the computer will not execute them.

4.5 Exercises and Questions

Exercise

Exercise 4a. Write and run the code snippets in the theoretical section.

Questions

Question 4.1 What is a Program? Which statement is incorrect?

A. A program is a collection of statements

B. A statement is a single, complete instruction that you give to the computer

C. Each statement asks the computer to perform a specific action

D. A Python program consists of 0s and 1s

Question 4.2 What is the interpretation and execution process? Which statement is incorrect?

A. You write a Python statement (e.g., print("Xin chào")). The Python Interpreter (python.exe) reads this line of code. 

B. The Interpreter translates the Python statement into English. 

C. The computer executes the machine code (displays "Xin chào" on the screen). 

D. This process repeats until the end of the program.

Question 4.3 Statements about indentation and comments. Which statement is incorrect?

A. Indentation is the act of shifting a piece of code inwards (usually using 4 spaces or 1 Tab key) relative to the right margin. 

B. Comments are used to explain the source code. 

C. Comments are used to temporarily disable code execution. 

D. Indentation is the act of shifting a piece of code inwards (usually using 4 spaces or 1 Tab key) relative to the left margin.

-----
Bài sau: