[Công nghệ Thông tin] -- [Web] -- [Công nghệ phần mềm] -- [PhoThong] -- [Đăng ký các khóa học] -- [Langbiang's Portfolio] -- [Học viên cũ] -- [10.000 giờ]
--------------- <> -----------------
---  KHOA HỌC - CÔNG NGHỆ - GIÁO DỤC - VIỆC LÀM --->>>  CÁC KHÓA HỌC...
---  Nhận làm website, web app, chạy quảng cáo, digital marketing --->>>  LIÊN HỆ...

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 thực hành (4) - Gỡ lỗi chương trình

Bài trước: Python basic (2): Syntax

-----
4. Gỡ lỗi chương trình

Như đã đề cập, để tạo ra một chương trình trong Python, chúng ta cần thực hiện 5 bước:

- Phân tích bài toán và thiết kế thuật toán

- Lập trình

- Thông dịch và thực thi

- Kiểm thử và gỡ lỗi

- Hiển thị kết quả 

Ở các phần trước chúng ta đã làm quen với một số bước như lập trình, thông dịch và thực thi, hiển thị kết quả.

Phần này, chúng ta sẽ tìm hiểu về Gỡ lỗi chương trình.

4.1 Gỡ lỗi chương trình

Trong lập trình, "lỗi" (bug) là những sai sót trong mã nguồn, khiến chương trình không hoạt động như mong đợi. Lỗi có thể dẫn đến nhiều kết quả khác nhau, từ việc chương trình bị treo, đưa ra kết quả sai, hoặc thậm chí gây ra sự cố bảo mật.

Các loại lỗi thường gặp: 

- Lỗi cú pháp (syntax error)

- Lỗi logic (logical error)

- Lỗi khi chạy (runtime error)

- Lỗi kiểu dữ liệu (type error)

- Lỗi tràn bộ nhớ (memory overflow)

- Lỗi bảo mật (security vulnerability)

Gỡ lỗi là gì?

Gỡ lỗi (debugging) là quá trình tìm kiếm và loại bỏ các lỗi trong mã nguồn của chương trình máy tính.

Để gỡ lỗi, chúng ta thực hiện theo các bước sau:

- Xác định lỗi: dựa vào thông báo lỗi, kiểm tra kết quả đầu ra chương trình, hoặc sử dụng các công cụ gỡ lỗi để xác định xem chương trình đang bị lỗi gì? Ở dòng mã nào?

- Phân tích lỗi: phân tích, phỏng đoán xem tại sao lại có lỗi.

- Sửa lỗi: khi đã biết được lỗi, chúng ta sẽ thực hiện sửa lại mã nguồn để chương trình chạy đúng.

- Kiểm tra lại: chạy lại chương trình để đảm bảo không còn lỗi.

4.2 Thực hành gỡ lỗi

Lỗi cú pháp

Lỗi cú pháp (syntax error) là loại lỗi xảy ra khi mã nguồn của chương trình vi phạm các quy tắc cú pháp của ngôn ngữ lập trình. Nói một cách đơn giản, lỗi cú pháp xảy ra khi bạn viết mã nguồn không đúng "ngữ pháp" mà ngôn ngữ lập trình đó yêu cầu.

Ví dụ 1:

Bạn tạo một chương trình Python, ví dụ loiCuPhap1.py với nội dung sau:

[loiCuPhap1.py]

# dòng mã sau bị lỗi cú pháp

print("hi ban Teo"

Mở chương trình cửa sổ dòng lệnh, thực thi chương trình, bạn sẽ nhận được thông báo lỗi như sau:

E:\pythonLabs>py loicuphap1.py

  File "E:\pythonLabs\loicuphap1.py", line 1

    print("hi ban Teo"

         ^

SyntaxError: '(' was never closed

Khi gặp lỗi, việc đầu tiên là đọc và hiểu thông báo lỗi nói gì?

Ví dụ, ở lỗi phía trên, máy tính thông báo là:

- Lỗi xảy ra ở hàng số 1 (line 1), trong tập tin loiCuPhap1.py

- Đây là lỗi cú pháp (Syntax Error), xảy ra tại dấu (^), nội dung lỗi là: có mở ngoặc nhưng không đóng ( ‘(‘ was never close).

- Cách sửa lỗi: là tìm tới vị trí bị lỗi: dòng số 1 trong tập tin loiCuPhap1.py, thêm dấu )

- Chạy lại chương trình, bạn sẽ không còn thấy thông báo lỗi nữa, thấy có dòng chữ hi ban Teo xuất ra màn hình.

Ví dụ 2:

Tạo một chương trình Python, ví dụ loiCuPhap2.py với nội dung sau:

[loiCuPhap2.py]

# dòng mã sau bị lỗi cú pháp

a = 3

if a > 0:

print("a là số dương")

Mở chương trình cửa sổ dòng lệnh, thực thi chương trình, bạn sẽ nhận được thông báo lỗi như sau:

E:\pythonLabs>py loicuphap2.py

  File "E:\pythonLabs\loicuphap2.py", line 4

    print(f"{a} là số dương")

    ^^^^^

IndentationError: expected an indented block after 'if' statement on line 3

- Đọc thông báo, để xác định lỗi

- Lỗi xảy ra ở hàng số 4 (line 4), trong tập tin loiCuPhap2.py

- Đây là lỗi cú pháp (cụ thể là lỗi liên quan đến thụt lề - IndentationError), xảy ra tại dấu (^^^^^), nội dung lỗi là: mong đợi một dấu thụt lề cho đoạn mã sau lệnh if ở dòng số 3.

- Cách sửa lỗi: là tìm tới vị trí bị lỗi: dòng số 4 trong tập tin loiCuPhap2.py, thụt lề cho lệnh print()

- Chạy lại chương trình, bạn sẽ không còn thấy thông báo lỗi nữa, thấy có dòng chữ 3 là số dương xuất ra màn hình.

4.3 Lập trình cũng là một cách để học tư duy

Tư duy (thinking) là gì?

Tư duy là cách mà bộ não của chúng ta suy nghĩ, giải quyết vấn đề hoặc hiểu về thế giới xung quanh. Nó giống như một "công cụ" trong đầu giúp ta tưởng tượng, phân tích, và đưa ra quyết định. Nói đơn giản, tư duy là khi bạn dùng đầu óc để nghĩ xem làm thế nào để làm một việc gì đó hoặc hiểu một điều gì đó.

Bạn nào chỉ chờ có hướng dẫn từng bước để làm theo thì khác gì cái máy, mình là con người mà, phải hơn cái máy chứ! Biến cái máy (máy tính, robot, chatbot, AI) trở thành công cụ để hỗ trợ con người trong quá trình tư duy, làm việc.

Một số ví dụ về tư duy.

Khi bạn chơi cờ:

- Bạn không chỉ di chuyển quân cờ một cách ngẫu nhiên, mà còn suy nghĩ về những nước đi tiếp theo của mình và của đối thủ.

- Bạn dự đoán những tình huống có thể xảy ra, và tìm ra những chiến thuật tốt nhất.

- Đó chính là tư duy chiến lược.

Khi bạn viết văn:

- Bạn không chỉ viết ra những câu văn đơn giản, mà còn suy nghĩ về cách diễn đạt ý tưởng của mình một cách rõ ràng và hấp dẫn.

- Bạn sắp xếp các ý tưởng theo một trình tự logic, và sử dụng ngôn ngữ một cách sáng tạo.

- Đó chính là tư duy sáng tạo.

Khi bạn sửa chữa một đồ vật bị hỏng:

- Bạn không chỉ thử một cách ngẫu nhiên, mà còn suy nghĩ về nguyên nhân gây ra hỏng hóc.

- Bạn phân tích cấu tạo của đồ vật, và tìm ra cách sửa chữa hiệu quả nhất.

- Đó chính là tư duy logic và phân tích.

Tư duy giúp chúng ta:

- Hiểu rõ hơn về thế giới xung quanh.

- Giải quyết vấn đề một cách hiệu quả.

- Đưa ra những quyết định sáng suốt.

- Sáng tạo ra những ý tưởng mới. 

- Học hỏi và phát triển bản thân.

Tư duy là một kỹ năng rất quan trọng, và chúng ta có thể rèn luyện nó bằng cách đọc sách, học hỏi, và thực hành.

Thông qua lập trình, bạn sẽ rèn luyện các phương pháp tư duy sau:

- Tư duy của một nhà toán học: sử dụng ngôn ngữ hình thức (ngôn ngữ lập trình) để biểu thị các ý tưởng.

- Tư duy của một kỹ sư: thiết kế mọi thứ, lắp ráp các thành phần thành một hệ thống và đánh giá kết quả khi thay đổi các giải pháp.

- Tư duy của một nhà khoa học: quan sát hành vi của các hệ thống phức tạp, hình thành giả thuyết và kiểm nghiệm các dự đoán.

4.4 Bài tập

Bài tập 4.1 Tìm lỗi, ghi lại lỗi và sửa lỗi cú pháp sau:

[baiTap4_1.py]

# dòng mã sau bị lỗi cú pháp

printer("hi ban Ti")

Bài tập 4.2 Tìm lỗi, ghi lại lỗi và sửa lỗi cú pháp sau:

[baiTap4_2.py]

# đoạn mã sau bị lỗi cú pháp

a = 6

b = 5

print(''ket qua: '')

print(a + b)

Câu hỏi 4.3 Lỗi lập trình là gì? Phát biểu nào sau đây không đúng?

A. Lỗi lập trình là những sai sót trong mã nguồn khiến chương trình không hoạt động như mong đợi.

B. Lỗi lập trình chỉ xảy ra khi chương trình đang chạy, không thể xảy ra trong quá trình viết mã (lập trình).

C. Lỗi lập trình có thể dẫn đến nhiều kết quả khác nhau, từ việc chương trình bị treo đến gây ra sự cố bảo mật.

D. Các loại lỗi lập trình thường gặp bao gồm lỗi cú pháp, lỗi logic, và lỗi kiểu dữ liệu.

Câu hỏi 4.4 Tư duy là gì? Phát biểu nào sau đây không đúng?

A. Tư duy là cách mà bộ não của chúng ta suy nghĩ, giải quyết vấn đề hoặc hiểu về thế giới xung quanh.

B. Tư duy giúp chúng ta hiểu rõ hơn về thế giới xung quanh, giải quyết vấn đề hiệu quả và đưa ra quyết định sáng suốt.

C. Tư duy là một kỹ năng quan trọng có thể rèn luyện bằng cách đọc sách, học hỏi và thực hành.

D. Tư duy chỉ đơn thuần là việc làm theo các hướng dẫn có sẵn, không cần suy nghĩ sáng tạo.

-----
Cập nhật: 28/3/2025
-----
Bài sau: Python thực hành (5) - Kiểu dữ liệu số nguyên
-----