Home Blog Page 24

Sử dụng override trong Java sao cho hiệu quả?

override trong java

Trong lập trình hướng đối tượng (OOP), việc ghi đè phương thức (method overriding) là một tính năng cho phép con lớp định nghĩa lại các phương thức được kế thừa từ lớp cha. Phương thức ghi đè sẽ có cùng tên và tham số với phương thức trong lớp cha, nhưng có thể có hành vi khác nhau. Từ khóa override được sử dụng trong java để chỉ ra rằng phương thức trong con lớp đang ghi đè phương thức của lớp cha. Từ khóa này giúp trình biên dịch Java kiểm tra xem phương thức được ghi đè có tuân theo các quy tắc nhất định hay không.

Tìm hiểu về từ khóa override trong Java

Trong Java, từ khóa override được sử dụng để ghi đè phương thức của lớp cha trong lớp con. Điều này có nghĩa là khi một phương thức được gọi từ một đối tượng của lớp con, phương thức trong lớp con sẽ được thực thi thay vì phương thức trong lớp cha. Điều này cho phép chúng ta định nghĩa lại các phương thức đã có trong lớp cha và điều chỉnh hành vi của chúng theo ý muốn.

Để sử dụng từ khóa override, chúng ta cần thực hiện các bước sau:

  1. Tạo một con lớp kế thừa từ lớp cha có phương thức muốn ghi đè.
  2. Định nghĩa một phương thức mới trong con lớp có cùng tên và tham số với phương thức trong lớp cha.
  3. Sử dụng từ khóa override trước khai báo phương thức trong con lớp.

Ví dụ:

class Cha {
    public void inRa() {
        System.out.println("Đây là lớp cha");
    }
}

class Con extends Cha {
    @Override
    public void inRa() {
        System.out.println("Đây là lớp con");
    }
}

Trong ví dụ trên, phương thức inRa() trong lớp Con ghi đè phương thức inRa() của lớp Cha. Khi gọi phương thức inRa() từ lớp Con, trình biên dịch Java sẽ ưu tiên sử dụng phương thức ghi đè trong lớp Con.

>>> Xem thêm: Sử dụng List để quản lý dữ liệu trong Java

Cách sử dụng override trong Java

Để sử dụng override trong Java, chúng ta cần làm theo các bước sau:

  1. Xác định phương thức cần ghi đè trong lớp cha.
  2. Tạo một lớp con kế thừa từ lớp cha đó.
  3. Định nghĩa lại phương thức cần ghi đè trong lớp con với cùng tên và tham số như trong lớp cha.
  4. Sử dụng từ khóa override trước khai báo phương thức trong lớp con.

Ví dụ:

class Hinh {
    public void ve() {
        System.out.println("Đây là hình");
    }
}

class HinhChuNhat extends Hinh {
    @Override
    public void ve() {
        System.out.println("Đây là hình chữ nhật");
    }
}

Trong ví dụ trên, lớp HinhChuNhat kế thừa phương thức ve() từ lớp Hinh và ghi đè lại phương thức này để in ra “Đây là hình chữ nhật” thay vì “Đây là hình”.

Cập nhật thông tin tuyển dụng Java mới nhất tại TopDev

Lợi ích của việc sử dụng override trong Java

Việc sử dụng override trong Java mang lại nhiều lợi ích cho người lập trình, bao gồm:

  • Cho phép định nghĩa lại các phương thức đã có trong lớp cha theo ý muốn.
  • Giúp tăng tính linh hoạt và tái sử dụng code.
  • Có thể điều chỉnh hành vi của các phương thức đã có trong lớp cha mà không cần phải sửa đổi code gốc.
  • Giúp tăng tính đa hình trong lập trình hướng đối tượng.

override trong java

Các quy tắc khi sử dụng override trong Java

Khi sử dụng override trong Java, chúng ta cần tuân thủ các quy tắc sau:

  1. Phương thức trong lớp con phải có cùng tên và tham số với phương thức trong lớp cha.
  2. Phương thức trong lớp con phải có kiểu trả về giống hoặc là kiểu con của kiểu trả về của phương thức trong lớp cha.
  3. Phương thức trong lớp con không được có phạm vi truy cập nhỏ hơn phạm vi truy cập của phương thức trong lớp cha.
  4. Nếu phương thức trong lớp cha là final, thì không thể ghi đè phương thức đó trong lớp con.
  5. Nếu phương thức trong lớp cha là static, thì không thể ghi đè phương thức đó trong lớp con.

So sánh giữa override và overloading trong Java

Override và overloading là hai khái niệm quan trọng trong lập trình hướng đối tượng. Tuy nhiên, chúng có những điểm khác biệt cơ bản như sau:

Override Overloading
Ghi đè lại phương thức đã có trong lớp cha. Định nghĩa thêm các phương thức mới với cùng tên nhưng khác tham số trong cùng một lớp.
Phương thức ghi đè phải có cùng tên và tham số với phương thức trong lớp cha. Các phương thức overloading phải có cùng tên nhưng khác tham số với nhau.
Phương thức ghi đè có thể có hành vi khác hoặc giống với phương thức trong lớp cha. Các phương thức overloading phải có hành vi khác nhau.
Thực thi phương thức ghi đè khi gọi từ đối tượng của lớp con. Thực thi phương thức overloading dựa trên tham số truyền vào.

>>> Xem thêm: Tính trừu tượng (Abstraction) trong Java

Các ví dụ minh họa về override trong Java

Để hiểu rõ hơn về cách sử dụng override trong Java, chúng ta cùng xem qua một số ví dụ sau:

Ví dụ 1: Ghi đè phương thức toString()

Trong Java, lớp Object là lớp cha của tất cả các lớp khác. Lớp này có một phương thức toString() để trả về chuỗi biểu diễn đối tượng dưới dạng String. Chúng ta có thể ghi đè phương thức này để định nghĩa lại cách hiển thị thông tin của đối tượng.

class SinhVien {
    private String ten;
    private int tuoi;

    public SinhVien(String ten, int tuoi) {
        this.ten = ten;
        this.tuoi = tuoi;
    }

    @Override
    public String toString() {
        return "Tên: " + ten + ", Tuổi: " + tuoi;
    }
}

public class Main {
    public static void main(String[] args) {
        SinhVien sv = new SinhVien("John", 20);
        System.out.println(sv); // Kết quả: Tên: John, Tuổi: 20
    }
}

Ví dụ 2: Ghi đè phương thức equals()

Phương thức equals() trong lớp Object được sử dụng để so sánh hai đối tượng. Chúng ta có thể ghi đè phương thức này để định nghĩa lại cách so sánh giữa hai đối tượng của lớp con.

class NhanVien {
    private String maNV;
    private String ten;

    public NhanVien(String maNV, String ten) {
        this.maNV = maNV;
        this.ten = ten;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof NhanVien) {
            NhanVien nv = (NhanVien) obj;
            return this.maNV.equals(nv.maNV);
        }
        return false;
    }
}

public class Main {
    public static void main(String[] args) {
        NhanVien nv1 = new NhanVien("NV001", "John");
        NhanVien nv2 = new NhanVien("NV002", "Mary");
        NhanVien nv3 = new NhanVien("NV001", "Peter");

        System.out.println(nv1.equals(nv2)); // Kết quả: false
        System.out.println(nv1.equals(nv3)); // Kết quả: true
    }
}
 

override trong java

Những lỗi thường gặp khi sử dụng override trong Java

Khi sử dụng override trong Java, chúng ta cần lưu ý một số lỗi thường gặp sau đây:

  • Thiếu từ khóa @Override: Nếu không sử dụng từ khóa override trước khai báo phương thức trong lớp con, trình biên dịch sẽ không nhận diện được rằng phương thức này đang ghi đè phương thức của lớp cha.
  • Sai kiểu trả về: Phương thức trong lớp con phải có kiểu trả về giống hoặc là kiểu con của kiểu trả về của phương thức trong lớp cha. Nếu không tuân thủ điều này, trình biên dịch sẽ báo lỗi.
  • Sai số lượng tham số: Phương thức trong lớp con phải có cùng số lượng và kiểu tham số với phương thức trong lớp cha. Nếu không tuân thủ điều này, trình biên dịch sẽ báo lỗi.
  • Phạm vi truy cập sai: Phương thức trong lớp con không được có phạm vi truy cập nhỏ hơn phạm vi truy cập của phương thức trong lớp cha. Nếu không tuân thủ điều này, trình biên dịch sẽ báo lỗi.

Cách ghi đè phương thức trong Java

Để ghi đè một phương thức trong Java, chúng ta cần làm theo các bước sau:

  1. Xác định phương thức cần ghi đè trong lớp cha.
  2. Tạo một lớp con kế thừa từ lớp cha đó.
  3. Định nghĩa lại phương thức cần ghi đè trong lớp con với cùng tên và tham số như trong lớp cha.
  4. Sử dụng từ khóa override trước khai báo phương thức trong lớp con.

Ví dụ:

class Hinh {
    public void ve() {
        System.out.println("Đây là hình");
    }
}

class HinhChuNhat extends Hinh {
    @Override
    public void ve() {
        System.out.println("Đây là hình chữ nhật");
    }
}

Trong ví dụ trên, lớp HinhChuNhat kế thừa phương thức ve() từ lớp Hinh và ghi đè lại phương thức này để in ra “Đây là hình chữ nhật” thay vì “Đây là hình”.

Sự khác biệt giữa override và implement trong Java

Override và implement là hai khái niệm quan trọng trong lập trình hướng đối tượng. Tuy nhiên, chúng có những điểm khác biệt sau:

  • Override là việc ghi đè lại phương thức của lớp cha trong lớp con, còn implement là việc triển khai các phương thức của một interface trong lớp.
  • Override chỉ áp dụng cho các phương thức, còn implement có thể áp dụng cho cả lớp và phương thức.
  • Một lớp chỉ có thể kế thừa từ một lớp cha, nhưng có thể triển khai nhiều interface.

Các trường hợp không nên sử dụng override trong Java

Mặc dù override là một tính năng hữu ích trong Java, nhưng cũng có những trường hợp không nên sử dụng nó. Dưới đây là một số trường hợp không nên sử dụng override trong Java:

  • Khi không muốn thay đổi hành vi của phương thức trong lớp cha: Nếu phương thức trong lớp cha đã hoạt động đúng và không cần thay đổi, ta không nên ghi đè lại phương thức này trong lớp con.
  • Khi không có quyền truy cập vào mã nguồn của lớp cha: Nếu lớp cha được định nghĩa bên ngoài và không thể sửa đổi, ta không thể ghi đè lại phương thức của lớp cha.
  • Khi không có nhu cầu sử dụng lại mã nguồn của phương thức trong lớp cha: Nếu không cần thiết sử dụng lại mã nguồn của phương thức trong lớp cha, ta không nên ghi đè lại phương thức này trong lớp con.

Kết luận

Trong bài viết này, chúng ta đã tìm hiểu về từ khóa override trong Java và cách sử dụng nó để ghi đè lại các phương thức của lớp cha trong lớp con. Chúng ta cũng đã thấy được lợi ích của việc sử dụng override và những lỗi thường gặp khi sử dụng nó. Ngoài ra, chúng ta cũng đã so sánh giữa override và overloading, implement và điểm khác biệt giữa chúng. Hy vọng bài viết này sẽ giúp bạn hiểu rõ hơn về tính năng quan trọng này trong lập trình java.

Bài viết chỉ mang tính chất tham khảo

Nội dung được tổng hợp bởi AI và điều chỉnh bởi Ban Biên tập TopDev 

Cập nhật tin tuyển dụng IT lương cao tại TopDev

Sử dụng List để quản lý dữ liệu trong Java

list trong java

Trong lập trình, việc quản lý dữ liệu là một phần quan trọng và không thể thiếu. Và trong Java, List là một trong những cấu trúc dữ liệu quan trọng nhất để lưu trữ và quản lý các bộ sưu tập các phần tử cùng kiểu dữ liệu. Trong bài viết này, hãy cùng TopDev tìm hiểu về cách sử dụng List trong Java và các tính năng quan trọng của nó.

Cách sử dụng List trong Java

List là một trong những cấu trúc dữ liệu phổ biến nhất trong Java và được sử dụng rộng rãi trong các ứng dụng thực tế. Nó cung cấp cho chúng ta một cách tiện lợi để lưu trữ và quản lý các phần tử theo thứ tự và dưới đây là một số cách chúng ta có thể sử dụng List trong Java:

  • Lưu trữ danh sách các sản phẩm trong một cửa hàng trực tuyến.
  • Quản lý danh sách các khách hàng của một công ty.
  • Lưu trữ thông tin về các bài viết trên một trang blog.
  • Quản lý danh sách các sinh viên trong một lớp học.

Với những ví dụ trên, chúng ta có thể thấy rằng List là một công cụ hữu ích để quản lý các bộ sưu tập dữ liệu trong nhiều lĩnh vực khác nhau.

Tìm hiểu về interface List trong Java

Trong lập trình Java, List được biểu diễn bằng giao diện java.util.List. Điều này có nghĩa là chúng ta không thể tạo một đối tượng List trực tiếp mà phải sử dụng một trong hai triển khai của giao diện này: ArrayList hoặc LinkedList. Giao diện List cung cấp một số phương thức để thao tác với các phần tử trong danh sách. Chúng ta sẽ tìm hiểu về các phương thức này trong phần tiếp theo.

list trong java

Các phương thức của List

Giao diện List cung cấp một số phương thức để thao tác với các phần tử trong danh sách. Dưới đây là một số phương thức quan trọng nhất của List:

  • add(E element): Thêm một phần tử vào cuối danh sách.
  • remove(int index): Xóa phần tử tại chỉ mục đã cho.
  • get(int index): Lấy phần tử tại chỉ mục đã cho.
  • set(int index, E element): Cập nhật phần tử tại chỉ mục đã cho với một phần tử mới.
  • indexOf(E element): Tìm kiếm phần tử đầu tiên trong danh sách bằng với phần tử đã cho và trả về chỉ mục của nó.
  • size(): Trả về số phần tử trong danh sách.

Để hiểu rõ hơn về cách sử dụng các phương thức này, mình cùng đi vào ví dụ cụ thể ở nội dung ngay sau đây.

Sự khác biệt giữa ArrayList và LinkedList trong Java

Trong Java, có hai triển khai chính của giao diện List: ArrayList và LinkedList. Chúng khác nhau về cách chúng lưu trữ và truy cập các phần tử. Dưới đây là một bảng so sánh giữa hai triển khai này:

ArrayList LinkedList
Lưu trữ các phần tử theo thứ tự Lưu trữ các phần tử không theo thứ tự
Có thể truy cập các phần tử nhanh chóng bằng chỉ mục Thời gian truy cập các phần tử tùy thuộc vào vị trí của chúng trong danh sách
Được sử dụng khi cần thao tác với các phần tử theo thứ tự Được sử dụng khi cần thêm hoặc xóa các phần tử thường xuyên
Tốn ít bộ nhớ hơn so với LinkedList Tốn nhiều bộ nhớ hơn do cần lưu trữ các con trỏ giữa các phần tử

Từ bảng so sánh trên, chúng ta có thể thấy rằng cả ArrayList và LinkedList đều có những ưu điểm và nhược điểm riêng. Do đó, chúng ta cần cân nhắc kỹ lưỡng khi lựa chọn triển khai nào phù hợp với yêu cầu của mình.

>>> Để hiểu hơn về sự khác biệt giữa ArrayList và LinkedList, bạn có thể truy cập bài viết phân biệt ArrayList và LinkedList.

Cách tạo và sử dụng ArrayList trong Java

Để tạo một đối tượng ArrayList trong Java, chúng ta có thể sử dụng cú pháp sau:

ArrayList tênBiến = new ArrayList();

Ví dụ: để tạo một danh sách các số nguyên, chúng ta có thể làm như sau:

ArrayList numbers = new ArrayList();

Sau khi đã tạo được đối tượng ArrayList, chúng ta có thể sử dụng các phương thức của List để thao tác với các phần tử trong danh sách. Ví dụ:

numbers.add(5); // Thêm số 5 vào cuối danh sách
numbers.add(10); // Thêm số 10 vào cuối danh sách
numbers.add(0, 15); // Thêm số 15 vào vị trí đầu tiên của danh sách
numbers.remove(1); // Xóa phần tử ở vị trí thứ 2 trong danh sách
int firstNumber = numbers.get(0); // Lấy giá trị của phần tử đầu tiên trong danh sách

Làm thế nào để sắp xếp một List trong Java?

Để sắp xếp một List trong Java, chúng ta có thể sử dụng phương thức sort() của lớp Collections. Ví dụ:

ArrayList numbers = new ArrayList();
numbers.add(5);
numbers.add(10);
numbers.add(3);
numbers.add(8);

Collections.sort(numbers); // Sắp xếp các số theo thứ tự tăng dần

System.out.println(numbers); // Kết quả: [3, 5, 8, 10]

Ngoài ra, chúng ta cũng có thể sử dụng một Comparator để chỉ định cách sắp xếp các phần tử trong danh sách. Ví dụ: để sắp xếp các số theo thứ tự giảm dần, chúng ta có thể làm như sau:

Comparator comparator = Collections.reverseOrder();
Collections.sort(numbers, comparator); // Sắp xếp các số theo thứ tự giảm dần

System.out.println(numbers); // Kết quả: [10, 8, 5, 3]

Tuyển dụng Java lương cao, xem ngay tại TopDev

Cách lặp qua các phần tử của List trong Java

Để lặp qua các phần tử của một List trong Java, chúng ta có thể sử dụng vòng lặp for hoặc foreach. Ví dụ:

ArrayList names = new ArrayList();
names.add("John");
names.add("Mary");
names.add("David");

// Sử dụng vòng lặp for
for (int i = 0; i  fruits = new ArrayList();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");

fruits.remove(1); // Xóa phần tử ở vị trí thứ 2 (tức là "Banana")
System.out.println(fruits); // Kết quả: [Apple, Orange]

fruits.remove("Orange"); // Xóa phần tử có giá trị là "Orange"
System.out.println(fruits); // Kết quả: [Apple]

Phương thức clear() sẽ xóa tất cả các phần tử trong danh sách. Ví dụ:

fruits.clear(); // Xóa tất cả các phần tử trong danh sách
System.out.println(fruits); // Kết quả: []

>>> Xem thêm: Lập trình đa luồng trong Java (Java Multi-threading)

Các ví dụ thực tế về việc sử dụng List

Để hiểu rõ hơn về cách sử dụng List trong các ứng dụng thực tế, chúng ta sẽ đi vào một số ví dụ sau:

Ví dụ 1: Quản lý danh sách sinh viên

Hãy thử tưởng tượng một ngày đẹp trời, một người thân hay người bạn làm giáo viên của bạn nhờ bạn tạo file quản lý học sinh/sinh viên thì đây là lúc bạn “show” kỹ năng của mình thông qua việc sử dụng List. Mỗi sinh viên sẽ có các thông tin như tên, tuổi và điểm số như ví dụ dưới đây:

class Student {
    String name;
    int age;
    double score;

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
}

// Tạo một danh sách các sinh viên
ArrayList students = new ArrayList();

// Thêm các sinh viên vào danh sách
students.add(new Student("John", 20, 8.5));
students.add(new Student("Mary", 19, 9.0));
students.add(new Student("David", 21, 7.0));

// In ra thông tin của từng sinh viên
for (Student student : students) {
    System.out.println("Name: " + student.name);
    System.out.println("Age: " + student.age);
    System.out.println("Score: " + student.score);
} 

Kết quả:

Name: John
Age: 20
Score: 8.5
Name: Mary
Age: 19
Score: 9.0
Name: David
Age: 21
Score: 7.0 

list trong java

Ví dụ 2: Lưu trữ lịch sử giao dịch của khách hàng

Trong một ứng dụng quản lý tài chính, bạn cũng có thể sử dụng List để lưu trữ lịch sử giao dịch của khách hàng và mỗi giao dịch sẽ có các thông tin như ngày tháng, loại giao dịch và số tiền. Hãy cùng TopDev xét ví dụ dưới đây:

class Transaction {
    LocalDate date;
    String type;
    double amount;

    public Transaction(LocalDate date, String type, double amount) {
        this.date = date;
        this.type = type;
        this.amount = amount;
    }
}
// Tạo một danh sách các giao dịch
ArrayList transactions = new ArrayList();

// Thêm các giao dịch vào danh sách
transactions.add(new Transaction(LocalDate.of(2021, 10, 1), "Nạp tiền", 1000000));
transactions.add(new Transaction(LocalDate.of(2021, 10, 5), "Rút tiền", 500000));
transactions.add(new Transaction(LocalDate.of(2021, 10, 10), "Thanh toán hóa đơn", 200000));

// In ra thông tin của từng giao dịch
for (Transaction transaction : transactions) {
    System.out.println("Date: " + transaction.date);
    System.out.println("Type: " + transaction.type);
    System.out.println("Amount: " + transaction.amount);
} 

Kết quả:

Date: 2021-10-01
Type: Nạp tiền
Amount: 1000000.0
Date: 2021-10-05
Type: Rút tiền
Amount: 500000.0
Date: 2021-10-10
Type: Thanh toán hóa đơn
Amount: 200000.0

Kết luận

Trong bài viết này, TopDev đã chia sẻ về cách sử dụng List trong Java, cách tạo và sử dụng ArrayList, cách sắp xếp một List, tối ưu hóa hiệu suất khi sử dụng List,…Hy vọng rằng với những thông tin này, các lập trình viên, nhất là các bạn fresher sẽ hiểu rõ hơn về cách sử dụng List trong Java và áp dụng được vào các dự án của mình.

Bài viết chỉ mang tính chất tham khảo

Nội dung được tổng hợp bởi AI và điều chỉnh bởi Ban Biên tập TopDev 

Cập nhật tin tuyển dụng IT lương cao tại TopDev

Headless CMS là gì? Headless CMS có tối ưu cho SEO không?

Headless CMS là gì?

Bài viết được sự cho phép bởi tác giả Sơn Dương

Trong một lần tình cờ lên Facebook, mình thấy một bạn hỏi về dự án xây dựng hệ thống CMS (Content Management System) bằng VueJS. Mình mới biết tới khái niệm Headless CMS, thực sự không biết Headless CMS là gì cả.

Thực ra Headless CMS xuất hiện từ lâu rồi, chẳng qua mình gà, ít tiếp xúc nên không biết thôi.

Nhân tiện đây thì chúng ta cùng tìm hiểu xem Headless CMS là gì và ưu điểm của nó so với CMS truyền thống như nào?

Headless CMS là gì?

Trước khi tìm hiểu khái niệm Headless CMS, chúng ta cần biết lịch sử hệ thống CMS đã.

CMS được hiểu là một hệ thống quản lý nội dung, giống như VNTALKING này đây, là một dạng của CMS.

Có thể bạn đã từng nghe tới các CMS nổi tiếng như WordPress, Joomla, NukeViet… Đây đều là các CMS theo mô hình truyền thống (Traditional CMS).

Các CMS truyền thống theo mô hình là đóng gói toàn bộ gồm backend + frontend + database. Tất cả sẽ liên kết chặt chẽ với nhau về mã nguồn, và chắc chắn không thể tách rời nhau được. Và khi deploy hay mở rộng hệ thống thì chỉ có hai cách: một là tăng cấu hình máy chủ (tăng CPU, tăng RAM), hoặc là dùng cân bằng tải – bốc toàn bộ mã nguồn và deploy trên nhiều server. Đây cũng chính là nhược điểm của CMS truyền thống.

Nhận thấy được điểm yếu trên, đồng thời khi các mô hình microservice phổ biến hơn, chưa kể giờ đây hình thức xem nội dung không chỉ trên web máy tính mà còn trên ứng dụng điện thoại, trên TV.v.v… Người ta nghĩ ra mô hình Headless CMS.

Hiểu nôm na, Headless CMS là mô hình mà các thành phần trong hệ thống sẽ xây dựng độc lập với nhau. Phần backend riêng, giao diện front end cho người dùng riêng, database cũng riêng, tất cả chúng sẽ được kết nối với nhau thông qua API.

Hình ảnh mô hình dưới đây sẽ mô tả rõ nhất.

Headless CMS là gì?

  So sánh Wordpress và Drupal: Lựa chọn CMS nào sẽ tốt hơn?

  Top 3 Laravel CMS được đánh giá cao

Ưu điểm của Headless CMS

Mỗi mô hình CMS đều có những ưu điểm riêng. Chứ không tại sao WordPress lại phổ biến đến như vậy.

Dưới đây là một số ưu điểm mà Headless CMS mang lại:

  • Khả năng mở rộng cao: Chính vì Headless CMS phát triển các thành phần theo kiểu phân tán, chia nhỏ hệ thống thành các phần độc lập với nhau. Nên khi thành phần nào có dấu hiệu tải cao, bạn có thể chỉ cần mở rộng hạ tầng riêng thành phần đó thay vì phải mở rộng hạ tầng cả hệ thống.
  • Linh động về công nghệ: Với Headless CMS, các developer có thể thoải mái sử dụng công nghệ mà mình ưu thích. Bởi vì phần giao diện tách biệt với phần core, nên bạn tha hồ chọn UI framework mà mình thích như React, Vue… Nhưng với các CMS truyền thống như WordPress thì hơi khó, bạn phải biết PHP, SQL trước đã rồi mới tính cái khác được
  • Dễ dàng hỗ trợ nhiều nền tảng: Vì headless có một phần API ở giữa trung gian, kết nối các thành phần. Nên bạn dễ dàng triển khai, bổ sung giao diện hỗ trợ nhiều nền tảng. Ví dụ, bạn dễ dàng xây dựng ứng dụng mobile tối ưu cho người dùng di động, điều mà CMS truyền thống thực hiện khó khăn hơn nhiều.
  • Bảo mật tốt hơn: Vì các thành phần giao tiếp với nhau qua API, nội dung được tách biệt khỏi giao diện nên nguy bị tấn công bởi các phần mềm độc hại thấp hơn nhiều so với CMS truyền thống.

Trên đây là 3 ưu điểm lớn nhất mà mình thấy ở Headless CMS, đặc biệt là ưu điểm số 2 – dưới góc độ của một developer.

Tham khảo việc làm WordPress hấp dẫn trên TopDev!

Khi nào sử dụng Headless CMS?

Dưới đây là một số ý tưởng mà bạn có thể nghĩ tới mô hình Headless CMS cho dự án sắp tới:

Ứng dụng web (sử dụng các JS framework phổ biến như React, Vue, Angular)

Tương tự như các trang thương mại điện tử như Shopee, Tiki… Họ sẽ xây dựng một hệ thống quản lý nội dung riêng biệt và cung cấp API ra ngoài. Sau đó họ sẽ xây dựng các ứng dụng web bằng các JS framework nổi tiếng. Điều này giúp cho họ dễ dàng thêm tính năng cho hệ thống và nhanh tới tay người dùng hơn nhiều.

Ứng dụng mobile

Khi bạn quyết định triển khai ứng dụng mobile cho hệ thống CMS, mình cá 99% bạn phải xây dựng API và cung cấp cho dự án mobile. Với CMS truyền thống. bạn cũng có thể tạo API được nhưng nó không linh hoạt và khó mở rộng hơn rất nhiều.

Với cách triển khai theo kiểu headless, bạn đã có sẵn API và dễ dàng cung cấp cho đội mobile.

Headless CMS có tối ưu cho SEO không?

Đây có lẽ là câu hỏi vô cùng quan trọng mà hầu hết ai muốn xây dựng CMS đều quan tâm.

Vì làm content mà không có ai xem thì thật là buồn phải không?

Mà muốn có nhiều người xem thì ít nhất phải tối ưu cho Google Search trước. Vì hiện tại Google vẫn đang là trùm tìm kiếm.

Câu trả lời tất nhiên là CÓ, tối ưu tốt cho SEO.

Tất nhiên, làm thế nào để nó tối ưu cho SEO thì hoàn toàn phụ thuộc vào bạn. Tại sao mình lại nói như vậy?

Với Headless CMS, phần nội dung được tách biệt và chỉ cung cấp ra ngoài thông qua API. Do đó, để tối ưu cho SEO, bạn phải thực hiện ở phần front end – thành phần giao diện người dùng. Lúc này, bạn cần phải chọn những công nghệ frontend được render phía server (người ta gọi là SSR – Server Side Rendering). Nếu bạn lại chọn kiểu front end dạng SPA (Single Page Application) thì lại thua đấy.

Một số framework UI hỗ trợ SSR như NuxtJS (dựa  trên Vue), NextJS (dựa trên React)… bạn có thể tham khảo.

Tạm kết

Trên đây là một chia sẻ về mô hình Headles CMS. Việc lựa chọn mô hình CMS truyền thống hay headless hoàn toàn phụ thuộc vào bài toán và nhu cầu thực tế của bạn.

Hy vọng qua bài viết này, bạn có hiểu biết cơ bản headless CMS là gì và có được lựa chọn cho mình khi gặp bài toán tương tự. Đừng ngần ngại để lại bình luận bên dưới để mọi người biết ý kiến của bạn nhé!

Bài viết gốc được đăng tải tại vntalking.com

Bạn có thể xem thêm:

Dev đừng bỏ lỡ Top tin tuyển dụng IT tại TopDev nhé!

Cách viết phần kỹ năng “chất như nước cất” cho CV của bạn

cách viết kỹ năng trong cv

Bài viết được sự cho phép của tác giả Lê Tuấn Anh

Là người làm công tác tư vấn hướng nghiệp và tìm việc, một trong các đầu việc mình làm là tư vấn CV cho các bạn có nhu cầu tìm/đổi việc. Tư vấn, tức là chỉ ra cho các bạn những lỗi sai, gợi ý cách viết mới phù hợp – chứ không phải viết hộ CV cho các bạn. CV của ai phải do chính người đó tự viết, như vậy mới đúng là hồ sơ tìm việc của mình. Một bản CV qua tư vấn không phải là bản CV hoàn hảo nộp đâu trúng đó, nhưng là bản CV có cơ hội trúng tuyển cao hơn và gây ấn tượng tốt hơn với nhà tuyển dụng.

Có rất nhiều thành tố tạo nên một bản CV hay, từ thông tin cá nhân, học vấn, kinh nghiệm, kỹ năng. Trong đó, kỹ năng là một phần mình thấy nhiều bạn viết qua loa và ít đầu tư vào nhất. Thực tế nếu đầu tư viết phần kỹ năng tốt, bạn có thể làm cho CV của mình gây ấn tượng hơn với nhà tuyển dụng, nộp đơn được vào các công việc trái ngành hoặc mình còn ít kinh nghiệm trong lĩnh vực đó.

Thực trạng viết phần kỹ năng hiện nay trong các CV?

Nếu bạn đã có CV, hãy mở CV hiện tại của bạn ra (hoặc xem CV của bạn bè xung quanh bạn) và xem xem hiện tại bạn đang có những từ khoá kiểu như Communication (giao tiếp), Teamwork (làm việc nhóm), MS Office, Presentation (thuyết trình) ở trong CV hay không? Nếu chỉ đang có các kỹ năng như trên, CV của bạn đang nằm trong nhóm “số đông”.

Khi đi tìm việc, chúng ta không muốn thuộc nhóm ứng viên “số đông”. Chúng ta cần là người đặc biệt, nổi bật, khác biệt so với các ứng viên khác, cộng thêm tiêu chí phù hợp với công việc, chúng ta sẽ là người được chọn. Vậy tại sao ghi những kỹ năng ở trên vào CV lại khiến chúng ta trở thành “số đông”?

Thứ nhất, không có số liệu chính xác, nhưng từ kinh nghiệm cá nhân của mình, cứ 10 CV thì có đến 7-8 CV chỉ ghi những kỹ năng trên mà không có các kỹ năng khác. Như vậy thì ai cũng giống ai.

Thứ hai, các kỹ năng mềm như giao tiếp, làm việc nhóm, thuyết trình, cộng với kỹ năng tin học văn phòng cơ bản gần như đang là những kỹ năng bắt buộc phải có, thông dụng với bất kỳ lĩnh vực, công việc nào – tức là công việc nào cũng cần. Chỉ ghi những kỹ năng như vậy vào CV không giúp cho người đọc biết được bạn đang định ứng tuyển kế toán, Marketing hay IT.

Tạo CV online nhanh chóng, đẹp dành cho dân IT

Dưới đây là một số hình ảnh ví dụ các “mẫu CV” trên mạng để bạn thấy người ta viết kỹ năng rất giống nhau.

cv

cv

cv

Cách Viết Kỹ Năng (Skills) Trong CV

  Phân tích “keyword” trong JD để viết CV hiệu quả

  Các kỹ năng cần có trong CV IT để chinh phục mọi nhà tuyển dụng

Một lỗi nhỏ nữa khi viết kỹ năng

Ngoài vấn đề viết kỹ năng chung chung như đã chia sẻ ở trên, có một vấn đề nữa liên quan đến kỹ năng mà bạn đọc cũng cần lưu ý đó là sử dụng các thanh đánh giá. Việc sử dụng các thanh đánh giá trong CV có thể giúp CV của bạn trông đẹp và xịn hơn, tuy nhiên hãy cẩn trọng khi sử dụng các thanh đánh giá. Thực sự rất khó để đánh giá kỹ năng làm việc nhóm của mình là 4/5, hay kỹ năng thuyết trình là 5/5 – không có tiêu chí rõ ràng xác nhận cho việc này. Nếu bạn có bằng TOEIC 550 hay bằng tiếng Nhật N3, những tiêu chí như vậy rõ ràng hơn để đánh giá.

Giải pháp: đừng dùng thanh đánh giá nếu bạn không có tiêu chí rõ ràng để đánh giá.

Cách viết kỹ năng hay

Một danh sách kỹ năng hay ở trong CV vừa phải là toát lên thế mạnh của bạn trong công việc, vừa cần giúp cho nhà tuyển dụng nhanh chóng thấy sự phù hợp của bạn với công việc đó. Để CV của bạn phù hợp với công việc bạn đang nộp, bạn nên bắt đầu từ việc phân tích Job Description thật kỹ. Nhà tuyển dụng đã dành rất nhiều thời gian để viết JD, bạn hãy tận dụng bản JD đó. Việc cần làm là đọc từng gạch đầu dòng ở phần mô tả công việc, trong mỗi gạch đầu dòng đó hãy chọn ra những từ khoá (một cụm động từ) mô tả công việc bạn phải làm. Lấy ví dụ JD công việc dưới đây.

Mô tả công việc

  • Tìm kiếm khách hàng mới
  • Chăm sóc khách hàng cũ theo data được công ty giao.
  • Tư vấn sản phẩm
  • Đàm phán, soạn thảo hợp đồng bán hàng, theo dõi tiến trình thực hiện hợp đồng của khách hàng.
  • Tham gia phục vụ hội chợ, triển lãm, trưng bày giới thiệu sản phẩm, các khóa đào tạo.
  • Đặt hàng cung cấp cho khách hàng
  • Tổng kết công nợ khách hàng, theo dõi và thu hồi công nợ khách hàng
  • Thực hiện bảo hành hàng hóa.
  • Báo cáo (ngày, tuần, tháng) theo yêu cầu của quản lý.

Sau khi phân tích JD ở trên, chúng ta lọc được ra các từ khoá cụm động từ bao gồm.

  1. Tìm kiếm khách hàng.
  2. Chăm sóc khách hàng.
  3. Tư vấn sản phẩm.
  4. Soạn thảo hợp đồng.
  5. Tổng kết công nợ.
  6. Báo cáo.

Nếu đã từng làm Sales, bạn sẽ dễ dàng nhận ra ở trên là những kỹ năng cần của một nhân viên kinh doanh. Vậy nếu định ứng tuyển vào công việc này, bạn cần xem lại xem ở 6 gạch đầu dòng trên mình làm được những gạch đầu dòng nào – nếu gạch đầu dòng nào bạn tự tin mình làm được, đó có thể tính là kỹ năng của bạn. Chỉ cần thấy bản thân là được 70% trở lên các gạch đầu dòng của một công việc, bạn hãy cứ tự tin nộp cho công việc đó nhé.

Như vậy, khi một nhà tuyển dụng đọc và so sánh hai bản CV dưới đây ứng tuyển cho công việc Nhân viên kinh doanh, bạn nghĩ rằng học sẽ thấy bản CV nào ấn tượng hơn?

Kỹ năng

  • Tìm kiếm khách hàng.
  • Chăm sóc khách hàng.
  • Tư vấn sản phẩm.
  • Soạn thảo hợp đồng.
  • Tổng kết công nợ.

Kỹ năng

  • Giao tiếp
  • Làm việc nhóm
  • Thuyết trình
  • Giải quyết vấn đề
  • MS Office

Để viết được như hướng dẫn trên, đòi hỏi với mỗi công việc khác nhau, bạn cần dành thời gian để phân tích kỹ từng JD công việc. Việc này đúng là hơi tốn thời gian, nhưng thực sự đáng và nên làm để tăng hiệu quả trúng tuyển cho CV của bạn nhé.

Chúc bạn có một bản CV thật hay.

Bài viết gốc được đăng tải tại anhtuanle.com

Xem thêm:

Xem thêm các việc làm về CNTT hấp dẫn tại TopDev

Tính trừu tượng (Abstraction) trong Java

tính trừu tượng trong java

Trong lập trình hướng đối tượng, tính trừu tượng và tính kế thừa là hai khái niệm quan trọng và được sử dụng rộng rãi trong ngôn ngữ lập trình java. Tuy nhiên, nhiều người vẫn còn băn khoăn về sự khác biệt giữa hai khái niệm này và cách sử dụng chúng trong việc thiết kế và triển khai các ứng dụng.

Trong bài viết này, hãy cùng TopDev tìm hiểu về tính trừu tượng và tính kế thừa trong Java, từ đó có thể hiểu rõ hơn về sự khác biệt giữa hai khái niệm này và áp dụng chúng một cách hiệu quả nhé!

Khái niệm về tính trừu tượng trong Java

Trong lập trình hướng đối tượng, tính trừu tượng là một khái niệm quan trọng giúp mô hình hóa thế giới thực bằng cách ẩn đi các chi tiết triển khai bên trong của một đối tượng, chỉ tập trung vào hành vi và giao diện bên ngoài của đối tượng đó. Tính trừu tượng cho phép chúng ta xác định các lớp trừu tượng, các phương thức trừu tượng và các biến trừu tượng trong mã của chúng ta.

Trong Java, tính trừu tượng được thể hiện thông qua từ khóa abstract. Một lớp trừu tượng là một lớp không thể khởi tạo; chỉ có thể được sử dụng để tạo các lớp con.

Các phương thức trừu tượng là các phương thức không có phần thân, chỉ có phần khai báo, các phương thức trừu tượng phải được ghi đè trong các lớp con. Biến trừu tượng là các biến chưa được gán giá trị ban đầu và giá trị của chúng phải được gán trong các lớp con.

tính trừu tượng trong java

Các đặc điểm của tính trừu tượng trong Java

Để hiểu rõ hơn về tính trừu tượng trong Java, hãy cùng xem qua các đặc điểm của nó:

Tạo ra các lớp trừu tượng

Như đã đề cập ở trên, một lớp trừu tượng là một lớp không thể khởi tạo và chỉ có thể được sử dụng để tạo các lớp con. Điều này có nghĩa là chúng ta không thể tạo một đối tượng từ một lớp trừu tượng bằng cách sử dụng từ khóa new. Thay vào đó, chúng ta phải tạo một lớp con và triển khai các phương thức trừu tượng của lớp cha.

Phương thức trừu tượng

Phương thức trừu tượng là các phương thức không có phần thân, chỉ có phần khai báo. Điều này có nghĩa là chúng ta chỉ định tên, kiểu dữ liệu và tham số cho phương thức mà không cần triển khai nội dung của nó. Các phương thức trừu tượng phải được ghi đè trong các lớp con và triển khai nội dung của chúng.

Biến trừu tượng

Biến trừu tượng là các biến chưa được gán giá trị ban đầu và giá trị của chúng phải được gán trong các lớp con. Điều này có nghĩa là chúng ta không thể sử dụng các biến trừu tượng trong phương thức của lớp trừu tượng, mà chỉ có thể sử dụng chúng trong các lớp con.

Lớp con

Một lớp con là một lớp kế thừa từ một lớp trừu tượng. Điều này có nghĩa là lớp con sẽ kế thừa các thuộc tính và phương thức của lớp cha, bao gồm cả các phương thức trừu tượng. Tuy nhiên, lớp con phải cung cấp triển khai cho tất cả các phương thức trừu tượng của lớp cha.

>>> Xem thêm: Java Enum là gì? Tại sao nên sử dụng enum?

Lợi ích của tính trừu tượng trong lập trình java

Tính trừu tượng là một khái niệm quan trọng trong lập trình hướng đối tượng và có nhiều lợi ích khi được áp dụng trong ngôn ngữ lập trình Java:

Tăng tính trừu tượng

Tính trừu tượng giúp che giấu các chi tiết triển khai, làm cho mã dễ đọc và bảo trì hơn. Thay vì phải quan tâm đến các chi tiết bên trong của một đối tượng, chúng ta chỉ cần tập trung vào giao diện và hành vi bên ngoài của nó. Điều này giúp mã trở nên dễ hiểu và dễ mở rộng hơn trong tương lai.

Tính linh hoạt

Tính trừu tượng cho phép các lớp khác nhau có thể có các hành vi khác nhau, nhưng lại chia sẻ chung một giao diện. Điều này giúp chúng ta có thể linh hoạt trong việc thiết kế và triển khai các ứng dụng, đồng thời cũng giảm thiểu sự phức tạp của mã.

Tính tái sử dụng

Tính trừu tượng cho phép tái sử dụng mã bằng cách xác định các hành vi chung trong một lớp trừu tượng và sau đó tái sử dụng các hành vi đó trong các lớp con. Điều này giúp tiết kiệm thời gian và công sức trong việc viết mã, đồng thời cũng giúp mã trở nên dễ bảo trì hơn.

Cách sử dụng tính trừu tượng trong Java

Để sử dụng tính trừu tượng trong Java, bạn cần làm theo các bước sau:

  1. Xác định các lớp trừu tượng: Chúng ta cần xác định các lớp trừu tượng trong mã của mình bằng cách sử dụng từ khóa abstract trước tên lớp.
  2. Định nghĩa các phương thức trừu tượng: Bạn cần định nghĩa các phương thức trừu tượng trong lớp trừu tượng bằng cách sử dụng từ khóa abstract trước kiểu trả về của phương thức.
  3. Triển khai các phương thức trừu tượng: Lập trình viên cần triển khai các phương thức trừu tượng trong các lớp con bằng cách sử dụng từ khóa @Override trước phương thức và viết nội dung cho phương thức đó.

Các khái niệm cơ bản liên quan đến tính trừu tượng trong Java

Trong quá trình làm việc với tính trừu tượng trong Java, chúng ta cần hiểu rõ các khái niệm cơ bản sau:

Ghi đè (Overriding)

Ghi đè là quá trình triển khai lại một phương thức trừu tượng trong lớp con. Điều này có nghĩa là chúng ta sẽ viết lại nội dung của phương thức trừu tượng trong lớp con để phù hợp với hành vi của lớp đó.

Gọi super (Super Keyword)

Trong trường hợp muốn gọi phương thức trừu tượng của lớp cha trong lớp con, chúng ta có thể sử dụng từ khóa super trước tên phương thức. Điều này giúp chúng ta tránh việc ghi đè hoàn toàn các phương thức của lớp cha.

Lớp trừu tượng (Abstract Class)

Lớp trừu tượng là một lớp không thể khởi tạo và chỉ có thể được sử dụng để tạo các lớp con. Nó chứa các phương thức trừu tượng và các phương thức đã triển khai.

>>> Xem thêm: Tìm hiểu tính chất của abstract class trong Java

Phương thức trừu tượng (Abstract Method)

Phương thức trừu tượng là các phương thức không có phần thân, chỉ có phần khai báo. Chúng ta cần triển khai lại các phương thức này trong các lớp con.

>>> Xem thêm: Constructor trong Java là gì?

Các ví dụ minh họa về tính trừu tượng trong Java

Để hiểu rõ hơn về tính trừu tượng trong Java, chúng ta cùng xem qua một số ví dụ sau:

Ví dụ 1: Tạo lớp trừu tượng Shape 

public abstract class Shape {
    // Khai báo phương thức tính diện tích
    public abstract double calculateArea();
} 

Ví dụ 2: Kế thừa từ lớp trừu tượng Shape 

public class Rectangle extends Shape {
    private double length;
    private double width;
    // Triển khai phương thức tính diện tích cho hình chữ nhật
    @Override
    public double calculateArea() {
        return length * width;
    }
} 

Ví dụ 3: Sử dụng lớp trừu tượng Shape trong mã 

public class Main {
    public static void main(String[] args) {
        // Khởi tạo một đối tượng hình chữ nhật
        Rectangle rectangle = new Rectangle();
        rectangle.length = 10;
        rectangle.width = 5;
        // Tính diện tích của hình chữ nhật
        double area = rectangle.calculateArea();
        System.out.println("Diện tích của hình chữ nhật là: " + area);
    }
} 

Sự khác biệt giữa tính trừu tượng và tính kế thừa trong Java

Tính trừu tượng và tính kế thừa là hai khái niệm quan trọng trong lập trình hướng đối tượng, tuy nhiên chúng có những điểm khác biệt sau:

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

  • Là quá trình che giấu các chi tiết triển khai bên trong của một đối tượng.
  • Giúp mã trở nên dễ hiểu và dễ bảo trì hơn.
  • Được sử dụng thông qua lớp trừu tượng và phương thức trừu tượng.

Tính kế thừa (Inheritance)

  • Là quá trình kế thừa các thuộc tính và phương thức từ một lớp cha sang một lớp con.
  • Giúp tái sử dụng mã và giảm thiểu sự phức tạp của mã.
  • Được sử dụng thông qua từ khóa extends khi khai báo lớp con.

Các lỗi thường gặp khi sử dụng tính trừu tượng trong Java

Trong quá trình sử dụng tính trừu tượng trong Java, chúng ta có thể gặp phải các lỗi sau:

Lỗi không triển khai đầy đủ các phương thức trừu tượng

Khi một lớp con kế thừa từ một lớp trừu tượng, nó phải triển khai đầy đủ các phương thức trừu tượng của lớp cha. Nếu không, chúng ta sẽ gặp lỗi khi cố gắng sử dụng các phương thức này.

Lỗi không ghi đè đúng các phương thức trừu tượng

Khi ghi đè một phương thức trừu tượng trong lớp con, chúng ta phải đảm bảo rằng nội dung của phương thức đó phù hợp với hành vi của lớp đó. Nếu không, chúng ta có thể gặp lỗi logic trong mã.

Lỗi khởi tạo đối tượng từ lớp trừu tượng

Lớp trừu tượng không thể được khởi tạo, do đó chúng ta không thể tạo đối tượng trực tiếp từ lớp này. Chúng ta chỉ có thể tạo đối tượng từ các lớp con của nó.

Cách thiết kế và triển khai tính trừu tượng trong Java

Để thiết kế và triển khai tính trừu tượng trong Java, chúng ta có thể làm theo các bước sau:

  1. Xác định các hành vi chung: Đầu tiên, bạn cần xác định các hành vi chung mà các lớp con có thể chia sẻ.
  2. Tạo lớp trừu tượng: Sau đó, lập trình viên cần tạo một lớp trừu tượng và định nghĩa các phương thức trừu tượng cho các hành vi chung đã xác định ở bước trước.
  3. Kế thừa từ lớp trừu tượng: Bạn cần tạo các lớp con kế thừa từ lớp trừu tượng và triển khai lại các phương thức trừu tượng đã được định nghĩa.
  4. Sử dụng tính trừu tượng: Cuối cùng, bạn có thể sử dụng tính trừu tượng trong mã của mình bằng cách tạo đối tượng từ các lớp con và gọi các phương thức trừu tượng.

Tính trừu tượng trong Java và ứng dụng trong thực tế

Tính trừu tượng là một khái niệm quan trọng trong lập trình hướng đối tượng và có nhiều ứng dụng trong thực tế, ví dụ như:

  • Trong thiết kế các ứng dụng lớn, tính trừu tượng giúp giảm thiểu sự phức tạp của mã và làm cho mã dễ bảo trì hơn.
  • Tính trừu tượng cũng giúp chúng ta có thể linh hoạt trong việc thiết kế và triển khai các ứng dụng, đồng thời cũng giảm thiểu sự phụ thuộc giữa các lớp.
  • Trong các dự án phần mềm, tính trừu tượng giúp chia nhỏ mã thành các phần nhỏ hơn và dễ quản lý hơn.
  • Tính trừu tượng cũng giúp tái sử dụng mã, giúp tiết kiệm thời gian và công sức trong việc viết mã mới.

Kết luận

Tính trừu tượng là một khái niệm quan trọng trong lập trình hướng đối tượng và có nhiều lợi ích khi được áp dụng trong ngôn ngữ lập trình Java. Chúng ta có thể sử dụng tính trừu tượng để tăng tính trừu tượng, tính linh hoạt và tính tái sử dụng trong mã của mình. Để sử dụng tính trừu tượng trong Java, chúng ta cần hiểu các khái niệm cơ bản liên quan đến nó và cách thiết kế và triển khai tính trừu tượng trong mã. 

Bài viết chỉ mang tính chất tham khảo

Nội dung được tổng hợp bởi AI và điều chỉnh bởi Ban Biên tập TopDev 

Cập nhật tin tuyển dụng IT lương cao tại TopDev

Tìm hiểu về lớp Scanner trong ngôn ngữ lập trình Java

scanner trong java

Lớp Scanner trong java là một công cụ quan trọng cho việc đọc dữ liệu đầu vào từ người dùng hoặc các nguồn khác như tệp hoặc luồng. Điều này giúp cho việc nhập liệu trở nên dễ dàng và thuận tiện hơn đối với các lập trình viên. Hãy cùng TopDev hiểu rõ hơn về lớp Scanner trong Java qua nội dung bài viết.

Cách sử dụng Scanner trong Java

Để sử dụng lớp Scanner trong Java, bạn cần import gói java.util và sau đó tạo đối tượng Scanner được liên kết với nguồn dữ liệu. Ví dụ:

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in); // Đọc dữ liệu từ bảng điều khiển
    }
}

Bạn cũng có thể liên kết đối tượng Scanner với một tệp hoặc luồng:

Scanner scanner = new Scanner(new File("input.txt")); // Đọc dữ liệu từ tệp
Scanner scanner = new Scanner(new FileInputStream("input.txt")); // Đọc dữ liệu từ FileInputStream

Sau khi tạo đối tượng Scanner, bạn có thể sử dụng các phương thức của lớp này để đọc dữ liệu. Phương thức phổ biến nhất là nextInt(), nextDouble() và nextLine(), lần lượt đọc các số nguyên, số thực và chuỗi ký tự từ nguồn.

Xem ngay tin tuyển dụng Java tại TopDev

Ví dụ về việc sử dụng Scanner trong Java

Để minh họa cho việc sử dụng lớp Scanner trong Java, hãy cùng xem xét một ví dụ đơn giản về việc nhập vào thông tin của một sinh viên và hiển thị ra màn hình:

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Nhập tên sinh viên: ");
        String name = scanner.nextLine();
        System.out.print("Nhập tuổi sinh viên: ");
        int age = scanner.nextInt();
        System.out.println("Thông tin sinh viên:");
        System.out.println("Tên: " + name);
        System.out.println("Tuổi: " + age);
    }
}

Kết quả khi chạy chương trình và nhập vào tên là “Nguyen Van A” và tuổi là 20 sẽ là:

Nhập tên sinh viên: Nguyen Van A
Nhập tuổi sinh viên: 20
Thông tin sinh viên:
Tên: Nguyen Van A
Tuổi: 20

>>> Xem thêm: Lập trình đa luồng trong Java (Java Multi-threading)

Lợi ích của việc sử dụng Scanner trong Java

  • Thuận tiện: Scanner cung cấp một cách đơn giản và dễ sử dụng để đọc dữ liệu đầu vào. Các lập trình viên chỉ cần tạo đối tượng Scanner và sử dụng các phương thức của nó để đọc dữ liệu từ nguồn.
  • Tiết kiệm thời gian: Với lớp Scanner, bạn không cần phải tự viết mã để xử lý dữ liệu đầu vào. Điều này giúp cho việc nhập liệu trở nên nhanh chóng hơn và tiết kiệm được thời gian cho các lập trình viên.
  • Dễ dàng sử dụng với các kiểu dữ liệu khác nhau: Lớp Scanner có thể đọc được nhiều loại dữ liệu khác nhau như số nguyên, số thực, chuỗi ký tự, v.v. Điều này giúp cho việc nhập liệu trở nên linh hoạt hơn và không bị giới hạn bởi kiểu dữ liệu.

scanner trong java

Các phương thức của lớp Scanner trong Java

Lớp Scanner trong Java cung cấp nhiều phương thức để đọc dữ liệu từ nguồn. Dưới đây là danh sách các phương thức phổ biến nhất:

Phương thức Mô tả
nextInt() Đọc một số nguyên từ nguồn dữ liệu
nextDouble() Đọc một số thực từ nguồn dữ liệu
nextLine() Đọc một chuỗi ký tự từ nguồn dữ liệu
nextBoolean() Đọc một giá trị boolean từ nguồn dữ liệu
nextByte() Đọc một số byte từ nguồn dữ liệu
nextShort() Đọc một số short từ nguồn dữ liệu
nextLong() Đọc một số long từ nguồn dữ liệu
nextFloat() Đọc một số float từ nguồn dữ liệu

Những lỗi thường gặp khi sử dụng Scanner trong Java

Mặc dù lớp Scanner là một công cụ hữu ích, nhưng nó cũng có thể gây ra một số lỗi khi sử dụng. Dưới đây là một số lỗi thường gặp khi sử dụng Scanner trong Java và cách xử lý chúng:

Lỗi InputMismatchException

Lỗi này xảy ra khi người dùng nhập vào một kiểu dữ liệu không phù hợp với kiểu dữ liệu được yêu cầu bởi phương thức. Ví dụ, nếu bạn sử dụng phương thức nextInt() để đọc một số nguyên nhưng người dùng lại nhập vào một chuỗi ký tự, lỗi InputMismatchException sẽ xảy ra. Để xử lý lỗi này, bạn có thể sử dụng phương thức hasNextInt() để kiểm tra trước khi đọc dữ liệu.

Lỗi NoSuchElementException

Lỗi này xảy ra khi không còn dữ liệu để đọc từ nguồn nữa. Ví dụ, nếu bạn sử dụng phương thức nextInt() để đọc một số nguyên nhưng không còn số nào để đọc nữa, lỗi NoSuchElementException sẽ xảy ra. Để xử lý lỗi này, bạn có thể sử dụng phương thức hasNext() để kiểm tra trước khi đọc dữ liệu.

Lỗi IllegalStateException

Lỗi này xảy ra khi phương thức được gọi trong trạng thái không hợp lệ. Ví dụ, nếu bạn đã đọc hết dữ liệu từ nguồn và tiếp tục gọi phương thức next(), lỗi IllegalStateException sẽ xảy ra. Để xử lý lỗi này, bạn có thể sử dụng phương thức hasNext() để kiểm tra trước khi gọi phương thức khác.

Cách xử lý lỗi khi sử dụng Scanner trong Java

Để xử lý các lỗi khi sử dụng Scanner trong Java, bạn có thể sử dụng cấu trúc try-catch để bắt và xử lý các ngoại lệ. Ví dụ:

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        try {
            System.out.print("Nhập số nguyên: ");
            int num = scanner.nextInt();
            System.out.println("Số nguyên vừa nhập là: " + num);
        } catch (InputMismatchException e) {
            System.out.println("Bạn đã nhập sai kiểu dữ liệu.");
        }
    }
} 

Scanner và các kiểu dữ liệu trong Java

Lớp Scanner trong Java có thể đọc được nhiều loại dữ liệu khác nhau, bao gồm các kiểu dữ liệu cơ bản của Java như int, double, boolean, v.v. Ngoài ra, nó cũng có thể đọc được các kiểu dữ liệu đối tượng như String, Date, v.v.

scanner trong java

Làm thế nào để tối ưu hóa việc sử dụng Scanner?

Để tối ưu hóa việc sử dụng Scanner trong Java, bạn có thể áp dụng một số mẹo sau:

  • Sử dụng phương thức hasNext() để kiểm tra trước khi đọc dữ liệu.
  • Đóng đối tượng Scanner sau khi sử dụng để giải phóng bộ nhớ.
  • Sử dụng các phương thức nextLine() hoặc next() để đọc dữ liệu thay vì sử dụng các phương thức đọc kiểu cụ thể.
  • Sử dụng các biến trung gian để lưu giá trị đọc được từ Scanner, giúp cho việc xử lý dữ liệu trở nên dễ dàng hơn.

>>> Xem thêm: Ép Kiểu & Comment Source Code trong Java

So sánh Scanner với các công cụ nhập liệu khác trong Java

Trong Java, ngoài lớp Scanner, còn có một số công cụ khác để nhập liệu như BufferedReader và Console. Dưới đây là một bảng so sánh giữa lớp Scanner và các công cụ này:

Công cụ Điểm mạnh Điểm yếu
Scanner Thuận tiện và dễ sử dụng Chậm khi đọc dữ liệu
BufferedReader Nhanh khi đọc dữ liệu Phức tạp hơn khi sử dụng
Console Hỗ trợ nhập liệu từ bảng điều khiển Không thể sử dụng khi chạy ứng dụng từ bên ngoài bảng điều khiển

Tùy vào mục đích sử dụng và yêu cầu của từng dự án, bạn có thể lựa chọn công cụ phù hợp để nhập liệu.

Các lưu ý khi sử dụng Scanner

  • Tránh sử dụng phương thức next() để đọc dữ liệu từ nguồn vì nó chỉ đọc một từ hoặc một số từ đầu tiên của chuỗi ký tự.
  • Nếu bạn muốn đọc một số nguyên hoặc số thực, hãy sử dụng các phương thức nextInt() và nextDouble() thay vì next().
  • Khi sử dụng Scanner để đọc dữ liệu từ tệp, hãy chắc chắn rằng tệp đó có định dạng phù hợp với kiểu dữ liệu mà bạn muốn đọc.

Kết luận

Như vậy, qua bài viết này, TopDev đã giúp bạn hiểu rõ hơn về lớp Scanner trong ngôn ngữ lập trình java. Lớp này cung cấp cho chúng ta một cách đơn giản và thuận tiện để đọc dữ liệu đầu vào từ người dùng hoặc các nguồn khác. Hy vọng bài viết này sẽ giúp bạn áp dụng hiệu quả lớp Scanner trong các dự án của mình.

Bài viết chỉ mang tính chất tham khảo

Nội dung được tổng hợp bởi AI và điều chỉnh bởi Ban Biên tập TopDev 

Cập nhật tin tuyển dụng IT lương cao tại TopDev

Tính đa hình trong Java là gì?

tính đa hình trong java

Tính đa hình (polymorphism) trong Java cho phép các đối tượng thể hiện nhiều hành vi khác nhau dựa trên ngữ cảnh sử dụng. Bài viết này của TopDev sẽ giải thích khái niệm tính đa hình trong Java, các phương thức đạt được tính đa hình, phân loại và lý do sử dụng nó trong lập trình hướng đối tượng.

Tính đa hình (polymorphism) trong Java là gì?

Tính đa hình là khả năng của các đối tượng thuộc các lớp có quan hệ kế thừa với nhau thể hiện nhiều hành vi khác nhau khi được gọi thông qua cùng một giao diện.

Trong Java, tính đa hình cho phép xử lý đối tượng con thông qua tham chiếu đến lớp cha của chúng. Khi gọi phương thức trên đối tượng con thông qua tham chiếu lớp cha, phiên bản phương thức được thực thi sẽ phụ thuộc vào kiểu của đối tượng thực tế.

Tính đa hình là gì?

Tính đa hình là một trong những tính chất quan trọng của lập trình hướng đối tượng, cho phép các đối tượng có nhiều dạng (poly) và chức năng (morph) khác nhau.

Nó cho phép một giao diện được thực hiện theo nhiều cách khác nhau. Một lệnh gọi trên một tham chiếu đối tượng sẽ thực thi hành vi phù hợp với kiểu của đối tượng được tham chiếu tới.

tính đa hình trong java

Tính đa hình trong Java là gì?

Trong Java, tính đa hình cho phép xác định một giao diện chung cho một nhóm các đối tượng có liên quan, sau đó ghi đè hoặc cài đặt các phiên bản cụ thể của các phương thức cho mỗi lớp con đại diện cho một loại cụ thể.

Java cung cấp 2 cơ chế để đạt được tính đa hình:

  1. Ghi đè phương thức (Overriding): Cho phép lớp con cung cấp triển khai riêng cho phương thức được kế thừa từ lớp cha.
  2. Ghi chồng phương thức (Overloading): Cho phép cùng một tên phương thức nhưng với các tham số khác nhau.

Java tuyển dụng lương cao, đãi ngộ tốt

Phương thức để đạt tính đa hình trong Java

Có 2 phương thức để đạt được tính đa hình trong Java là ghi đè phương thức và ghi chồng phương thức.

Overriding (Ghi đè)

Overriding cho phép lớp con ghi đè lên hành vi của phương thức kế thừa từ lớp cha bằng cách cung cấp triển khai riêng. Khi phương thức được gọi trên một đối tượng thuộc lớp con, phiên bản phương thức của lớp con sẽ được ưu tiên thực thi.

Để ghi đè phương thức, lớp con phải kế thừa từ lớp cha, định nghĩa lại phương thức với cùng tên, tham số và kiểu trả về. Phương thức của lớp con cũng phải được đánh dấu @Override để thông báo rằng lớp con đang ghi đè lên phương thức của lớp cha.

Ví dụ:

class Animal {
  public void makeSound() {
    System.out.println("The animal makes a sound");
  }
}

class Dog extends Animal {
  @Override  
  public void makeSound() {
    System.out.println("The dog barks woof woof"); 
  }
}

Dog d = new Dog();
d.makeSound(); // in ra "The dog barks woof woof"

Ở đây Dog ghi đè phương thức makeSound() có sẵn trong Animal để cung cấp triển khai riêng cho giống chó.

Ưu điểm của overriding

  • Cho phép mở rộng và tùy biến hành vi của lớp con mà không ảnh hưởng đến lớp cha.
  • Tăng tính đa hình và linh hoạt khi thao tác với các đối tượng có quan hệ kế thừa.

Nhược điểm của overriding

  • Khi sử dụng nhiều lớp kế thừa đa tầng, code trở nên phức tạp hơn, khó quản lý.
  • Khả năng xảy ra lỗi khi ghi đè sai quy tắc, dẫn tới hành vi không mong muốn.

Overloading (Ghi chồng)

Overloading cho phép cùng một tên phương thức xuất hiện nhiều lần trong cùng một lớp nhưng với số lượng và kiểu tham số khác nhau. Khi phương thức được gọi, trình biên dịch sẽ chọn phiên bản phương thức phù hợp nhất dựa trên số lượng và kiểu của các tham số được truyền vào.

Ví dụ:

class Calculator {
  int add(int a, int b) {
    return a + b;
  }
  
  double add(double a, double b) {
    return a + b; 
  }
} Calculator c = new Calculator(); System.out.println(c.add(1, 2)); // gọi phương thức add với int System.out.println(c.add(1.0, 2.0)); // gọi phương thức add với double

Ở đây, lớp Calculator định nghĩa 2 phương thức add() có cùng tên nhưng tham số và kiểu trả về khác nhau. Đây là ví dụ đơn giản về ghi chồng phương thức.

Ưu điểm của overloading

  • Tăng tính linh hoạt, cho phép sử dụng cùng một phương thức cho nhiều kiểu tham số.
  • Code ngắn gọn, dễ đọc và bảo trì hơn.

Nhược điểm của overloading

  • Dễ gây nhầm lẫn giữa các phiên bản phương thức, đặc biệt nếu chúng có tên giống nhau.
  • Có thể dẫn đến lỗi thời gian chạy nếu sử dụng sai kiểu dữ liệu.

>>> Xem thêm: Java Reflection là gì? Hướng dẫn Java Reflection API

Phân loại đa hình trong Java

Có 2 loại đa hình trong Java:

  1. Đa hình Compile-Time (Tĩnh)
  2. Đa hình Runtime (Động)

Đa hình Compile – Time trong Java

Đa hình compile-time xảy ra khi phương thức được gọi được xác định và liên kết tại thời điểm biên dịch. Việc gọi phương thức phụ thuộc vào kiểu tham chiếu của đối tượng. Đa hình tĩnh đạt được thông qua ghi chồng phương thức và tải sớm liên kết (static binding) trong quá trình biên dịch.

Ví dụ:

class OverloadExample {
  public void demo(int a) {
    System.out.println("a: " + a);
  }

  public void demo(String a) {
    System.out.println("a: " + a);
  }
}

Ở đây đa hình tĩnh sẽ xác định phiên bản demo() phù hợp để gọi dựa trên kiểu dữ liệu của tham số truyền vào khi biên dịch.

tính đa hình trong java

Đa hình Runtime trong Java

Đa hình runtime (hoặc đa hình động) xảy ra khi phương thức được xác định tại thời điểm chương trình chạy. Phiên bản phương thức thực thi dựa trên kiểu thực tế của đối tượng vào thời điểm runtime.

Đa hình runtime đạt được qua việc ghi đè phương thức và gắn kết muộn (dynamic binding) thông qua cơ chế kế thừa.

Ví dụ:

class Animal {
  public void makeSound() {
    System.out.println("Animal making sound"); 
  }
}

class Dog extends Animal {
  public void makeSound() {
    System.out.println("Bark bark");
  }
}

Animal a = new Dog();  
a.makeSound();  

Ở đây makeSound() của Dog sẽ được gọi dù a được khai báo kiểu Animal bởi vì đối tượng thực tế là Dog. Kiểu đối tượng thực tế mới quyết định phiên bản phương thức gọi tại runtime.

Đa hình Runtime trong Java với kế thừa đa tầng

Trong trường hợp kế thừa đa tầng, đối tượng có thể là instance của một lớp rất sâu trong cấp độ kế thừa. Lúc này phiên bản phương thức được gọi cũng là của lớp sâu nhất đó.

Ví dụ:

class Animal {
  public void makeSound() {
    System.out.println("Animal making sound"); 
  }
}

class Dog extends Animal {
  public void makeSound() { 
    System.out.println("Bark bark");

}

class BabyDog extends Dog {
  public void makeSound() {
    System.out.println("Bow wow");
  }
}

Animal a = new BabyDog();
a.makeSound(); // In ra "Bow wow"

Ở đây dù a được khai báo kiểu Animal nhưng đối tượng thực sự là BabyDog. Vì vậy phương thức makeSound() của BabyDog sẽ được ưu tiên gọi khi thực thi.

>>> Xem thêm: Top 10 câu hỏi phỏng vấn Java Developer thường gặp

Tại sao sử dụng tính đa hình trong Java?

Tính đa hình mang lại nhiều lợi ích, là một trong những nguyên lý cốt lõi của lập trình hướng đối tượng:

Cải thiện tính linh hoạt và bảo trì

Tính đa hình cho phép các lớp con ghi đè và mở rộng hành vi của lớp cha mà không cần chỉnh sửa lớp cha. Điều này rất linh hoạt, tránh ảnh hưởng tới các lớp khác khi thay đổi một lớp cụ thể. Ngoài ra, tính đa hình cải thiện khả năng bảo trì và tái sử dụng code tốt hơn. Các lớp có thể được tái sử dụng cho nhiều mục đích khác nhau nhờ Override.

Tăng tính trừu tượng

Tính đa hình cho phép lập trình viên gọi các phương thức trên đối tượng mà không cần quan tâm chi tiết cài đặt bên trong. Điều này giúp tăng tính trừu tượng trong mã nguồn. Lập trình viên chỉ cần biết interface chung của các đối tượng, còn mỗi lớp con sẽ tự cung cấp triển khai riêng.

Mở rộng dễ dàng

Thông qua việc kế thừa và ghi đè, các ứng dụng có thể dễ dàng được mở rộng để hỗ trợ thêm các loại đối tượng và chức năng mới. Không cần sửa đổi các lớp hiện có, chỉ cần thêm các subclass mới là có thể mở rộng tính năng.

Ưu điểm của tính đa hình trong Java

  • Cải thiện tính linh hoạt và bảo trì code
  • Tăng tính trừu tượng, che giấu chi tiết triển khai
  • Mở rộng dễ dàng thông qua subclass
  • Tái sử dụng code tốt hơn
  • Hỗ trợ lập trình hướng giao diện tốt

Nhược điểm của tính đa hình trong Java

Có thể dẫn đến mã phức tạp khó bảo trì

Nếu lạm dụng tính đa hình với quá nhiều tầng subclass và override phương thức, code trở nên rất phức tạp, khó hiểu và khó bảo trì.

Rất khó để hiểu và theo dõi luồng thực thi của chương trình nếu quá nhiều phương thức bị ghi đè.

Cản trở hiệu suất

Do cơ chế gắn kết động muộn, việc gọi phương thức đa hình sẽ chậm hơn so với gọi trực tiếp. Điều này có thể ảnh hưởng hiệu suất nếu sử dụng quá nhiều.

Ngoài ra trình biên dịch cũng không thể tối ưu hóa tốt bằng kiểu tĩnh do kiểu động chỉ được xác định tại runtime.

Khả năng gây ra lỗi

Nếu ghi đè sai quy tắc hay định nghĩa lại phương thức sai chức năng so với ban đầu có thể dẫn tới lỗi nghiêm trọng.

Đặc biệt khi kết hợp với kế thừa đa tầng, rất khó để tìm nguyên nhân lỗi xảy ra.

Kết luận

Tính đa hình là một trong những nguyên lý quan trọng nhất của lập trình hướng đối tượng, cho phép linh hoạt xử lý các đối tượng có quan hệ thừa kế với nhau. Java hỗ trợ tính đa hình thông qua overriding và overloading, mang lại nhiều lợi ích như tính linh hoạt, mở rộng dễ dàng và tái sử dụng code.

Tuy nhiên, tính đa hình cũng tiềm ẩn một số nhược điểm như tăng độ phức tạp và khả năng gây lỗi. Do đó, bạn cần cân nhắc và sử dụng hợp lý để khai thác hiệu quả tối đa của tính đa hình trong Java.

Bài viết chỉ mang tính chất tham khảo

Nội dung được tổng hợp bởi AI và điều chỉnh bởi Ban Biên tập TopDev 

Cập nhật tin tuyển dụng IT lương cao tại TopDev

Tối ưu hóa hiệu suất với ReactJS và CSS

reactjs css

Trong thế giới phát triển web đầy sôi động, reactjs nổi lên như một thư viện JavaScript phổ biến giúp xây dựng các ứng dụng web giao diện người dùng liền mạch và tương tác. Khi nói đến việc tạo kiểu cho các ứng dụng ReactJS, CSS đóng một vai trò quan trọng trong việc xác định giao diện trực quan và khả năng sử dụng tổng thể.

Hiểu được cách tích hợp và tối ưu hóa CSS trong ReactJS là điều cần thiết để tạo ra các ứng dụng hiệu quả cao, hấp dẫn về mặt thẩm mỹ.

CSS trong ReactJS

CSS (Cascading Style Sheets) là một ngôn ngữ tạo kiểu được sử dụng để định nghĩa giao diện trực quan của trang web.

Ngôn ngữ này giúp kiểm soát các khía cạnh như màu sắc, kiểu chữ, bố cục và hành vi đáp ứng, tạo ra sự thống nhất và tăng cường khả năng bảo trì trong quá trình phát triển. Vì vậy, việc tích hợp CSS vào ReactJS là cực kỳ quan trọng để tạo ra các ứng dụng web chất lượng cao.

reactjs và css

Tạo kiểu thành phần ReactJS bằng CSS

Trong ReactJS, mỗi thành phần được tạo ra như một hàm JavaScript và có thể chứa mã HTML và CSS. Điều này cho phép chúng ta tạo kiểu cho các thành phần bằng cách sử dụng CSS trực tiếp trong tệp JSX của chúng. Ví dụ:

function Button() {
  return (
    Click me!
  );
}

Trong đó, className là thuộc tính của thành phần và button là tên lớp CSS được áp dụng cho nút. Tuy nhiên, phương pháp này không được khuyến khích cho các ứng dụng lớn hơn vì nó có thể gây ra xung đột tên giữa các thành phần khác nhau.

>>> Xem thêm: Hướng dẫn chi tiết xây dựng web app với Reactjs

Các phương pháp tích hợp CSS vào ReactJS

Để tách biệt giữa các mối quan tâm và duy trì tính tổng thể của mã, chúng ta có thể sử dụng các phương pháp sau để tích hợp CSS vào ReactJS:

  • Tệp CSS riêng: Tạo một tệp CSS riêng biệt và nhập nó vào thành phần ReactJS bằng thẻ . Phương pháp này giúp duy trì sự tách biệt giữa các mối quan tâm và có thể dễ dàng quản lý.
  • CSS Modules: CSS Modules là một giải pháp tạo kiểu cấp thành phần cung cấp phạm vi riêng cho các lớp CSS, ngăn ngừa xung đột tên giữa các thành phần khác nhau. Ví dụ:
import styles from './Button.module.css';

function Button() {
  return (
    Click me!
  );
}

Trong đó, styles là một đối tượng chứa các lớp CSS được định nghĩa trong tệp Button.module.css.

  • Thư viện CSS trong ReactJS: Có nhiều thư viện CSS được thiết kế đặc biệt để tích hợp với ReactJS như Styled Components, Emotion, và Material-UI. Chúng cung cấp các cú pháp đơn giản và tiện lợi để tạo kiểu cho các thành phần ReactJS.

Xem ngay tin tuyển dụng lập trình viên Reactjs tại TopDev

Tùy biến giao diện người dùng ReactJS bằng CSS

Với CSS, chúng ta có thể tùy biến giao diện người dùng của các thành phần ReactJS theo ý muốn. Điều này cho phép chúng ta tạo ra các giao diện độc đáo và thu hút người dùng. Dưới đây là một số cách để tùy biến giao diện người dùng ReactJS bằng CSS:

  • Sử dụng các lớp CSS: Tạo các lớp CSS riêng biệt cho từng thành phần và sử dụng chúng để tùy biến kiểu dáng, màu sắc và bố cục của giao diện.
  • Sử dụng các thuộc tính CSS: Sử dụng các thuộc tính CSS như font-size, color, background-color để tùy biến các phần tử trong thành phần.
  • Sử dụng các hiệu ứng CSS: Sử dụng các hiệu ứng CSS như hover, transition, animation để tạo ra các hiệu ứng tương tác và thu hút người dùng.

Các nguyên tắc thiết kế CSS tốt nhất cho ReactJS

Khi tạo kiểu cho các ứng dụng ReactJS, lập trình viên nên tuân thủ một số nguyên tắc thiết kế CSS tốt nhất sau đây để đảm bảo mã dễ đọc, dễ bảo trì và có hiệu suất tốt:

  • Sử dụng BEM (Block Element Modifier): BEM là một phương pháp đặt tên lớp CSS giúp tạo ra các lớp có ý nghĩa và dễ hiểu hơn. Nó cũng giúp tránh xung đột tên giữa các thành phần khác nhau.
  • Sử dụng CSS Reset: Sử dụng CSS Reset để loại bỏ các giá trị mặc định của các thuộc tính CSS và đảm bảo rằng giao diện sẽ được hiển thị đồng nhất trên các trình duyệt khác nhau.
  • Tối ưu hóa hiệu suất: Tránh sử dụng các lớp CSS không cần thiết và tối ưu hóa mã để đảm bảo hiệu suất tốt cho ứng dụng.

Tối ưu hóa hiệu suất CSS trong ReactJS

Để tối ưu hóa hiệu suất CSS trong ReactJS, bạn có thể áp dụng các kỹ thuật sau:

  • Sử dụng CSS Modules: Sử dụng CSS Modules để ngăn ngừa xung đột tên giữa các thành phần và tối ưu hóa hiệu suất của ứng dụng.
  • Sử dụng các thuộc tính CSS hiệu quả: Sử dụng các thuộc tính CSS như display: flex hoặc display: grid để tạo bố cục linh hoạt và hiệu quả.
  • Tối ưu hóa hình ảnh: Sử dụng các công cụ để tối ưu hóa kích thước và chất lượng của hình ảnh trong ứng dụng.

>>> Xem thêm: Hướng dẫn sử dụng ReactJS Props và State

Các thư viện CSS phổ biến cho ReactJS

Hiện nay, có rất nhiều thư viện CSS được thiết kế đặc biệt để tích hợp với ReactJS. Dưới đây là một số thư viện phổ biến và được sử dụng rộng rãi trong cộng đồng phát triển web:

  • Styled Components: Thư viện này cho phép chúng ta tạo các thành phần ReactJS có thể tái sử dụng và tùy biến bằng cách sử dụng các cú pháp CSS trong JavaScript.
  • Emotion: Emotion cung cấp các tính năng tương tự như Styled Components nhưng có thêm khả năng tạo ra các kiểu dáng động và hiệu ứng CSS.
  • Material-UI: Material-UI là một thư viện CSS được xây dựng trên cơ sở nguyên tắc thiết kế của Google Material Design. Nó cung cấp các thành phần giao diện người dùng sẵn có và các tính năng tùy biến để tạo ra các ứng dụng có giao diện đẹp mắt và dễ sử dụng.

reactjs css

Xử lý lỗi CSS trong ReactJS

Trong quá trình phát triển, bạn có thể gặp phải các lỗi liên quan đến CSS trong ReactJS. Để xử lý các lỗi này, bạn có thể áp dụng các kỹ thuật sau:

  • Kiểm tra cú pháp: Kiểm tra lại cú pháp của mã CSS để đảm bảo rằng nó không có lỗi.
  • Sử dụng công cụ kiểm tra lỗi: Sử dụng các công cụ như Chrome DevTools hoặc Firefox Developer Tools để tìm ra các lỗi CSS và sửa chúng.
  • Sử dụng các thư viện hỗ trợ: Có nhiều thư viện hỗ trợ giúp chúng ta xử lý các lỗi CSS trong ReactJS như stylelint, eslint-plugin-css-modules, và cssnano.

Xu hướng CSS cho ReactJS trong tương lai

Với sự phát triển nhanh chóng của công nghệ web, các xu hướng CSS cho ReactJS cũng đang thay đổi theo. Dưới đây là một số xu hướng được dự đoán sẽ phát triển trong tương lai:

  • CSS-in-JS: CSS-in-JS là một phương pháp tạo kiểu cho ứng dụng ReactJS bằng cách sử dụng JavaScript thay vì CSS truyền thống, cho phép chúng ta tạo các thành phần có thể tái sử dụng và tùy biến dễ dàng hơn.
  • CSS Grid: CSS Grid là một tính năng mới của CSS cho phép developer tạo bố cục linh hoạt và hiệu quả hơn. Nó đang trở thành một xu hướng phổ biến trong việc tạo kiểu cho các ứng dụng ReactJS.
  • CSS Animations: Với sự phát triển của các tính năng như CSS Transitions và CSS Animations, chúng ta có thể tạo ra các hiệu ứng động và tương tác đẹp mắt cho các ứng dụng ReactJS.

Kết luận

Trong bài viết này, chúng ta đã tìm hiểu về vai trò của CSS trong việc tạo kiểu cho các ứng dụng ReactJS và các phương pháp để tích hợp và tối ưu hóa CSS trong ReactJS. Mong rằng những chia sẻ từ TopDev sẽ giúp bạn hiểu rõ hơn về cách sử dụng CSS để tạo ra các giao diện người dùng đẹp mắt và hiệu quả cho các ứng dụng ReactJS.

Bài viết chỉ mang tính chất tham khảo

Nội dung được tổng hợp bởi AI và điều chỉnh bởi Ban Biên tập TopDev 

Cập nhật tin tuyển dụng IT lương cao tại TopDev

C++ algorithm: Những thuật toán cơ bản trong C++

c++ algorithm

Thuật toán là một chuỗi các bước có trình tự rõ ràng để giải quyết một vấn đề. Trong lập trình C++, thuật toán đóng vai trò quan trọng trong việc phát triển phần mềm hiệu quả và tối ưu. Do đó, việc hiểu được các c++ algorithm cơ bản là nền tảng cho bất kỳ ai muốn bước vào thế giới lập trình.

Khái quát về thuật toán C++ 

C++ là một ngôn ngữ lập trình hướng đối tượng và được sử dụng rộng rãi trong các ứng dụng khoa học máy tính, game và hệ thống nhúng. Với sự phát triển của công nghệ, việc tối ưu hóa và xử lý dữ liệu trở thành một yếu tố quan trọng trong lập trình và đây chính là lý do tại sao thuật toán lại trở nên cực kỳ quan trọng trong lập trình C++.

Trong C++, thuật toán được sử dụng để giải quyết các vấn đề liên quan đến xử lý dữ liệu, từ việc sắp xếp các phần tử trong một danh sách đến việc tìm kiếm các giá trị trong một tập hợp dữ liệu lớn. Vì vậy, hiểu và áp dụng các thuật toán cơ bản là điều cần thiết đối với một lập trình viên C++.

c++ algorithm

Khái niệm cơ bản về cấu trúc dữ liệu trong C++

Trước khi tìm hiểu về thuật toán, chúng ta cần nắm rõ khái niệm cấu trúc dữ liệu. Cấu trúc dữ liệu là cách thức tổ chức và sắp xếp dữ liệu trong bộ nhớ máy tính. Trong C++, có nhiều loại cấu trúc dữ liệu khác nhau, mỗi loại có ưu điểm và ứng dụng riêng. Dưới đây là những cấu trúc dữ liệu mà bất kỳ lập trình viên nào cũng phải biết:

Mảng (Array)

Mảng là một tập hợp các phần tử có cùng kiểu dữ liệu. Mỗi phần tử có một chỉ số duy nhất để truy cập và thay đổi giá trị của nó.

Array được sử dụng để lưu trữ các dữ liệu có cùng loại và kích thước cố định. Điều này giúp việc truy xuất và xử lý dữ liệu trở nên dễ dàng và nhanh chóng.

Ví dụ: Mảng số nguyên gồm 5 phần tử.

Chỉ số Giá trị
0 10
1 5
2 7
3 3
4 9

>>> Xem thêm: Solve Reverse Array with the best solution

Danh sách liên kết (Linked List)

Linked List là một tập hợp các phần tử được liên kết với nhau thông qua các con trỏ, mỗi phần tử trong danh sách chứa dữ liệu và một con trỏ đến phần tử tiếp theo trong danh sách. Điều này cho phép lập trình viên thêm, xóa và sắp xếp các phần tử trong danh sách một cách linh hoạt.

Cây (Tree)

Tree là một cấu trúc dữ liệu phân cấp, gồm một nút gốc và các nút con. Mỗi nút có thể có nhiều nút con khác và chỉ có một nút cha. Cây được sử dụng để lưu trữ dữ liệu theo cấu trúc phân cấp, ví dụ như cây gia phả, cây thư mục trên máy tính.

Đồ thị (Graph)

Graph là một tập hợp các đỉnh và các cạnh nối chúng. Điều này cho phép biểu diễn các mối quan hệ giữa các đối tượng trong thế giới thực. Đồ thị được sử dụng trong nhiều lĩnh vực như mạng máy tính, kế hoạch dự án, tối ưu hóa đường đi.

Bảng băm (Hash Table)

Hash Table là một cấu trúc dữ liệu sử dụng hàm băm để lưu trữ và truy xuất dữ liệu nhanh chóng. Hàm băm sẽ chuyển đổi khóa của dữ liệu thành một chỉ số duy nhất và lưu trữ dữ liệu tại vị trí đó trong bảng. Điều này giúp việc truy xuất dữ liệu trở nên nhanh chóng và hiệu quả.

Ví dụ: Bảng băm có 5 khóa và 5 giá trị tương ứng.

Khóa Giá trị
1 A
2 B
3 C
4 D
5 E

Hàng đợi (Queue)

Queue là một cấu trúc dữ liệu theo nguyên tắc vào trước, ra trước (FIFO – First In First Out). Các phần tử được thêm vào hàng đợi sẽ được lấy ra theo thứ tự chúng được thêm vào. Hàng đợi được sử dụng trong nhiều ứng dụng như xử lý tác vụ đồng bộ, quản lý tiến trình.

Ví dụ: Hàng đợi có 5 phần tử và phần tử đầu tiên được lấy ra trước.

Ngăn xếp (Stack)

Stack là một cấu trúc dữ liệu theo nguyên tắc vào sau, ra trước (FILO – First In Last Out). Các phần tử được thêm vào ngăn xếp sẽ được lấy ra theo thứ tự ngược lại so với thứ tự chúng được thêm vào. Ngăn xếp được sử dụng trong nhiều ứng dụng như xử lý biểu thức toán học, gọi hàm.

Ví dụ: Ngăn xếp có 5 phần tử và phần tử cuối cùng được lấy ra trước.

Nhiều vị trí tuyển dụng C++ đãi ngộ tốt trên TopDev

Thuật toán sắp xếp trong C++

Thuật toán sắp xếp sắp xếp các phần tử của một tập hợp theo một trật tự xác định. Các thuật toán sắp xếp phổ biến trong C++ bao gồm: sắp xếp nổi bọt, sắp xếp chọn, sắp xếp chèn, sắp xếp nhanh, sắp xếp trộn.

Sắp xếp nổi bọt (Bubble Sort)

Bubble Sort nổi bọt là thuật toán sắp xếp đơn giản nhất trong các thuật toán sắp xếp. Thuật toán này hoạt động bằng cách so sánh và hoán đổi các phần tử liền kề nhiều lần cho đến khi danh sách được sắp xếp.

Ý tưởng:

  • Lặp qua từng phần tử trong danh sách.
  • So sánh phần tử hiện tại với phần tử tiếp theo.
  • Nếu phần tử hiện tại lớn hơn phần tử tiếp theo, hoán đổi chúng.
  • Lặp lại quá trình cho đến khi danh sách được sắp xếp.

Độ phức tạp: O(n^2)

Ví dụ: Sắp xếp mảng số nguyên theo thứ tự tăng dần.

Bước Mảng trước khi sắp xếp Mảng sau khi sắp xếp
1 [5, 3, 8, 2, 1] [3, 5, 2, 1, 8]
2 [3, 5, 2, 1, 8] [3, 2, 1, 5, 8]
3 [3, 2, 1, 5, 8] [2, 1, 3, 5, 8]
4 [2, 1, 3, 5, 8] [1, 2, 3, 5, 8]

Sắp xếp chọn (Selection Sort)

Selection Sort là thuật toán sắp xếp bằng cách tìm kiếm phần tử nhỏ nhất trong danh sách và đưa nó về vị trí đầu tiên sau đó, tìm kiếm phần tử nhỏ nhất trong danh sách còn lại và đưa nó về vị trí thứ hai. Quá trình này được lặp lại cho đến khi danh sách được sắp xếp.

Ý tưởng:

  • Lặp qua từng phần tử trong danh sách.
  • Tìm kiếm phần tử nhỏ nhất trong danh sách còn lại.
  • Đưa phần tử nhỏ nhất về vị trí đầu tiên của danh sách.
  • Lặp lại quá trình cho đến khi danh sách được sắp xếp.

Độ phức tạp: O(n^2)

Ví dụ: Sắp xếp mảng số nguyên theo thứ tự tăng dần.

Bước Mảng trước khi sắp xếp Mảng sau khi sắp xếp
1 [5, 3, 8, 2, 1] [1, 3, 8, 2, 5]
2 [1, 3, 8, 2, 5] [1, 2, 8, 3, 5]
3 [1, 2, 8, 3, 5] [1, 2, 3, 8, 5]
4 [1, 2, 3, 8, 5] [1, 2, 3, 5, 8]

Sắp xếp chèn (Insertion Sort)

Insertion Sort là thuật toán sắp xếp bằng cách chia danh sách thành hai phần: phần đã sắp xếp và phần chưa sắp xếp. Ban đầu, phần đã sắp xếp chỉ có một phần tử đầu tiên của danh sách. Sau đó, bạn lặp qua từng phần tử trong phần chưa sắp xếp và chèn nó vào đúng vị trí trong phần đã sắp xếp.

Ý tưởng:

  • Chia danh sách thành hai phần: phần đã sắp xếp và phần chưa sắp xếp.
  • Lặp qua từng phần tử trong phần chưa sắp xếp.
  • Chèn phần tử hiện tại vào đúng vị trí trong phần đã sắp xếp.
  • Lặp lại quá trình cho đến khi danh sách được sắp xếp.

Độ phức tạp: O(n^2)

Ví dụ: Sắp xếp mảng số nguyên theo thứ tự tăng dần.

Bước Mảng trước khi sắp xếp Mảng sau khi sắp xếp
1 [5, 3, 8, 2, 1] [5, 3, 8, 2, 1]
2 [5, 3, 8, 2, 1] [3, 5, 8, 2, 1]
3 [3, 5, 8, 2, 1] [3, 5, 8, 2, 1]
4 [3, 5, 8, 2, 1] [2, 3, 5, 8, 1]
5 [2, 3, 5, 8, 1] [1, 2, 3, 5, 8]

Sắp xếp nhanh (Quick Sort)

Quick Sort là thuật toán sắp xếp đệ quy dựa trên nguyên tắc chia để trị. Thuật toán này hoạt động bằng cách chọn một phần tử gọi là “pivot” và chia danh sách thành hai phần: các phần tử nhỏ hơn pivot và các phần tử lớn hơn pivot. Sau đó, đệ quy sắp xếp các phần tử nhỏ hơn và lớn hơn pivot cho đến khi danh sách được sắp xếp.

Ý tưởng:

  • Chọn một phần tử làm pivot.
  • Chia danh sách thành hai phần: các phần tử nhỏ hơn pivot và các phần tử lớn hơn pivot.
  • Đệ quy sắp xếp các phần tử nhỏ hơn và lớn hơn pivot.
  • Kết hợp các phần tử đã sắp xếp với pivot để tạo thành danh sách đã sắp xếp.

Độ phức tạp: O(nlogn)

Ví dụ: Sắp xếp mảng số nguyên theo thứ tự tăng dần.

Bước Mảng trước khi sắp xếp Mảng sau khi sắp xếp
1 [5, 3, 8, 2, 1] [1, 3, 2, 5, 8]
2 [1, 3, 2] [1, 2, 3]
3 [5, 8] [5, 8]

Sắp xếp trộn (Merge Sort)

Merge Sort là thuật toán sắp xếp đệ quy dựa trên nguyên tắc chia để trị. Thuật toán này hoạt động bằng cách chia danh sách thành hai phần bằng nhau, đệ quy sắp xếp từng phần và kết hợp chúng lại để tạo ra danh sách đã sắp xếp.

Ý tưởng:

  • Chia danh sách thành hai phần bằng nhau.
  • Đệ quy sắp xếp từng phần.
  • Kết hợp các phần đã sắp xếp để tạo ra danh sách đã sắp xếp.

Độ phức tạp: O(nlogn)

Ví dụ: Sắp xếp mảng số nguyên theo thứ tự tăng dần.

Bước Mảng trước khi sắp xếp Mảng sau khi sắp xếp
1 [5, 3, 8, 2, 1] [1, 2, 3, 5, 8]
2 [5, 3] [3, 5]
3 [8, 2, 1] [1, 2, 8]
4 [3, 5] [3, 5]
5 [1, 2, 8] [1, 2, 8]

Xem thêm: Tổng hợp các thuật toán sắp xếp c++ tại đây

Thuật toán tìm kiếm trong C++

Thuật toán tìm kiếm là thuật toán tìm kiếm một giá trị cụ thể trong một tập hợp. Các thuật toán tìm kiếm trong C++ phổ biến bao gồm: tìm kiếm tuần tự, tìm kiếm nhị phân.

c++ algorithm

Tìm kiếm tuần tự (Linear Search)

Linear Search là thuật toán tìm kiếm bằng cách lặp qua từng phần tử trong danh sách cho đến khi tìm thấy giá trị cần tìm hoặc hết danh sách.

Ý tưởng:

  • Lặp qua từng phần tử trong danh sách.
  • So sánh phần tử hiện tại với giá trị cần tìm.
  • Nếu phần tử hiện tại bằng giá trị cần tìm, trả về vị trí của phần tử.
  • Nếu hết danh sách mà không tìm thấy giá trị cần tìm, trả về -1.

Độ phức tạp: O(n)

Ví dụ: Tìm kiếm giá trị 5 trong mảng số nguyên.

Bước Mảng Giá trị cần tìm Kết quả
1 [3, 8, 2, 5, 1] 5 3
2 [3, 8, 2, 5, 1] 5 4

Tìm kiếm nhị phân (Binary Search)

Tìm kiếm nhị phân là thuật toán tìm kiếm bằng cách chia đôi danh sách và so sánh giá trị cần tìm với phần tử ở giữa danh sách. Nếu giá trị cần tìm nhỏ hơn phần tử ở giữa, tiếp tục tìm kiếm trong nửa đầu của danh sách. Ngược lại, tìm kiếm trong nửa sau của danh sách.

Ý tưởng:

  • Chia đôi danh sách.
  • So sánh giá trị cần tìm với phần tử ở giữa danh sách.
  • Nếu giá trị cần tìm nhỏ hơn phần tử ở giữa, tiếp tục tìm kiếm trong nửa đầu của danh sách.
  • Ngược lại, tìm kiếm trong nửa sau của danh sách.
  • Lặp lại quá trình cho đến khi tìm thấy giá trị cần tìm hoặc hết danh sách.

Độ phức tạp: O(logn)

Ví dụ: Tìm kiếm giá trị 5 trong mảng số nguyên đã được sắp xếp.

Bước Mảng Giá trị cần tìm Kết quả
1 [1, 2, 3, 5, 8] 5 3
2 [1, 2, 3] 5 -1

Thuật toán đệ quy trong C++

Thuật toán đệ quy là thuật toán dựa trên nguyên tắc chia để trị. Nó hoạt động bằng cách gọi lại chính nó với các bài toán con nhỏ hơn cho đến khi đạt được kết quả cuối cùng.

Ví dụ: Tính giai thừa bằng đệ quy

Giai thừa của một số nguyên dương n được định nghĩa là tích của các số từ 1 đến n. Ví dụ: 5! = 1  2  3  4  5 = 120.

Ý tưởng:

  • Nếu n = 0 hoặc n = 1, trả về 1.
  • Ngược lại, tính giai thừa của n – 1 và nhân với n.

Độ phức tạp: O(n)

Ví dụ: Tính giai thừa của 5.

Bước Giá trị n Kết quả
1 5 120
2 4 24
3 3 6
4 2 2
5 1 1

Thuật toán tham lam trong C++

Thuật toán tham lam là thuật toán tìm kiếm giải pháp tốt nhất tại mỗi bước để đạt được kết quả cuối cùng tốt nhất. Nó không đảm bảo tìm ra giải pháp tối ưu nhưng thường cho kết quả gần với giải pháp tối ưu.

Ví dụ: Tìm số tiền ít nhất để trả lại

Giả sử bạn có các loại tiền sau: 1 đô la, 5 đô la, 10 đô la, 20 đô la, 50 đô la, 100 đô la. Hãy tính số tiền ít nhất cần trả lại khi khách hàng thanh toán một khoản tiền bất kỳ.

Ý tưởng:

  • Lặp qua từng loại tiền theo thứ tự lớn đến nhỏ.
  • Trừ số tiền cần trả lại với số tiền hiện có.
  • Đếm số lượng tiền đã trừ.
  • Lặp lại cho đến khi số tiền cần trả lại bằng 0.

Độ phức tạp: O(n)

Ví dụ: Trả lại 75 đô la.

Bước Số tiền cần trả lại Số tiền hiện có Số lượng tiền đã trừ
1 75 100 1
2 25 50 1
3 5 20 1

Thuật toán chia để trị trong C++

Thuật toán chia để trị là thuật toán dựa trên nguyên tắc chia bài toán thành các bài toán con nhỏ hơn, giải quyết từng bài toán con và kết hợp kết quả để đạt được kết quả cuối cùng.

Ví dụ: Tìm số lớn nhất trong mảng số nguyên

Ý tưởng:

  • Chia mảng thành hai nửa.
  • Đệ quy tìm số lớn nhất trong mỗi nửa.
  • So sánh số lớn nhất của hai nửa với nhau và trả về số lớn hơn.

Độ phức tạp: O(nlogn)

Ví dụ: Tìm số lớn nhất trong mảng [5, 8, 2, 1, 9].

Bước Mảng Số lớn nhất
1 [5, 8, 2] 8
2 [5] 5
3 [8, 2] 8
4 [1, 9] 9
5 [8, 9] 9

Thuật toán động trong C++

Thuật toán động là thuật toán tối ưu hóa bằng cách lưu trữ và sử dụng lại các kết quả tính toán trước đó.

Ví dụ: Tìm số Fibonacci thứ n

Dãy Fibonacci là dãy số bắt đầu từ 0 và 1, các số tiếp theo được tính bằng cách cộng hai số trước đó. Ví dụ: 0, 1, 1, 2, 3, 5, 8, …

Ý tưởng:

  • Sử dụng một mảng để lưu trữ các số Fibonacci đã tính toán.
  • Nếu số Fibonacci thứ n đã được tính toán trước đó, trả về giá trị đã tính.
  • Ngược lại, tính số Fibonacci thứ n bằng cách cộng hai số Fibonacci trước đó và lưu vào mảng.

Độ phức tạp: O(n)

Ví dụ: Tính số Fibonacci thứ 6.

Bước Số Fibonacci đã tính Kết quả
1 [0, 1] 8
2 [0, 1, 1] 8
3 [0, 1, 1, 2] 8
4 [0, 1, 1, 2, 3] 8
5 [0, 1, 1, 2, 3, 5] 8

Thuật toán đồ thị trong C++

Thuật toán đồ thị là thuật toán dùng để tìm kiếm và xử lý các đồ thị. Các thuật toán đồ thị phổ biến trong C++ bao gồm: Dijkstra, Prim, Kruskal, …

Ví dụ: Thuật toán Dijkstra

Thuật toán Dijkstra được sử dụng để tìm đường đi ngắn nhất từ một đỉnh đến tất cả các đỉnh còn lại trong đồ thị có trọng số dương.

Ý tưởng:

  • Khởi tạo một mảng lưu khoảng cách từ đỉnh xuất phát đến các đỉnh khác.
  • Khởi tạo một hàng đợi ưu tiên lưu các đỉnh chưa được duyệt theo thứ tự khoảng cách tăng dần.
  • Lặp cho đến khi hàng đợi ưu tiên trống:
  • Lấy ra đỉnh có khoảng cách nhỏ nhất trong hàng đợi.
  • Duyệt qua các đỉnh kề với đỉnh hiện tại và cập nhật khoảng cách nếu có đường đi ngắn hơn.
  • Thêm các đỉnh đã duyệt vào mảng lưu khoảng cách.
  • Trả về mảng lưu khoảng cách.

Độ phức tạp: O(ElogV) (E là số cạnh, V là số đỉnh)

Ví dụ: Tìm đường đi ngắn nhất từ đỉnh A đến các đỉnh khác trong đồ thị sau.

Bước Đỉnh được duyệt Khoảng cách từ A
1 A 0
2 B 3
3 C 6
4 D 7
5 E 9
6 F 11

Ứng dụng của thuật toán trong khoa học máy tính

Thuật toán là một công cụ quan trọng trong khoa học máy tính và có rất nhiều ứng dụng trong thực tế. Dưới đây là một số ví dụ về ứng dụng của thuật toán trong khoa học máy tính.

  • Trong lĩnh vực xử lý ảnh, thuật toán được sử dụng để nhận diện khuôn mặt, phân loại ảnh, nén ảnh, …
  • Trong lĩnh vực trí tuệ nhân tạo, thuật toán được sử dụng để xây dựng các mô hình học máy và học sâu.
  • Trong lĩnh vực tìm kiếm và khai thác dữ liệu, thuật toán được sử dụng để phân tích dữ liệu, dự đoán xu hướng và tìm kiếm thông tin.
  • Trong lĩnh vực trò chơi, thuật toán được sử dụng để xây dựng các trò chơi điện tử và trí tuệ nhân tạo để chơi các trò chơi.
  • Trong lĩnh vực mạng máy tính, thuật toán được sử dụng để quản lý và tối ưu hóa mạng.
  • Trong lĩnh vực tài chính, thuật toán được sử dụng để dự đoán giá cổ phiếu, quản lý rủi ro và tối ưu hóa các giao dịch.
  • Trong lĩnh vực y tế, thuật toán được sử dụng để phân tích dữ liệu bệnh nhân, dự đoán kết quả điều trị và phát hiện bệnh.
  • Trong lĩnh vực điều khiển tự động, thuật toán được sử dụng để điều khiển các thiết bị và hệ thống tự động.
  • Trong lĩnh vực robot, thuật toán được sử dụng để điều khiển và lập kế hoạch cho các robot di chuyển và thực hiện các tác vụ.
  • Trong lĩnh vực truyền thông, thuật toán được sử dụng để mã hóa và giải mã thông tin.

Kết luận

Trên đây là một số khái niệm cơ bản về thuật toán trong ngôn ngữ lập trình C++, cùng với các ví dụ và ứng dụng thực tế của chúng. Hiểu và áp dụng tốt các thuật toán sẽ giúp chúng ta giải quyết các vấn đề phức tạp trong khoa học máy tính một cách hiệu quả. Hy vọng bài viết của TopDev đã giúp bạn có cái nhìn tổng quan về thuật toán trong C++ và có những điều chỉnh phù hợp trong công việc của mình.

Bài viết chỉ mang tính chất tham khảo

Nội dung được tổng hợp bởi AI và điều chỉnh bởi Ban Biên tập TopDev 

Cập nhật tin tuyển dụng IT lương cao tại TopDev

Fix lỗi Force layout, reflow ảnh hưởng tới performance Frontend

Fix lỗi Force layout, reflow ảnh hưởng tới performance Frontend

Bài viết được sự cho phép của tác giả Thanh Lê

Tại sao nên đọc bài này?

  • Tìm hiểu xem Force Layout, reflow là gì?
  • Cách khắc phục, work around

Force layout

Force layout

Force layout/reflow là mỗi point ảnh hưởng cực lớn tới performance của website (Đặc biệt là mấy trang web phức tạp), mà nguyên nhân tạo ra nó mình thấy khá là… chí mạng. Vài dòng code cơ bản thôi mà lại khiến hậu quả lớn đến vậy!?

Như ví dụ trên hình trên là kết quả Performance check của CoinMarketCap, thời gian Hydrate là 1.03s, và trong đó, task force layout/reflow đã chiếm đâu đó khoảng 0.2s rồi (Tức là 20%)

Sau khi tìm hiểu rồi debug các kiểu thì mình nhận ra là issue này xuất phát từ một dòng lệch cực kì xàm

if (window.innerWidth < MOBILE_SIZE) {

Vậy cụ thể lỗi trên là như nào?

Những lỗi trên gọi là Layout Thrashing

Layout Thrashing means: Forcing the browser to calculate a layout that is never rendered to the screen.

Hiểu cơ bản là, nếu bạn dùng JS truy cập vào những thuộc tính liên quan tới layout thì thằng Browser sẽ phải tính toán lại data của layout đó để trả về cho bạn. Và công việc này khá là tốn resource CPU

Hồi xưa thì mình nghĩ là mọi con số về layout đều đã được tính toán và ready bởi trình duyệt rồi, kiểu như div này width bao nhiêu, height bao nhiêu thì render ra ngoài rồi phải nắm chứ nhỉ, vậy mà khi JS access vô thì nó không có mà phải tính lại ?!?!

Hmm, kì quá ta, vậy khi nào thì bị hiện tượng này? Chẳng lẽ avoid dùng mấy cái như window.innerWidth đồ luôn?

Layout Thrashing happens, when you request layout information of an element or the document, while layout is in an invalidated state.

// any DOM or CSSOM change flags the layout as invalid
document.body.classList.add('foo');

// reads layout == forces layout calculation
const box = element.getBoundingClientRect();

// write/mutate
document.body.appendChild(someBox);

//read/measure
const color = getComputedStyle(someOtherBox).color;

Rồi về cơ bản nếu bạn mutate DOM với những thứ liên quan tới Layout sẽ khiến cho layout invalid, và tiếp theo read các thuộc tính tới layout thì sẽ cần đợi thằng Browser render lại rồi mới trả số cho bạn được.

Như ví dụ trên document.body.classList.add('foo'); là một lệnh làm thay đổi layout, và đo đó, khi element.getBoundingClientRect(); run đoạn này sẽ cần đợi Browser tính toán lại layout mới rồi mới trả số được.

Tụi Browser đơn giản chỉ muốn thì thầm vào tai bạn

Fuck off , đừng có đụng vào cây DOM của tao. Tụi mày nên tôn trọng và tự sửa code lại cho hợp lý đi nhá

Vậy là cái issue ở trên mình gặp là mình đang read window.innerWidth mà chắc chắn trước đó đã có thằng nào mutate layout rồi.

  Thuật toán frontend: Tìm node chứa content chính

  Tổng hợp các thuật ngữ trong Frontend bạn nhất định phải biết!

Sửa sao cho vừa lòng Browser?

Cơ bản bạn sẽ cần tách ra 2 phần khi xử lý DOM

  • Read layout
  • Mutate DOM
// reads layout
const box = element.getBoundingClientRect();
const color = getComputedStyle(someOtherBox).color;

// write
document.body.classList.add('foo');
document.body.appendChild(someBox);

Read Layout sẽ không làm thay đổi gì thằng DOM cả, do đó chúng ta nên read nó đầu tiên, rồi xong sau mới bảo tụi Browser là ok, xong rồi, giờ mutate cái DOM hộ bố cái!

Ngoài ra với các tình huống phức tạp thì mình có thể dùng thư viện, cụ thể là Fastdom

import fastdom from 'fastdom';

function resizeAllParagraphsToMatchBoxWidth(paragraphs, box) {

    fastdom.measure(() => {
        const width = box.offsetWidth;

        fastdom.mutate(() => {
            for (let i = 0; i < paragraphs.length; i++) {
                paragraphs[i].style.width = width + 'px';
            }
        });
    });
}

Tham khảo việc làm Front-End hấp dẫn trên TopDev

Lifecycle của một frame

Ok giờ chuyên sâu hơn một xíu

Lifecycle của một frame
Mỗi lần vsync nghĩa là máy chúng ta sync data lên màn hình, cái này tương đương với một khung hình mới đó

Lifecycle của một frame

Lifecycle của một frame

Ròi, ngắn gọn là vầy:

  1. Nhận input event từ user. Có thể là click, scroll, touch,…
  2. JS xử lý đống event đó
  3. requestAnimationFrameObserver callback chạy (nếu có)
  4. Sau khi mọi thứ đủ đầy, commit mọi thứ ra màn hình – nghĩa là mapping những thứ đã tính toán được (Div này width bao nhiêu, height bao nhiêu, position ở đâu, bla bla) ra màn hình máy tính của user

Bằng cách hiểu cái life cycle như vậy, chúng ta tránh việc Layout Thrashing bằng cách:

Thay vì vừa read vừa write layout
Thay vì vừa read vừa write layout
Đưa cái đoạn write vào requestAnimationFrame
Đưa cái đoạn write vào requestAnimationFrame

Cách debug

Cái này thì cũng khá đơn giản. Bạn bật Web debug tool lên, ấn vào tab Performance, set cái CPU slow xuống x6 (Nếu máy bạn mạnh). Rồi Start Profiling

Cách debug

Nằm chờ, sau đó coi trong đó có cái thằng nào màu tím góc trên hiện màu đỏ như hình ở đầu bài không nhé.

Đây là list các thuộc tính có liên quan tới Layout Thrashing: https://gist.github.com/paulirish/5d52fb081b3570c81e3a

Cách workaround

Rồi, nói chung nếu muốn fix theo cách chính thống thì mình đã nói ở trên là tách vụ Read layout và Mutate layout riêng biệt và nhét vào rAF. Tuy nhiên nhiều khi nó cũng phức tạp và mệt mỏi, thì mình có một tip nhỏ để workaround.

Ở JS head mình đọc Layout data đó và lưu vào một biến cache, VD

window.widthCached = window.innerWidth

Rỗi giờ chỗ nào read window.innerWidth thì thay bằng window.widthCached là xong. Vậy là solve được vấn đề mình gặp phải ở đâu bài ‍

Đương nhiên là cái idea này không thể apply được cho mọi trường hợp, chỉ có những thuộc tính gần như là ít thay đổi, và ready lúc mình cần lưu cache thì mới chạy được thôi. Tuy nhiên work-around thì tùy vào năng lực sáng tạo của bạn mà.

Bài viết gốc được đăng tải tại thanhle.blog

Xem thêm:

Tham khảo ngay việc làm IT mọi cấp độ trên TopDev!

7 cách ChatGPT giúp bạn lập trình tốt hơn và nhanh hơn

7 cách ChatGPT giúp bạn lập trình tốt hơn và nhanh hơn

Bài viết được sự cho phép của tác giả Trần Ngọc Minh

1. Lập kế hoạch dự án (Project Planning)

Lập kế hoạch dự án là giai đoạn quan trọng nhất của bất kỳ dự án nào, nơi bạn đặt nền móng cho sự thành công. Nhận được sự hỗ trợ của ChatGPT trong giai đoạn lập kế hoạch có thể rất quý giá vì nó có thể giúp bạn suy nghĩ về phạm vi, kiến trúc, yêu cầu và khả năng thực hiện của dự án phát triển phần của bạn.

Lập kế hoạch dự án (Project Planning)

Bằng cách mô tả mục tiêu, ràng buộc và trường hợp sử dụng của bạn cho ChatGPT, nó có thể đưa ra những gợi ý hữu ích liên quan đến:

  • Công nghệ và công cụ để lựa chọn dựa trên nhu cầu cụ thể của bạn
  • Thiết kế và kiến trúc cấp cao
  • Những nhiệm vụ và bước quan trọng cần thực hiện theo đúng trình tự
  • Những vấn đề, rủi ro và trở ngại tiềm ẩn cần chú ý

2. Phân chia hệ thống phức tạp (Break down the Complex System)

Tránh yêu cầu ChatGPT viết code cho một hệ thống đầu-cuối từ đầu. Nó có thể tạo ra code chung chung, có lỗi, bỏ sót các trường hợp ngoại lệ và không đáp ứng được các yêu cầu cụ thể của bạn.

Thay vào đó, hãy tập trung sự hỗ trợ của ChatGPT vào những nhiệm vụ nhỏ, rõ ràng trong hệ thống tổng thể của bạn. Hãy yêu cầu nó tạo code cho:

  • Các hàm hoặc phương thức cụ thể thực hiện một bước logic
  • Các lớp riêng biệt để đại diện cho các phần có ranh giới rõ ràng của miền của bạn
  • Các thuật toán hoặc quy trình riêng biệt trong quy trình làm việc đầy đủ của bạn

Việc chia nhỏ vấn đề của bạn thành những thành phần nhỏ hơn sẽ tạo ra code dễ quản lý và có tính mô-đun hơn.

  Dân IT có thể được ChatGPT hỗ trợ code tự động hóa như thế nào?

  Làm thế nào để biến ChatGPT thành một "chuyên gia"?

3. Code sạch và dễ đọc (Clean Readable Code)

Code sạch và dễ đọc (Clean Readable Code)

ChatGPT có thể đề xuất những cách để làm cho code của bạn sạch sẽ và dễ đọc hơn bằng cách tuân theo các nguyên tắc tốt nhất cho ngôn ngữ lập trình và framework của bạn.

Bạn có thể sử dụng ChatGPT để đổi tên biến rõ ràng, chia nhỏ các hàm dài một cách hợp lý, giảm độ lồng nhau, thêm nhận xét nội tuyến và định dạng code một cách nhất quán để làm cho code của bạn dễ đọc, dễ bảo trì và không có lỗi cho người cộng tác.

4. Kiểm thử và xác minh đơn vị (Unit Testing and Verification)

Sau khi tạo ra một code, việc xác minh nó trên một máy cô lập trước khi đưa nó vào sản xuất hoặc một kho lưu trữ từ xa là rất quan trọng. Điều quan trọng là không nên hoàn toàn dựa vào chức năng của code mà cần đảm bảo rằng nó đang sử dụng API mới nhất.

Một trong những khía cạnh then chốt của phát triển phần mềm là tạo ra các hàm kiểm thử cho các chức năng quan trọng. Với sự hỗ trợ của ChatGPT, bạn có thể tạo ra các trường hợp kiểm thử cho bất kỳ hàm nào trong vài giây.

Việc làm AI lương thưởng hấp dẫn, mới nhất dành cho bạn!

5. Lặp lại (Iterate)

ChatGPT là một AI hội thoại và bạn có thể liên tục yêu cầu sự hỗ trợ trong việc thêm hoặc xóa các phần tử từ code của bạn, hoặc thậm chí yêu cầu cải tiến. Trong trường hợp xảy ra lỗi, chỉ cần sao chép và dán thông báo lỗi và yêu cầu ChatGPT tạo ra một phiên bản code cải tiến cho bạn.

Nó hiểu được ngữ cảnh và có thể tạo ra code phù hợp với nhiệm vụ đang thực hiện, đảm bảo chức năng và hiệu quả.

6. Tài liệu hóa code (Documenting Code)

Code được tài liệu hóa tốt là rất quan trọng cho bản thân bạn và các nhà phát triển khác để hiểu dự án của bạn. ChatGPT có thể giúp bạn tài liệu hóa code thông qua các nhận xét, docstring, tệp README, trang wiki và các tài liệu khác dựa trên ngôn ngữ và công cụ của bạn.

Tất cả những gì bạn cần làm là cung cấp một mô tả dự án ngắn gọn và một đoạn code của bạn, và ChatGPT sẽ tạo ra tài liệu sạch sẽ và dễ đọc sẽ giúp bạn hiểu codebase của bạn rất nhiều.

Nguồn: 7 Ways ChatGPT Makes You Code Better and Faster

Bài viết gốc được đăng tải tại ngocminhtran.com

Xem thêm:

Tìm kiếm việc làm IT mới nhất tại TopDev!

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

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

Bài viết được sự cho phép của tác giả Trần Ngọc Minh

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

Multiprocessing – Xử lí đa nhiệm

Multitasking (đa nhiệm vụ)

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

Multiprocessing (đa tiến trình)

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

Multithreading (đa tiểu trình)

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

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

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

Tranh chấp tài nguyên

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

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

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

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

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

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

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

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

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

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

  5 Điều Cần Trang Bị Để Trở Thành Lập Trình Viên .NET Giỏi

Khoá (lock)

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

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

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

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

Khoá chết (deadlock)

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

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

Tìm ngay việc làm .NET HCM tại TopDev!

Task Parallel Library

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

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

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

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

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

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

1
MOV AL, 61h

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Visual Studio

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

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

Xem ngay tin việc làm .NET tại các doanh nghiệp hàng đầu trên TopDev

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

Thực đơn (menu)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Hộp thoại (dialog box)

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

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

Hộp thoại (dialog box)

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

Hộp thoại (dialog box)

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

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

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

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

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

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

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

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

Thiết kế giao diện người dùng

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

Luật số 7

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

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

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

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

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

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

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

Biến (variables)

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

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

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

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

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

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

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

Lệnh điều khiển

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

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

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

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

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

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

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

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

Toán tử (operator)

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

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

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

Routine

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

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

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

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

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

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

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

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

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

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

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

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

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

Các vấn đề khác

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Bài viết gốc được đăng tải tại ngocminhtran.com

Có thể bạn quan tâm:

Tìm kiếm việc làm IT mới nhất tại TopDev!

20 mẹo xây dựng thương hiệu cá nhân hiệu quả trên LinkedIn (Phần 1)

20 mẹo xây dựng thương hiệu cá nhân hiệu quả trên LinkedIn

Bài viết được sự cho phép của tác giả Lê Tuấn Anh

LinkedIn hiện tại không chỉ là một kênh tìm việc tốt, xây dựng mối quan hệ tốt mà còn là nền tảng phù hợp để những ai đang đi làm xây dựng thương hiệu cá nhân chuyên nghiệp. Sau 8 năm sử dụng LinkedIn ở nhiều vai trò khác nhau từ ứng viên, người làm tuyển dụng và người xây dựng nội dung với hơn 21,000 lượt theo dõi, mình thấy rằng LinkedIn đã mang lại cho bản thân rất nhiều lợi ích và cơ hội.

Xung quanh mình đã nhiều người biết đến LinkedIn, nhưng có thể chưa dành thời gian đào sâu tìm hiểu và tận dụng triệt để các tính năng. Vì vậy trong bài viết này, mình chia sẻ đến các bạn 20 tips ngắn gọn để xây dựng thương hiệu cá nhân thu hút trên LinkedIn. Một thương hiệu cá nhân thu hút sẽ giúp bạn tìm việc tốt hơn hoặc xây dựng các mối quan hệ chất lượng hơn trên nền tảng mạng xã hội nghề nghiệp này.

Trong Phần 1, mình sẽ chia sẻ 10 tips đầu tiên.

1. Cá nhân hoá đường dẫn (URL)

Có hai đường dẫn như bên dưới, bạn thấy đường dẫn nào trông gọn gàng hơn?

  1. https://www.linkedin.com/in/anhtuanle234/
  2. https://www.linkedin.com/in/abcd-pham-2726a2148/

Không cần bàn cãi, lựa chọn 1 gọn gàng hơn đúng không nè? LinkedIn cho phép bạn tự viết lại đường dẫn và bạn nên thực hiện việc này. Link đường dẫn có tên bạn giúp bạn dễ nhận diện hơn, đính kèm vào các hồ sơ tìm việc, email trông chuyên nghiệp hơn. Trong trường hợp tên bạn bị trùng, bạn có thể thêm 1-2 con số phía sau, không nên thêm thắt quá nhiều từ. Sửa URL ở góc phải nhé.

2. Sửa Headline bên dưới tên

Headline dưới tên bạn giống như slogan của một công ty, là thứ đầu tiên hiện lên cùng với tên khi người khác tìm thông tin của bạn trên LinkedIn. Thông thường phần này để mặc định là tên công việc bạn đang làm. Tuy nhiên, bạn có thể đổi lại tuỳ theo mục đích đang tìm việc hay xây dựng mạng lưới quan hệ hay với mục đích khác. Hãy cứ tưởng tượng là có người đang tìm kiếm thông tin về bạn, bạn muốn họ tìm thấy bạn với thông tin gì?

Ví dụ, Tuấn Anh muốn mọi người tìm đến mình để thuê mình làm tư vấn hướng nghiệp hoặc viết lách, vì vậy Tuấn Anh để headline là A career consultant & a writer, vậy khi ai đó tìm “career consultant” hoặc tìm “writer” thì sẽ ra thông tin của mình. Mới mấy hôm trước khi viết bài này có một doanh nghiệp bên Italia đang tìm người viết ở thị trường Việt Nam và tìm ra mình bằng cách này.

Giới hạn cho phần này là 220 ký tự, trong đó chỉ 60-65 ký tự đầu tiên hiển thị cùng tên bạn khi bạn comment hoặc xuất hiện ở trang của ai đó. Vậy nên hãy chọn lọc từ ngữ kỹ càng nhé.

Ví dụ bên dưới là một số người đã vào xem LinkedIn của Tuấn Anh kèm tên và Headlines của các bạn/anh/chị ấy.

3. Sử dụng avatar chuyên nghiệp chất lượng cao

Bên cạnh tên, headline như đã nói ở trên, hình là thứ xuất hiện đầu tiên khi người khác tìm thông tin về bạn trên LinkedIn. Các cụ hay nói “nhìn mặt mà bắt hình dong”, có nghĩa là nếu hình chỉn chu, chuyên nghiệp thì cơ hội được để mắt tới của bạn cũng cao hơn.

Hạn chế để hình selfie, hình chất lượng thấp hoặc có background lộn xộn. Nên để những tấm hình rõ mặt, có thể là hình thẻ (phải đẹp nha), hoặc hình bạn trong môi trường làm việc chuyên nghiệp. Vì đa số trường hợp ảnh LinkedIn của bạn sẽ xuất hiện nhỏ (trong comment, trong thanh công cụ tìm kiếm), nên cố gắng làm sao rõ mặt nhất có thể. Màu sắc cũng có thể ảnh hưởng phần nào đến cảm quan của người xem, nên bạn cân nhắc chọn màu phù hợp, thông thường màu xám nền là đơn giản và chuyên nghiệp nhé.

Kích cỡ hình là 400 x 400 pixels và giới hạn lên đến 8MBs, thoải mái. Nếu chưa có tấm hình nào chuyên nghiệp, mình khuyến khích bạn bớt chút xiền đi làm ngay một bộ. Bạn có thể xem ảnh ở phần 1 trên để mường tượng hình của mình.

  Cách Viết Summary Trên LinkedIn Để Thu Hút Các Nhà Tuyển Dụng

  9 kênh tuyển dụng IT hiệu quả bạn nên sử dụng

4. Tận dụng ảnh Cover

Bên cạnh ảnh avatar thì trên đầu LinkedIn có một ảnh cover kích cỡ 1586 x 396 pixels. Bạn có thể để bất kỳ ảnh gì ở đây. Vì phần này cũng không xuất hiện nhiều như avatar (chỉ khi người xem ấn vào Profile bạn mới thấy), bạn có thể chọn để ảnh đơn giản về background công ty bạn đang làm (nếu muốn xây dựng quan hệ), hình ngành nghề bạn đang theo đuổi (nếu đang tìm việc), hoặc một hình bất kỳ bạn thiết kế.

5. Phần “About” nên viết thế nào cho hay?

‘About’ là phần quan trọng nhất trong LinkedIn. Phần này nên nói rõ bạn là ai, bạn đã đạt được những gì và bạn đang mong muốn nhận lại gì từ LinkedIn. Phần này tối đa 2,000 ký tự nên bạn có thể viết thoải mái mà không lo thiếu.

Đoạn đầu tiên nên dùng để giới thiệu nhanh về bạn, có bao nhiêu năm kinh nghiệm trong ngành gì và có kỹ năng gì nổi trội. Những đoạn tiếp theo bạn có thể dùng để tóm gọn về 1 hay nhiều thành tích nổi bật bạn đã có trong công việc. Đoạn cuối bạn dùng để nói về nhu cầu bạn mong muốn qua LinkedIn (tìm việc kiểu gì, xây dựng mối quan hệ với ai), kèm theo thông tin liên lạc của bạn. Tuỳ thuộc vào mục đích tìm việc mà bạn có thể chọn ghi tiếng Anh hoặc tiếng Việt.

6. Tập trung vào những “từ khoá” quan trọng

Giống như khi làm bài đọc tiếng Anh cần tìm ra những từ khoá quan trọng, khi viết các nội dung trong LinkedIn bạn cũng cần có những từ khoá quan trọng cho riêng mình. Mỗi ngành nghề lại có những từ khoá chuyên môn và chuyên ngành riêng thường được sử dụng. Các từ khoá này thường được sử dụng trong các tin tuyển dụng hoặc được người trong ngành tìm kiếm trên LinkedIn.

Để LinkedIn của bạn xuất hiện nhiều hơn trên thanh tìm kiếm và được tìm kiếm đến đúng chỗ, bạn nên bắt đầu phân tích từ khoá liên quan đến ngành nghề bạn đang làm và đưa vào các vị trí khác nhau trong LinkedIn của bạn. Ví dụ, bạn đang hướng đến Digital Marketing, bạn lên Google gõ “digital marketing keywords” sẽ cho ra các từ khoá như seo, target ad, affiliate marketing, social media marketing, marketing strategy, email marketing. Việc của bạn là phải làm sao để các từ khoá này xuất hiện ở nhiều vị trí khác nhau như Headline tiêu đề, phần About, phần kinh nghiệm làm việc, phần kỹ năng.

Xem thêm Cách viết thư trả lời kết quả phỏng vấn siêu chuẩn

“Featured” là một phần mới của LinkedIn mà nhiều bạn chưa để ý. Nó hiện ở ngay đầu và bạn có thể để hình ảnh, link ở phần này.

Các phần khác của LinkedIn chỉ để được chữ, phần này bạn có thể kèm theo link bài viết, video, hình ảnh. Nếu bạn có một video giới thiệu bản thân thì để chỗ này rất phù hợp.

Phần này cũng phù hợp để bạn khoe những sản phẩm nổi bật như sách đã xuất bản, Portfolio công việc, Resume hoặc Cover Letter.

8. Sự khác nhau của Skills trong CV và LinkedIn?

Trong cả CV và LinkedIn bạn đều có thể để phần Skills. Tuy nhiên điểm khác ở LinkedIn là người khác có thể “chứng nhận”, “endorse” cho Skills bạn ghi. Càng nhiều người chứng nhận, càng uy tín. Bạn có thể ghi đến 50 kỹ năng khác nhau ở phần này.

Bạn có thể kêu gọn bạn bè vào “chứng nhận” cho mình và bản thân bạn cũng có thể đi chứng nhận cho người khác. Có nhiều người chứng nhận cho một kỹ năng nào đó sẽ làm cho phần kỹ năng của bạn rất nổi bật. Tip nhỏ là mới bắt đầu đừng viết nhiều kỹ năng, tập trung 6-8 kỹ năng chính để bạn nhận được nhiều votes nhất có thể.

9. Đẩy mạnh thương hiệu cá nhân qua status

04 – 06 nội dung viết gần nhất sẽ hiện lên đầu trang LinkedIn của bạn. Bạn không cần phải nhận nhiều Likes hay nhiều Comments từ những bài viết này, hãy cứ chăm chỉ viết và chia sẻ một vài nội dung liên quan đến bạn hoặc ngành nghề bạn đang làm, vì biết đâu một ngày nào đó một ai đó vào xem hồ sơ của bạn sẽ thấy ấn tượng về những điều này.

Tuỳ thuộc mục đích và nhóm ngành nghề bạn tập trung và bạn có thể chia sẻ những chủ đề khác nhau. Ví dụ, Tuấn Anh làm tư vấn hướng nghiệp, mình chia sẻ các kiến thức về tìm việc, khám phá bản thân và xây dựng thương hiệu cá nhân trên LinkedIn.

10. Thêm phần Industry vào công việc

Mọi người có xu hướng tìm ứng viên hoặc kết nối với người trong lĩnh vực họ đang làm. Trong phần kinh nghiệm làm việc của LinkedIn có một phần nhỏ là Industry, bạn nhớ đừng bỏ qua phần này. Có thông tin ở phần này giúp hồ sơ của bạn có thể lên thanh Search nhiều hơn khi có người tìm kiếm về ngành nghề, lĩnh vực đó.

Tạm hết phần 01 tại đây, trong tuần tới Tuấn Anh sẽ chia sẻ với bạn thêm 10 tips nữa. Nếu bạn thấy bài viết này hay đừng ngần ngại chia sẻ nhé.

Bài viết gốc được đăng tải tại anhtuanle.com

Xem thêm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Thời Điểm Vàng, Thăng Hạng Sự Nghiệp

thời điểm vàng, thăng hạn sự nghiệp

Mùa tuyển dụng đã bắt đầu rồi, cả nhà ơi! Đặc biệt trong thời điểm này, TopDev hứa hẹn mang đến chương trình ‘Thời Điểm Vàng, Thăng Hạng Sự Nghiệp‘ với những phần quà không thể chối từ. Hãy nhanh tay đăng ký tài khoản hoặc trải nghiệm ngay những tính năng vô cùng tiện ích trên TopDev như Tạo CV Online hoặc Chuẩn Hóa CV để tham gia ngay chương trình này nhé!

promo tháng 3

Hướng dẫn tự quyết toán thuế TNCN online dành cho Người lao động | Năm 2023

quyết toán thuế thu nhập cá nhân
quyết toán thuế thu nhập cá nhân

Bài viết gốc được đăng tải tại thuvienphapluat.vn

Các cá nhân thuộc diện tự quyết toán thuế TNCN năm 2023

Những trường hợp không được ủy quyền quyết toán thuế TNCN thì phải tự quyết toán thuế TNCN từ tiền lương, tiền công.

  • Cá nhân cư trú có thu nhập từ tiền lương, tiền công trực tiếp khai quyết toán thuế TNCN với cơ quan thuế nếu có số thuế phải nộp thêm hoặc có số thuế nộp thừa đề nghị hoàn hoặc bù trừ vào kỳ khai thuế tiếp theo.
  • Cá nhân có mặt tại Việt Nam tính trong năm dương lịch đầu tiên dưới 183 ngày, nhưng tính trong 12 tháng liên tục kể từ ngày đầu tiên có mặt tại Việt Nam là từ 183 ngày trở lên thì năm quyết toán đầu tiên là 12 tháng liên tục kể từ ngày đầu tiên có mặt tại Việt Nam.
  • Cá nhân là người nước ngoài kết thúc hợp đồng làm việc tại Việt Nam khai quyết toán thuế với cơ quan thuế trước khi xuất cảnh. Trường hợp cá nhân chưa làm thủ tục quyết toán thuế với cơ quan thuế thì thực hiện ủy quyền cho tổ chức trả thu nhập hoặc tổ chức, cá nhân khác quyết toán thuế theo quy định về quyết toán thuế đối với cá nhân.
    Trường hợp tổ chức trả thu nhập hoặc tổ chức, cá nhân khác nhận ủy quyền quyết toán thì phải chịu trách nhiệm về số thuế TNCN phải nộp thêm hoặc được hoàn trả số thuế nộp thừa của cá nhân.
  • Cá nhân cư trú có thu nhập từ tiền lương, tiền công đồng thời thuộc diện xét giảm thuế do thiên tai, hỏa hoạn, tai nạn, bệnh hiểm nghèo ảnh hưởng đến khả năng nộp thuế thì không ủy quyền cho tổ chức, cá nhân trả thu nhập quyết toán thuế thay mà phải trực tiếp khai quyết toán với cơ quan thuế theo quy định.

Các bước tự quyết toán thuế TNCN online năm 2023

BƯỚC 1: Đăng nhập hệ thống/Nhập thông tin

Truy cập hệ thống thuế điện tử của Tổng cục Thuế và đăng nhập TẠI ĐÂY

Người nộp thuế điền thông tin mã số thuế và mã kiểm tra rồi nhấn tiếp tục. (Trường hợp quên mã số thuế thì người nộp thuế có thể tham khảo cách tra cứu mã số thuế Tại đây)

Sau khi đăng nhập thành công, sẽ xuất hiện giao diện như hình phía trên.

Chọn “Quyết toán thuế”, sau đó chọn “kê khai trực tuyến” và điền nội dung kê khai online.

Sau đó tại mục “Chọn thông tin tờ khai”, người nộp thuế điền các thông tin bắt buộc và chọn Tờ khai 02/QTT-TNCN.

Tùy theo trường hợp của người nộp thuế mà tích chọn mục phù hợp.

Chọn Cơ quan thuế Quyết toán: nhập vào các ô tương ứng, tích chọn một trong 03 trường hợp:

  • Trường hợp 1: Tích vào ô này nếu NNT có duy nhất 01 nguồn trực tiếp khai thuế trong năm do làm việc tại các tổ chức quốc tế, Đại sứ quán, Lãnh sự quán tại Việt Nam hoặc nguồn từ nước ngoài (không khấu trừ tại nguồn). Sau đó, NNT lựa chọn CQT đã khai trực tiếp trong năm tại ô “Cục thuế” trực tiếp khai thuế trong năm. Sau đó lựa chọn Cục thuế quản lý tổ chức chi trả (chọn cơ quan thuế ở phần tra cứu MST). Loại tờ khai: tờ khai chính thức/bổ sung.
  • Trường hợp 2: Tích vào ô này nếu NNT trực tiếp khai thuế trong năm có từ 02 nguồn trở lên bao gồm cả trường hợp vừa có thu nhập thuộc diện khai trực tiếp trong năm, vừa có thu nhập do tổ chức trả thu nhập đã khấu trừ. Sau đó, người nộp thuế tự kê khai các nguồn thu nhập và thông tin liên quan theo bảng.
  • Trường hợp 3: Tích vào ô này nếu NNT không trực tiếp khai thuế trong năm chỉ có nguồn thu nhập thuộc diện khấu trừ qua tổ chức trả thu nhập. Sau đó khai thông tin về việc thay đổi nơi làm việc.

**Trường hợp 3.1: NNT tích vào ô này nếu có thay đổi nơi làm việc. Sau đó khai thông tin vào ô 1 hoặc ô 2.

– Ô 1: Tại thời điểm quyết toán NNT đang tính giảm trừ gia cảnh cho bản thân tại tổ chức chi trả. Nếu tích vào ô này thì tiếp NNT tục nhập thông tin mã số thuế của tổ chức chi trả tính GTGC cho bản thân.

Nhập Mã số thuế của Tổ chức chi trả thu nhập, nơi đăng ký GTGC cho bản thân

– Ô 2: Tại thời điểm QT NNT không làm việc cho tổ chức chi trả hoặc không tính GTGC cho bản thân tại bất kỳ tổ chức chi trả nào. Nếu  tích vào ô này NNT tiếp tục lựa chọn cơ quan thuế quản lý tại nơi cư trú (tạm trú hoặc thường trú).

**Trường hợp 3.2: NNT tích vào ô này nếu không thay đổi nơi làm việc.Sau đó khai thông tin vào ô 3 hoặc ô 4 hoặc ô 5.

– Ô 3: Tại thời điểm QT vẫn còn làm việc tại tổ chức chi trả. Nếu tích vào ô này NNT tiếp tục nhập thông tin MST của tổ chức chi trả để hệ thống hỗ trợ tự động xác định cơ quan thuế quyết toán.

– Ô 4: Tại thời điểm quyết toán đã nghỉ việc và không làm việc tại bất kỳ tổ chức chi trả nào nào; Nếu tích vào ô này thì NNT tiếp tục lựa chọn cơ quan thuế quản lý tại nơi cư trú (tạm trú hoặc thường trú).

– Ô 5: Tại thời điểm quyết toán NNT chưa tính giảm trừ gia cho bản thân ở bất kỳ tổ chức trả thu nhập nào (tổ chức khấu trừ thuế 10% tại nguồn của cá nguồn). Nếu tích vào ô này NNT tiếp tục lựa chọn cơ quan thuế quản lý tại nơi cư trú (tạm trú hoặc thường trú).

***

Nhấn Tiếp tục => Đến phần NHẬP DỮ LIỆU TỜ KHAI

Ví dụ trường hợp người nộp thuế có thu nhập tại 2 nơi (đã thay đổi nơi làm việc) và đã khấu trừ thuế tại nguồn. Khi nhập mã số thuế của đơn vị thực hiện khấu trù thuế tại thời điểm đang thực hiện quyết toán thuế thì hệ thống tự động nhận diện cơ quan quyết toán thuế. (Xem hình chụp bên dưới)

Tiếp theo, người nộp thuế chọn trường hợp quyết toán thuế.

Chọn “Năm kê khai” là năm 2023 (từ tháng 01/2023 đến tháng 12/2023).

Lưu ý: Trường hợp người nộp thuế thuộc diện xét giảm thuế do thiên tai, hỏa hoạn, tai nạn, bệnh hiểm nghèo ảnh hưởng đến khả năng nộp thuế thì người nộp thuế nộp hồ sơ xét giảm thuế đến cơ quan thuế nơi nộp hồ sơ quyết toán thuế trực tiếp.

Chọn “Tiếp tục” để chuyển đến bước khai tờ khai quyết toán.

BƯỚC 2: Nhập dữ liệu tờ khai

Người nộp thuế nhập dữ liệu tờ khai quyết toán thuế

[01] đến [06]: Hệ thống tự động nhập

Click chọn Tờ khai quyết toán thuế kèm theo hồ sơ giảm thuế do thiên tai, hoả hoạn, tai nạn, bệnh hiểm nghèo nếu người nộp thuế thuộc trường hợp này

[07] đến [08]: Chọn tỉnh, thành phố ở mục 08 trước, sau đó chọn quận huyện ở mục 07

[09]: Điền số điện thoại của NNT: (Bắt buộc điền)

[10]: Fax: Không bắt buộc

[11]: Điền địa chỉ email của NNT. (Bắt buộc điền)

[12] đến [14] Thông tin liên quan đến đại lý thuế (nếu có)

[15] đến [19] Hệ thống tự động điền thông tin

[20] Tổng thu nhập chịu thuế (TNCT) trong kỳ [20]=[21]+[23]

[21] Tổng TNCT phát sinh tại Việt Nam

Là tổng các khoản thu nhập chịu thuế từ tiền lương, tiền công và các khoản thu nhập chịu thuế khác; có tính chất tiền lương tiền công phát sinh tại Việt Nam; bao gồm cả thu nhập chịu thuế từ tiền lương; tiền công do làm việc trong khu kinh tế và thu nhập chịu thuế được miễn theo Hiệp định tránh đánh thuế hai lần (nếu có).

Thu nhập phát sinh ở đâu thì cơ quan chi trả thu nhập xuất chứng từ cho cá nhân, cá nhân lấy thông tin về thu nhập trên các chứng từ đó nhập vào tờ khai.

Ví dụ: Năm 2022, Dương Văn A làm công ty X từ tháng 1 đến tháng 4 có tổng thu nhập chịu thuế theo chứng từ là 50.000.000 đồng, làm công ty Y từ tháng 5 đến tháng 12 có tổng thu nhập chịu thuế theo chứng từ là 200.000.000 đồng. Như vậy tại chỉ tiêu [21], anh A sẽ nhập 250.000.000 đồng.

[22] Tổng TNCT phát sinh tại Việt Nam được miễn giảm theo Hiệp định (nếu có)

[23] Tổng TNCT phát sinh ngoài Việt Nam

[24] Số người phụ thuộc: Chỉ tiêu này hệ thống tự động điền theo số người phụ thuộc mà NTT đã đăng ký.

[25] Các khoản giảm trừ ([25]= [26] + [27] + [28] + [29] + [30]

[26] Giảm trừ cho bản thân cá nhân: Hệ thống tự điền sẵn là 132.000.000 đồng

[27] Giảm trừ cho những người phụ thuộc được giảm trừ: Hệ thống sẽ tính số tiền được giảm trừ theo số người phụ thuộc được đăng ký.

[28] Từ thiện, nhân đạo, khuyến học: NTT tự điền thông tin này theo chứng từ

[29] Các khoản đóng bảo hiểm được trừ: NNT tự điền thông tin này theo chứng từ

[30] Khoản đóng quỹ hưu trí tự nguyện được trừ: NNT tự điền thông tin này theo chứng từ

[31] Tổng thu nhập tính thuế ([31]=[20]-[22]-[25]): Hệ thống sẽ tự tính dựa trên thông tin mà NNT đã nhập

[32] Tổng số thuế thu nhập cá nhân (TNCN) phát sinh trong kỳ: Hệ thống sẽ tự tính dựa trên thông tin mà NNT đã nhập

***

[33] Tổng số thuế đã nộp trong kỳ: ([33]=[34]+[35]+[36]-[37]-[38])

[34] Số thuế đã khấu trừ tại tổ chức trả thu nhập

Số thuế đã khấu trừ tại tổ chức trả thu nhập là số thuế mà tổ chức chi trả thu nhập đã khấu trừ (căn cứ theo chứng từ khấu trừ thuế TNCN).

[35] Số thuế đã nộp trong năm không qua tổ chức trả thu nhập

Số thuế đã nộp trong năm không qua tổ chức trả thu nhập là số thuế TNCN mà cá nhân đã nộp vào ngân sách nhà nước theo mã số thuế của cá nhân người nộp thuế không qua tổ chức trả thu nhập.

[36] Số thuế đã nộp ở nước ngoài được trừ (nếu có)

[37] Số thuế đã khấu trừ, đã nộp ở nước ngoài trùng do quyết toán vắt năm

[38] Số thuế đã nộp trong năm không qua tổ chức trả thu nhập trùng do quyết toán vắt năm

[39] Tổng số thuế TNCN được giảm trong kỳ [39]=[40]+[41]

[40] Số thuế phải nộp trùng do quyết toán vắt năm

[41] Tổng số thuế TNCN được giảm khác

[42] Tổng số thuế còn phải nộp trong kỳ ([42]=([32]-[33]-[39])>0)

[43] Số thuế được miễn do cá nhân có số tiền thuế phải nộp sau quyết toán từ 50.000 đồng trở xuống (0<[42]<=50.000 đồng)

[44] Tổng số thuế nộp thừa trong kỳ ([44]=([32]-[33]-[39])<0)

[45] Tổng số thuế đề nghị hoàn trả [45]=[46]+[47]

[46] Số thuế hoàn trả cho người nộp thuế

[47] Số thuế bù trừ cho khoản phải nộp ngân sách nhà nước khác

[48] Tổng số thuế bù trừ cho các phát sinh của kỳ sau ([48]=[44]-[45])

Trường hợp người nộp thuế đề nghị hoàn trả vào tài khoản của người nộp thuế tại chỉ tiêu [46] thì ghi thêm các thông tin sau:

Trường hợp người nộp thuế đề nghị bù trừ cho khoản phải nộp ngân sách nhà nước khác tại chỉ tiêu [47] thì ghi thêm các thông tin sau:

Đến bước này, người nộp thuế đã có thể xác định được số thuế TNCN được hoàn hay phải nộp thêm.

Sau khi điền xong thì NNT chọn “Hoàn thành kê khai”.

BƯỚC 3: Nộp hồ sơ

Trường hợp cá nhân có tài khoản giao dịch thuế điện tử

=> Bấm Lưu bản nháp + Hoàn thành kê khai => Kết xuất xml => Gửi tờ khai => Chọn phụ lục đính kèm  => Chọn chứng từ khấu trừ (Choose File) => Chọn tiếp tục => Nhập mã xác thực OTP (gửi về điện thoại) => Nộp Tờ khai thành công.

Trường hợp cá nhân chưa có tài khoản giao dịch thuế điện tử

– Bấm Lưu bản nháp + Hoàn thành kê khai

– Chọn kết xuất XML

NNT chọn kết xuất XML trước khi gửi tờ khai.

NNT lưu lại file.

Chọn Nộp tờ khai, Nhập mã kiểm tra để xác thực nộp tờ khai và chọn Tiếp tục.

In tờ khai

Tại bước sau khi chọn “Kết xuất XML“, hệ thống sẽ gửi về cho bạn file tờ khai theo định dạng XML. Sử dụng máy tính có cài itax viewer để mở file tờ khai theo định dạng XML => In => Ký tên người khai thuế.

Tải về ứng dụng itax viewer dưới đây, cài đặt như như các ứng dụng thông thường. Sau khi đã cài đặt thì bạn có thể mở file “kết xuất XML” như bình thường và chọn in 2 bản (Mở file đã kết xuất xml bằng phần mềm iTaxview mới nhất) và nộp đến Cơ quan Thuế (Bộ phận một cửa).

Cách mở file định dạng XML sau khi đã cài đăt xong: Bạn double click để mở hoặc nhấn chuột phải chọn Open.

Trường hợp muốn kiểm tra lại trạng thái Tờ khai đã gửi => Vào Tab: “Tra cứu tờ khai” => Lựa chọn loại tờ khai => Chọn ngày gửi => Tra cứu (mục đích kiểm tra Tờ khai đã được ghi nhận vào hệ thống của Cơ quan Thuế chưa).

Prototype chain là gì? Cách sử dụng Prototype chain hiệu quả

Prototype chain là gì?

Prototype chain là một khái niệm cốt lõi trong JavaScript nhưng không dễ để nắm vững được nhất là đối với các anh em lập trình viên mới học ngôn ngữ này. Hiểu được khái niệm này sẽ giúp bạn dễ dàng triển khai được cơ chế kế thừa trong lập trình hướng đối tượng bằng JS. Bài viết hôm nay chúng ta cùng nhau đi sâu vào khái niệm quan trọng này nhé.

Prototype là gì?

Trong JavaScript, ngoại trừ undefined thì toàn bộ các kiểu còn lại đều là object. Các kiểu dữ liệu nguyên thủy (primitive) như string, số, boolean lần lượt sẽ là các object dạng String, Number, Boolean. Mảng là một object dạng Array, hàm trong JS cũng được xem là một object dạng Function. Vậy ý nghĩa của khái niệm object “dạng” này hay “dạng” kìa là gì? Và làm sao chúng ta biết được 1 object được tạo ra với dạng nào? Để giải quyết vấn đề này thì JS tạo ra khái niệm Prototype.

Prototype là gì?

Nếu như với các ngôn ngữ OOP (hướng đối tượng), kiểu class-based giúp chúng ta xác định rõ một object được tạo ra thuộc vào một class nào, sẽ kế thừa những thuộc tính (properties) và phương thức (methods) nào; thì với JS, việc kế thừa sẽ thực hiện theo kiểu prototype-based. Tất cả các object trong JS đều có một Prototype và các object này kế thừa các thuộc tính cũng như phương thức từ Prototype của mình. Bản thân Prototype là một instance object, chúng ta sử dụng thuộc tính __proto__ để truy cập tới nó.

Với mỗi function trong JavaScript sẽ có một thuộc tính prototype mặc định với kiểu dữ liệu là object. Để thực hiện kế thừa các thuộc tính và phương thức của 1 function trong JS, chúng ta sử dụng thuộc tính prototype này để thêm vào; sau đó thì các đối tượng con tạo ra bởi hàm khởi tạo (constructor) sẽ đều mang các giá trị trong thuộc tính prototype này. Điều này chính là điểm mấu chốt cho khái niệm Prototype chain hay là cơ chế triển khai kế thừa trong JavaScript.

Prototype là gì?

Ví dụ như hình vẽ trên, các object b và c sẽ đều có một Prototype là Foo.prototype có thể truy cập thông qua thuộc tính __proto__. Bản thân Foo là một function, nó sẽ chứa thuộc tính prototype; điều này có nghĩa rằng các object b, c được khởi tạo thông qua hàm constructor của Foo sẽ được kế thừa các phương thức như calculate hay thuộc tính x = 10 có sẵn. Đây chính là cơ chế triển khai tính kế thừa trong OOP của JavaScript.

  Prototype của object

  Prototype pattern – một trong những pattern phổ biến nhất

Prototype chain là gì?

Prototype chain hay chuỗi Prototype, như cái tên của nó, đề cập đến chuỗi quá trình lặp lại trong việc tìm ra các thuộc tính, phương thức đầy đủ của một đối tượng. Như đã nói ở phần trước, một object sẽ có một prototype của riêng mình chứa thông tin về các thuộc tính và phương thức. Vì thế khi ta gọi tới một thuộc tính (hay phương thức) của đối tượng, ban đầu JS sẽ tìm trong thuộc tính riêng của đối tượng; nếu không tìm thấy nó sẽ tiếp tục tìm trong prototype của đối tượng và lặp lại quá trình này với prototype của prototype của đối tượng cho đến khi gặp Object.prototype thì dừng lại và cho ra kết quả undefined nếu không tìm thấy.

Prototype chain là gì?

Tóm lại thì bạn cần nhớ rằng trong JS, mỗi đối tượng sẽ có một liên kết ẩn với prototype của nó – nơi mà sẽ khai báo các thuộc tính và phương thức mà đối tượng đó có, đồng thời cũng là một object chứa liên kết ẩn đến một prototype khác chứa thông tin về prototype này. Prototype chain chính là cơ chế cho phép các đối tượng truy cập vào toàn bộ các thuộc tính, phương thức được định nghĩa bên trong object và toàn bộ các chuỗi prototype gắn với nó.

Tham khảo việc làm Javascript lương hấp dẫn trên TopDev!

Cách sử dụng Prototype chain

Lý thuyết nhiều quá nên chúng ta sẽ đến với phần triển khai code để có thể dễ hiểu hơn nhé. Đầu tiên chúng ta khai báo 1 hàm Person như dưới đây với 2 thuộc tính có sẵn là nameemail:

function Person(name, email) {
  this.name = name;
  this.email = email;
}

Như đã nói ở phần trước thì function Person này sẽ có 1 thuộc tính là prototype; bản thân Prototype này cũng là một object, vì thế chúng ta có thể thêm thuộc tính số điện thoại vào cho nó:

Person.prototype.phone = "0987654321";

let nguyenVanA = new Person("Nguyễn Văn A", "a.nv@gmail.com");

console.log(nguyenVanA); // {name: 'Nguyễn Văn A', email: 'a.nv@gmail.com'}
console.log(nguyenVanA.phone); //0987654321

Đoạn code trên tạo ra đối tượng nguyenVanA với 2 thuộc tính (nameemail) có trong function Person và 1 thuộc tính (phone) lấy từ prototype của Student. Kết quả khi console.log ra nguyenVanA thì sẽ chỉ cho ra 2 thuộc tính nameemail; nhưng chúng ta vẫn sẽ truy cập được thuộc tính phone ở câu console.log bên dưới bình thường.

Tương tự với việc thêm phương thức (methods) cho prototype, chúng ta có thể triển khai như dưới đây:

Person.prototype.showName = function () {
  console.log(this.name);
};

console.log(nguyenVanA.showName()); //Nguyễn Văn A

Thuộc tính phone và phương thức showName được nằm trong chính prototype của Person.

Cách sử dụng Prototype chain

Để triển khai việc kế thừa code trong JavaScript, chúng ta có thể làm theo cách dưới đây. Trước tiên hãy tạo ra 1 hàm Student dùng cho việc kế thừa hàm Person ở trên (ở đây hiểu khái niệm hàm sẽ tương tự với khái niệm class trong OOP).

function Student(id, score) {
  this.id = id;
  this.score = score;

  this.showScore = function () {
    console.log(this.score);
  };
}

Student.prototype = new Person();

Student sẽ có thêm 2 thuộc tính là idscore cùng 1 phương thức là showScore. Ngoài ra prototype của Student được kế thừa từ Person nên chúng ta có thể dễ dàng sử dụng các thuộc tính name, email, phone hay phương thức showName.

let leThiB = new Student(1, 100);
leThiB.name = "Lê Thị B";
leThiB.showName(); //Lê Thị B
leThiB.showScore(); //100

console.log(leThiB.phone); //0987654321

Kết bài

Như vậy chúng ta đã cùng tìm hiểu về khái niệm Prototype chain trong JavaScript cùng với cách triển khai tính kế thừa trong ngôn ngữ lập trình này. Nắm chắc được cơ chế Prototype sẽ giúp bạn hiểu rõ hơn về JS cũng như OOP và cải thiện các kỹ năng lập trình của mình. Hy vọng bài viết hữu ích dành cho bạn và hẹn gặp lại trong các bài viết tiếp theo của mình.

Tác giả: Phạm Minh Khoa

Có thể bạn quan tâm:

Xem thêm các việc làm Developer hấp dẫn tại TopDev

Bí quyết gõ code siêu tốc và hiệu quả cho lập trình viên

Gõ code nhanh là một kỹ năng thiết yếu cho mọi lập trình viên. Nó giúp bạn tiết kiệm thời gian, tăng hiệu quả công việc và giảm thiểu lỗi sai. Để gõ code nhanh, bạn cần kết hợp nhiều yếu tố: kỹ năng gõ phím, kiến thức lập trình, sử dụng công cụ hỗ trợ và thói quen luyện tập. Trong bài viết này, TopDev sẽ hướng dẫn bạn cách gõ code nhanh bằng một số “mẹo” hữu ích.

Vì sao lập trình viên cần gõ code nhanh?

cách gõ code nhanh

Tốc độ gõ code ảnh hưởng trực tiếp đến hiệu suất làm việc của lập trình viên. Trong quá trình phát triển phần mềm, thời gian là một yếu tố quý báu, và việc gõ code nhanh giúp tiết kiệm thời gian và nâng cao năng suất làm việc.

Bên cạnh đó, tốc độ gõ code cũng ảnh hưởng đến tinh thần làm việc và sự tập trung của lập trình viên. Việc gõ code chậm có thể dẫn đến mất tập trung và gây ra sự gián đoạn trong quá trình làm việc, ảnh hưởng đến hiệu suất làm việc tổng thể. Ngược lại, khi có khả năng gõ code nhanh, lập trình viên có thể tập trung hơn vào các vấn đề kỹ thuật và tối ưu hóa mã nguồn một cách hiệu quả.

Cuối cùng, việc gõ code nhanh cũng đồng nghĩa với việc giảm thiểu sai sót trong mã nguồn. Khi làm việc nhanh chóng, lập trình viên có thể dễ dàng bắt kịp lịch trình và đảm bảo chất lượng của mã nguồn. Điều này giúp tránh được các lỗi phát sinh và tiết kiệm thời gian cho việc kiểm tra và sửa lỗi sau này.

  5 tips giúp lập trình viên TẬP TRUNG hơn khi NGỒI CODE

Cách gõ code nhanh hiệu quả

Bằng cách sử dụng kỹ thuật, công cụ hỗ trợ và thói quen luyện tập, bạn có thể trở thành một lập trình viên có khả năng gõ code nhanh, chính xác và hiệu quả. Hãy cùng khám phá những phương pháp và nguyên tắc cơ bản để nắm vững kỹ năng này và nâng cao hiệu suất trong quá trình lập trình.

Nâng cao kỹ năng gõ phím

  • Luyện tập gõ phím mười ngón: Đây là cách gõ code nhanh cơ bản và chính xác. Sử dụng các phần mềm luyện gõ phím như Typing Tutor, Rapid Typing, Keybr để rèn luyện.
  • Học cách gõ tắt: Sử dụng các phím tắt để gõ các lệnh, cú pháp phổ biến trong ngôn ngữ lập trình bạn sử dụng. Điều này giúp tiết kiệm thời gian và tăng hiệu suất trong quá trình lập trình.
  • Tập trung vào việc gõ, hạn chế nhìn bàn phím: Hạn chế nhìn xuống bàn phím giúp bạn tập trung hơn và nâng cao tốc độ gõ code.

Tuyển NodeJS lương cao hấp dẫn cho bạn

Nắm vững kiến thức lập trình

Nắm vững kiến thức lập trình

  • Nắm vững cú pháp và ngữ pháp của ngôn ngữ lập trình: Hiểu rõ cú pháp và ngữ pháp giúp bạn gõ code chính xác và tránh được các lỗi phổ biến.
  • Hiểu rõ chức năng của các thư viện, framework: Hiểu rõ các thư viện, framework giúp bạn sử dụng chúng một cách hiệu quả và tiết kiệm thời gian gõ code.
  • Sử dụng các snippet code: Lưu trữ các đoạn mã thường dùng giúp bạn tiết kiệm thời gian và tăng độ chính xác trong quá trình lập trình.

Tận dụng các công cụ hỗ trợ

  • Sử dụng IDE phù hợp: Chọn IDE có các tính năng hỗ trợ như auto-completion, syntax highlighting, linting, debugging để giúp bạn gõ code nhanh chóng và chính xác.
  • Sử dụng các plugin hỗ trợ gõ code: Cài đặt các plugin để mở rộng chức năng và tăng cường khả năng gõ code trong IDE của bạn.
  • Sử dụng code editor online: Code editor online là một cách gõ code nhanh mọi lúc mọi nơi mà không cần cài đặt phần mềm, tiện lợi khi di chuyển hoặc làm việc từ xa.

Tạo thói quen luyện tập

  • Luyện tập gõ code thường xuyên: Thực hành gõ code hàng ngày giúp bạn tăng tốc độ gõ và cải thiện độ chính xác.
  • Tham gia các cộng đồng lập trình: Tham gia các cộng đồng lập trình để học hỏi kinh nghiệm gõ code từ cộng đồng và chia sẻ kinh nghiệm của bạn.

  Bí kíp luyện Kỹ sư phần mềm: Đọc code!

2 công cụ hữu ích giúp cải thiện tốc độ gõ code

Typing.io là một công cụ tập trung vào việc cải thiện tốc độ và độ chính xác khi gõ code. Nó cung cấp các bài tập và văn bản chứa các đoạn mã nguồn phổ biến trong lập trình, từ JavaScript, Python, Java đến Ruby và nhiều hơn nữa. Mặc dù phiên bản miễn phí có giới hạn về số lượng bài tập và chức năng, giao diện đơn giản và thân thiện với người dùng của Typing.io là điểm cộng lớn.

Typing.io

SpeedCoder.net cung cấp một môi trường luyện tập đa dạng với các bài tập gõ code trong nhiều ngôn ngữ lập trình khác nhau. Tính năng này giúp lập trình viên cải thiện kỹ năng gõ code một cách linh hoạt, từ cấp độ cơ bản đến nâng cao. Giao diện đẹp mắt và dễ sử dụng, cùng với thống kê và phản hồi sau mỗi bài tập, là những điểm nổi bật của SpeedCoder.net.

SpeedCoder.net

Tóm lại, bài viết này đã giới thiệu đến bạn các cách gõ code nhanh hiệu quả. Việc gõ code nhanh không chỉ là kỹ năng, mà còn là một công cụ mạnh mẽ để tối ưu hóa quá trình lập trình. Bằng cách áp dụng các phương pháp, công cụ hỗ trợ và thói quen luyện tập, bạn có thể trở thành một lập trình viên có khả năng gõ code nhanh, chính xác và hiệu quả.

Xem thêm:

Xem thêm Việc làm IT Jobs for Developer hấp dẫn trên TopDev

Cách xử lý conflict khi git merge – Vấn nạn đau đầu của mọi Dev

Cách xử lý conflict khi git merge

Bài viết được sự cho phép bởi tác giả Sơn Dương

Git là một trong những giải pháp quản lý mã nguồn dự án hiệu quả nhất ở thời điểm hiện tại.

Đặc biệt là các dự án lớn, có nhiều thành viên tham gia, Git luôn thể hiện rõ sức mạnh. Tuy nhiên, mình tin là bạn đã từng rất bực mình, chỉ biết ngẩng mặt lên trời mà hét “Trời ơi”.

Bản thân mỗi khi bắt đầu một dự án mới, mình luôn phổ biến với các thành viên về quy tắc submit/pull code trên git, để hạn chế tối đa việc bị conflict mỗi khi merge các branch.

Tất nhiên, người tính không bằng trời tính, đôi lúc vẫn xảy ra trường hợp bị conflict code. Bạn sẽ giải quyết lỗi git conflict này như thế nào? Dưới đây là một cách mà mình muốn chia sẻ với bạn.

Git conflict là gì? Khi nào thì xảy ra conflict?

Hiểu đơn giản thì Git là hệ thống quản lý các phiên bản của một file mã nguồn. Thông thường, các developer trong dự án sẽ làm việc trên các nhánh dành riêng. Khi task hoàn thành, developer sẽ tạo merge request để merge code từ nhánh của họ vào nhánh master (nhánh chính của dự án).

Với nhóm dự án của mình, các developer luôn được yêu cầu phải pull code từ nhánh master về nhánh của mình vào đầu mỗi ngày làm việc. Nhờ đó mà hạn chế tối đa bị lỗi git conflict khi merge ngược trở lại nhánh master.

Tuy nhiên, khi nhiều developer mà cùng chỉnh sửa ở cùng một dùng code thì khả năng bị conflict khi merge là vô cùng cao.

Git conflict là gì?

Hình minh họa trên là ví dụ điển hình gây ra git conflict. Từ một nhánh main, một bạn developer (nick name: abid) tách ra nhánh mới, chỉnh sửa một file có dòng code “Hello, World” thành “Hello, Cat”. Trong khi bạn abid đang thực hiện thay đổi, thì nhánh main cũng bị được dòng code thành “Hello, Dog”.

Bùm! Khi bạn abid mà tạo request merge từ nhánh abid vào nhánh main, lập tức sẽ bị lỗi conflict và không thể merge được. Điều không thể bàn cãi!

Câu lệnh git merge có chức năng chính là hợp nhất hai nhánh và tự động xử lý conflict. Tuy nhiên, có những conflict mà không thể tự xử lý được, nó sẽ đánh dấu và dừng quá trình merge.

Những conflict này bắt buộc bạn phải xử lý thủ công.

  Sự khác biệt giữa ‘git merge’ và ‘git rebase’ là gì?

  Git: merge – rebase và những lưu ý

Cách giải quyết git conflict bằng VS Code

Khi bạn thực hiện câu lệnh git merge và bị conflict. Bước đầu tiên, bạn cần tìm đến file bị báo conflict. Trong bài viết này, mình sử dụng VS Code để minh họa, còn các IDE khác cũng tương tự thôi.

Với VS Code, nó sẽ highlight đoạn code bị conflict.

Cách giải quyết git conflict bằng VS Code

Ở đây có 3 lựa chọn mà bạn có thể chọn nhanh:

  • Accept Current Change: Tức là đoạn code conflict đó sẽ được thay thế bằng đoạn code của bạn, code mà bạn đang chỉnh sửa.
  • Accept Incoming Change: Chấp nhận thay thế bằng đoạn code lấy từ nhánh code khác về mà do developer khác sửa.
  • Accept Both Change: Lựa chọn này sẽ chấp nhận đoạn code của cả hai, cả của bạn và của developer khác. Thường là nó sẽ remix hai đoạn code lại với nhau, tỷ lệ code chạy được sau đó là rất thấp
  • Giải pháp thủ công: Xóa hết đoạn code trong block conflict và tự viết lại code trong đó.
Cảnh báo: Việc quyết định lựa chọn đoạn code thay đổi nào phụ thuộc vào mục tiêu cuối cùng của dự án. Bạn nên thảo luận với bạn developer mà có đoạn code gây ra conflict đó.

Sau khi đã quyết định lựa chọn xong, bạn nhớ xóa bỏ các ký tự === , <<<<, và >>>> để tránh bị lỗi compile.

Cuối cùng là thực hiện commit lại code sau khi đã resolve conflict theo các bước sau:

  • Chạy lệnh git status để kiểm tra lại lần nữa những thay đổi
  • Chạy lệnh git add [file name] để thêm những file thay đổi vào stage
  • Thực hiện commit các thay đổi lên local repo bằng lệnh : git commit -m “nội dung message”
  • Cuối cùng là push code bằng lệnh git push

Vậy là xong rồi đấy.

Tham khảo Job FrontEnd HOT trên TopDev!

Xử lý conflict trên Github

Đối với các dự án mã nguồn mở được quản lý trên Github, bạn sẽ phải thường xuyên kiểm tra các pull request của các bạn Contributors. Tất nhiên, cũng không thể tránh việc bị conflict.

Khi bạn mở một pull request, bạn sẽ biết được request này có bị conflict hay không? Nếu bị conflict thì bị ở những file nào?

Xử lý conflict trên Github

Cách xử lý conflict trên github cũng hoàn toàn tương tự như trên VS Code thôi.

Đầu tiên, bạn cần tìm tới file được báo là bị conflict và tìm tới dòng được đánh dấu bằng các ký tự <<<<< ====, >>>>

Tương tự, bạn cũng cần phải đưa ra quyết định lựa chọn code của bạn, hay code từ base branch hoặc giữ cả hai.

Xử lý conflict trên Github

Sau chọn xong thì bạn cũng cần phải xóa các ký tự đánh dấu <<<<< ====, >>>>

Cuối cùng là commit lại những thay đổi

Xử lý conflict trên Github

Trên đây là một số kinh nghiệm và phương pháp để resolve các git conflict.

Câu “Resolve conflict là một nghệ thuật thì người resolve là một nghệ sĩ “ quả thực không hề sai tý nào. Trong quá trình giải quyết conflict thì công đoạn đưa ra quyết định lựa chọn code nào là quan trọng nhất.

Bạn có kinh nghiệm gì hay đừng ngại chia sẻ dưới bình luận nhé.

Bài viết gốc được đăng tải tại vntalking.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev

Hiểu cơ chế layer caching khi build docker image để viết Dockerfile tốt hơn

Hiểu cơ chế layer caching khi build docker image để viết Dockerfile tốt hơn

Bài viết được sự cho phép của tác giả Tống Xuân Hoài

Vấn đề

Docker gần đây đang nổi đình đám trong cộng đồng IT nên ngày càng phổ biến, được nhiều người dùng hơn. Bằng chứng là tần suất từ Docker xuất hiện trong JD của nhà tuyển dụng ngày càng nhiều. Công ty của tôi sử dụng Docker, dự án của tôi cũng dùng Docker, dự án làm cho người khác cũng dùng nó… Docker xuất hiện như một giải pháp “đóng gói” quá thuận lợi cho cuộc cách mạng tự động hóa.

Nhưng có một điều đã tồn tại song song với nó từ xưa đến này là vấn đề build docker image khá tốn thời gian. Dung lượng của một “hình ảnh” docker nhiều khi lên đến cả hàng GB. Docker bổng nhiên trở thành một “sát thủ ổ cứng”. Nhiều câu nói đùa rằng, ông bạn có đủ ổ cứng không mà dám CI/CD với Docker? Nhưng trong bài viết này, tôi không nói về vấn đề nó ngốn dung lượng như thế nào, mà tập trung vào cách làm sao để giảm được tốc độ build docker image.

Có một vài cách để tăng tốc độ build cũng như làm giảm kích thước của docker image như chỉ cài đặt các gói cần thiết, sử dụng các hình ảnh cơ bản nhẹ (alpine), sử dụng ít layer nhất có thể… Chúng đều xoay quanh vấn đề là giữ cho docker tải xuống các tệp cần thiết ít nhất và nhẹ nhất.

Ngoài ra, còn một cách để tăng tốc là tận dụng layer caching của Docker. Vậy nó là gì thì xin mời bạn đọc tiếp bài viết dưới đây.

  20 trường hợp sử dụng lệnh Docker cho developer

  Sử dụng miễn phí Docker Registry của Gitlab

Sử dụng thứ tự lớp hình ảnh để có lợi cho bạn

Docker image được tạo thành từ các lớp (layer) xếp chồng lên nhau. Mỗi layer đại diện cho một hướng dẫn trong Dockerfile của image. Ví dụ một file Dockerfile như sau:

FROM ubuntu:18.04
LABEL org.opencontainers.image.authors="org@example.com"
COPY . /app
RUN make /app
RUN rm -r $HOME/.cache
CMD python /app/app.py

Mỗi dòng đại diện cho một layer, chúng có kích thước khác nhau và phụ thuộc vào lượng công việc mà chúng làm. Tổng dung lượng của các layer tạo thành dung lượng của image. Chính vì thế, layer càng nhiều và càng nặng thì image càng to. Để hiểu rõ hơn, hãy sử dụng lệnh docker history <image> để biết chi tiết về các lớp tạo thành image.

Ví dụ dưới đây là các lớp và dung lượng của một redislabs/redisearch image:

$ docker history redislabs/redisearch

Kết quả giống như sau:

cơ chế layer caching khi build docker image

Mỗi lần sử dụng lệnh docker build image, docker sẽ phải chạy qua lần lượt từng layer. Nhưng nếu tận dụng layer caching, docker chỉ thực sự tạo lại các lớp bắt đầu từ lớp có sự thay đổi trở về sau. Điều này đồng nghĩa với việc các layer không bị thay đổi đổ về trước có thời gian thực hiện gần như ngay lập tức. Nghĩa là bạn chỉ tốn thời gian cho lần chạy đầu tiên, ở các lần chạy sau đó docker sẽ tận dụng cache để build image.

Ví dụ dưới đây là một Dockerfile của ứng dụng viết bằng Node.js.

FROM node:18-alpine

WORKDIR /app

COPY . .

RUN npm install

Các gói phụ thuộc (dependencies) là rất ít khi bị thay đổi (thêm/sửa/xóa), cho nên khả năng sử dụng lệnh npm install là rất hiếm. Nhưng trong ví dụ trên, rõ ràng dòng lệnh COPY đã làm xáo trộn, gây ra sự thay đổi của layer nên theo lẽ thường, tất cả layer phía sau nó phải được thực hiện mà không có bộ đệm. Bạn sẽ tốn thời gian lẫn băng thông mạng để chạy lệnh npm install sau đó. Đây quả thực là cơn “ác mộng” trong mùa đứt cáp này.

Để tận dụng được cơ chế layer caching, hãy sửa và sắp xếp lại thứ tự layer một cách hợp lý hơn như sau.

FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .

Có thể thấy nếu package hoặc package-lock.json thay đổi, npm ci sẽ được thực hiện. Còn nếu không thì 2 lệnh trên có thời gian thực hiện gần như là ngay lập tức.

Tổng kết

Có một vài cách để tăng tốc độ build docker image cũng như làm giảm kích thước của docker image. Trong số đó là tận dụng cơ chế layer caching mà docker cung cấp để sắp xếp thứ tự các layer sao cho đạt được ít nhất sự thay đổi, từ đó tăng tốc độ xây dựng các hình ảnh của bạn.

Bài viết gốc được đăng tải tại 2coffee.dev

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev

Làm thế nào để biến ChatGPT thành một “chuyên gia”?

Làm thế nào để biến ChatGPT thành một

Bài viết được sự cho phép của tác giả Tống Xuân Hoài

Vấn đề

Cho đến thời điểm hiện tại, ChatGPT không còn là một cái gì đó quá mới. Nhớ lại lần đầu tiên sử dụng ChatGPT, tôi đã hơi bị “sock” khi nó có thể trả lời câu hỏi như một con người bằng cách diễn đạt hết sức tự nhiên, một điều mà trước đó chưa từng thấy ở bất kỳ chatbot nào. Cộng thêm sức mạnh của truyền thông, ChatGPT lúc đó xuất hiện như một “vị thần” để sẵn sàng để “tiễn” các công cụ, hay thậm chí là ngành nghề khác đi vào dĩ vãng.

Vậy điều đó có còn đúng trong tình cảnh hiện tại? Nhớ lại bài học về cuộc cách mạng công nghiệp cuối thế kỷ XVIII, khi mà giai cấp công nhân đứng lên đấu tranh chống lại áp bức, họ đập phá hết máy móc vì cho rằng sự xuất hiện của chúng vừa bóc lột sức lao động, vừa cướp mất công việc của mình. Nhưng sự thật là máy móc không hề bị xóa bỏ, thậm chí nó còn ngày một hiện đại. Hơn ai hết, con người dần hiểu ra nếu biết cách sử dụng hoặc chế tạo ra máy móc, nó còn tạo ra nhiều công ăn việc làm hơn cho mọi người, đồng thời giúp cho năng suất lao động ngày càng tăng.

ChatGPT cũng vậy, nếu biết cách sử dụng chúng sẽ biến thành lợi thế cho chúng ta. Thay vì lướt Google hàng giờ để tìm một câu trả lời cho vấn đề thì chỉ cần hỏi ChatGPT, nó sẵn sàng cho bạn câu trả lời nhanh nhất. Thật tuyệt! Ấy thế mà thật ngạc nhiên khi một số bạn bè của tôi vẫn không sử dụng nó, không biết vì lý do gì nữa!

Tôi đã sử dụng ChatGPT từ những ngày đầu tiên, hỏi nó rất nhiều câu hỏi cũng như tiếp thu thêm được rất nhiều kiến thức. Tuy vậy, ChatGPT vẫn có những yếu điểm nhất định mà tôi sẽ kể tiếp dưới đây. Song song với đó, cách đây gần hai tuần thôi, tôi vừa khám phá ra một cách biến ChatGPT trở nên “cứng cáp” hơn trong một vài lĩnh vực, từ đó nó sẽ đưa ra câu trả lời như một chuyên gia.

Nhưng trước tiên, hãy xem cách tôi sử dụng ChatGPT hàng ngày như thế nào nhé.

Cách tôi sử dụng ChatGPT hàng ngày

ChatGPT cho chúng ta sử dụng miễn phí ở địa chỉ chat.openai.com. Với model GPT-3.5 không quá yếu cũng không quá mạnh, bởi vì đến thời điểm hiện tại họ đã giới thiệu đến GPT-4 Turbo với rất nhiều cải tiến và hỗ trợ “context” rất lớn (128K). Hiểu đơn giản, model đại diện cho phiên bản của GPT, 3.5 thì khác với 4, và thường thì phiên bản càng cao, càng có nhiều nâng cấp và cải tiến giúp cho nó mạnh mẽ hơn.

Tôi hay sử dụng ChatGPT mỗi khi có thắc mắc lớn mà không tìm được câu trả lời, bất kể lĩnh vực gì cả công việc lẫn cuộc sống. Ví dụ tôi thường nhờ nó nhắc lại các khái niệm, giải thích tại sao phải làm thế này thế nọ, có những cách nào để làm một công việc A, B, C… gi gỉ gì gi, cái gì không biết cũng có thể hỏi.

Tôi cũng thường xuyên sử dụng nó để sửa lỗi, hoặc nhờ nó chuyển đổi đoạn mã viết bằng ngôn ngữ này sang ngôn ngữ khác. Ví dụ đoạn mã viết ra bằng một cách nào đó không chạy được, tôi sẽ bê nguyên vào và hỏi tại sao đoạn mã này lại không chạy, nhiều khi nó tìm ra được nguyên nhân và chỉ cho tôi cách khắc phục. Hoặc đôi khi tôi cũng hỏi nó cách hoạt động của một đoạn mã, có gì cần cải tiến hoặc đề xuất gì hay không… Nói chung đụng đến vấn đề code, nó có vẻ hoạt bát hơn, nhưng nhiều khi nó cũng “troll” mình bằng cách trả về trong code những “function” không hề tồn tại.

Đôi khi tôi coi ChatGPT như là một người bạn để cùng nhau trao đổi một vấn đề gì đó. Tôi sẽ là người đặt nghi vấn và trò chuyện với nó như người bạn. Nhưng người bạn này rất hay “quên” và có phần hơi “ba phải”, bằng chứng là đã nhiều lần nó thay đổi quyết định như trở bàn tay, khiến tôi phải nhắc lại vừa rồi bạn đã trả lời như thế này thế nọ mà bây giờ đã trả lời khác đi… Những lúc đó nó chỉ biết xin lỗi và một lúc nữa thôi, mọi chuyện lại diễn ra y xì như cũ.

ChatGPT ở đằng sau là một mô hình ngôn ngữ lớn (LLM) cho nên năng lực về ngôn từ rất tốt, nó có thể hiểu và trò chuyện với con người một cách tự nhiên nhất có thể. Do đó, tất cả kỹ năng viết, dịch thuật có thể xem là thế mạnh của GPT. Trước đó, tôi có một bài viết Tích hợp ChatGPT vào dịch bài viết trong AdminCP để nhờ nó dịch bài viết tiếng Việt sang tiếng Anh cho mình. Tóm lại, tôi tích hợp API của ChatGPT và hệ thống và chỉ cần một nút bấm, bài viết bằng tiếng Việt được dịch sang tiếng Anh trong chớp mắt.

Và còn nhiều cách sử dụng vụn vặt khác nữa mà tôi không thể kể ra hết ở đây. Nếu bạn cũng đang dùng ChatGPT hàng ngày và có điều gì muốn chia sẻ thì hãy để lại bình luận xuống phía dưới bài viết nhé.

  Facebook giới thiệu LLaMA tạo siêu AI cạnh tranh với ChatGPT

  Tất cả những điều cần biết về ChatGPT-4

Hạn chế khi sử dụng ChatGPT

Đây là lúc mà không thể tha thứ cho ChatGPT, đành phải “bóc phốt” tại đây.

Điều mà tôi luôn dè chừng nhất khi dùng ChatGPT là tính xác thực của câu trả lời. Hầu như các câu trả lời từ nó đều không có nguồn trích dẫn cho nên chúng ta không thể biết được liệu điều đó là đúng hay sai, được nhiều người công nhận hay là không. Theo như OpenAI công bố, dữ liệu để đào tạo cho ChatGPT được tổng hợp từ rất nhiều nguồn, bao gồm cả tài liệu từ Internet cho nên nó sẽ trả lời dựa trên những gì nó được học. Vậy điều gì xảy ra khi cùng một vấn đề nhưng dữ liệu đào tạo lại cho ra nhiều luồng ý kiến khác nhau?

Điều đó dẫn đến trường hợp cùng một câu hỏi, ChatGPT có thể đưa ra các câu trả lời khác nhau. Cũng giống như con người, khi chúng ta tiếp nhận nhiều luồng thông tin, chúng ta càng phải đánh giá tính hợp lý và sẽ có lúc chúng ta trả lời khác nhau trong một số tình huống, tôi nghĩ ChatGPT cũng phải chịu hoàn cảnh như vậy. Do đó, nếu chưa được thuyết phục bởi câu trả lời, bạn đọc nên tham khảo thêm thông tin từ các nguồn khác, đồng thời cũng đừng quá tin vào câu trả lời của ChatGPT.

Ngoài ra ChatGPT thường trả lời câu hỏi một cách chung chung và ngắn gọn, nếu không xác định được câu hỏi, bạn sẽ không thể biết cách khai thác thêm thông tin. Khi nói chuyện với một chuyên gia, họ luôn biết cách trả lời sao cho dễ hiểu, đồng thời họ cũng có tính tương tác qua lại bằng cách hỏi lại chúng ta một số câu gợi ý, từ đó khiến cho cuộc giao tiếp hiệu quả hơn. Nhưng với ChatGPT, thường thì nó sẽ dừng lại sau khi trả lời xong thắc mắc của chúng ta.

Cũng cần phải kể đến những lần ChatGPT trả lời sai và “đoảng trí”. Trong nhiều cuộc hội thoại, tôi đã tin những lời nó nói một cách sái cổ cho đến khi nó vô tình thốt ra một điều ngược lại hoàn toàn với khẳng định ban đầu. Điều đó làm tôi hoang mang và không biết liệu có nên tiếp tục hỏi. Người ta thường nói một lần mất tin vạn lần mất tín mà. Những lúc đó, tôi nghĩ mình cần tìm kiếm thông tin trên một nguồn khác tin cậy hơn.

Do đó, ChatGPT cũng chỉ là một nguồn tham khảo và không nên tin tuyệt đối vào nó.

Việc làm AI lương thưởng hấp dẫn, mới nhất dành cho bạn!

Biến ChatGPT thành một “chuyên gia”

Khi nhắc đến chuyên gia trong một lĩnh vực nào đó, chúng ta thường liên tưởng ngay đến một người dày dạn kinh nghiệm. Với vốn kiến thức đó, họ có thể trả lời rất nhiều thắc mắc của chúng ta, và dĩ nhiên là chỉ trong lĩnh vực giỏi nhất thì họ mới phát huy được hết năng lực.

Mặc dù có nhiều điểm còn hạn chế nhưng không thể phủ nhận sự hữu ích của ChatGPT. Thay vì nhìn vào mặt chưa tốt, chúng ta có thể tìm cách làm cho ChatGPT trở nên đáng tin cậy hơn.

Nếu thường xuyên cập nhật tin tức về ChatGPT, bạn sẽ biết gần đây họ tung ra tính năng cho phép người dùng tự tạo một con bot GPT cho riêng mình. Thật ra tính năng này đã có từ khá lâu, nhưng đến tận cuối tháng 12 thì mới cập bến đến thị trường của chúng ta. Sau khi tạo bot thành công, bạn có thể chia sẻ nó đến người dùng bằng cách đưa lên “chợ”. Khi người dùng thấy bot của bạn, họ bấm vào, một cuộc hội thoại mới mở ra giống như cuộc hội thoại thông thường, chỉ có điều người trò chuyện lúc này là “BOT GPT” chứ không hẳn là GPT bình thường nữa.

Tạm gác lại, khi nghiên cứu API của ChatGPT, ở phần Text generation models | OpenAI, chúng ta sẽ thấy sự xuất hiện của 3 role chính là systemuser và assistant. Kết hợp 3 role này lại với nhau, chúng sẽ tạo ra một ngữ cảnh để đưa bạn và ChatGPT vào trong chính câu chuyện đó. Ví dụ đây là một ngữ cảnh mà bạn tạo ra:

[
      {
        "role": "system",  
        "content": "You are a helpful assistant."
      },  
      {
        "role": "user",  
        "content": "Who won the world series in 2020?"
      },  
      {
        "role": "assistant",  
        "content": "The Los Angeles Dodgers won the World Series in 2020."
      },  
      {
        "role": "user",  
        "content": "Where was it played?"
      }
]

Một cách hiểu đơn giản, đây giống như là một kịch bản dựng lên cho ChatGPT. Đầu tiên system bảo với ChatGPT rằng “Bạn là một trợ lý hữu ích”, sau đó user (role này có thể hiểu là chính bạn) hỏi một câu hỏi, assistant đưa ra câu trả lời. Sau đó user lại tiếp tục đặt ra một câu hỏi khác, nếu thực thi nội dung này qua API, bạn sẽ thấy ChatGPT tiếp tục trả lời câu hỏi cuối cùng của user. Hay nói cách khác, đây là một ngữ cảnh mà chúng ta tạo ra cho ChatGPT, từ đó nó hiểu được đang nói chuyện với ai, nói về chủ đề gì… mà đưa ra các câu trả lời chính xác sau đó.

system có thể được hiểu như là “lời mô tả hệ thống” hay là “mô tả về hình mẫu ChatGPT” của bạn. Vì ChatGPT rất thông minh, học quá sâu, biết quá rộng nên nhiều khi đó lại là một yếu điểm. Bởi vì cùng một câu hỏi, nhưng chuyên gia ở lĩnh vực này có thể trả lời khác với chuyên gia ở lĩnh vực khác. Ví dụ khi hỏi “Loại gạo nào giàu chất dinh dưỡng nhất?”, giả sử lần hỏi đầu tiên, ChatGPT coi mình là “một người bình thường” thì nó trả lời đơn giản là loại gạo A. Nhưng trong lần sau, ChatGPT nhập vai là một chuyên gia nông nghiệp, nó có thể trả lời rằng gạo B mới đúng, kèm theo các lời giải thích chi tiết, khi là một chuyên gia nó sẽ có khả năng phân tích và giải thích cho người khác hiểu tại sao B mới đúng.

Đấy cũng chính là cách để bạn tạo ra một con BOT cho riêng mình, bằng cách thu hẹp ngữ cảnh xuống, thuyết phục nó trở thành một chuyên gia trong lĩnh vực bất kỳ, rồi đưa ra những mong đợi của người dùng đối với câu trả lời của chuyên gia. Ngay lập tức nó sẽ hiểu ý của bạn và cố gắng trở thành một “con người” như đã mong đợi.

Một ví dụ, đây là một ngữ cảnh mà tôi tự viết ra để mong đợi ChatGPT trở thành một chuyên gia trong chủ đề viết lách, từ đó yêu cầu nó đưa ra lời khuyên hay chỉnh sửa bài viết cho mình.

Bạn là một nhà văn, người viết sách chuyên nghiệp và thành thạo nhiều thứ tiếng, trong đó mạnh nhất là Tiếng Anh và Tiếng Việt.  
Bạn luôn tuân thủ ngữ pháp tiếng Anh và tiếng Việt.  
Bạn cũng là người có kinh nghiệm trong việc dịch thuật.  
Bạn đọc rất nhiều sách và báo tiếng Anh và tiếng Việt, bạn có thể nhận ra những điều bất hợp lý về câu từ sử dụng như là sai chính tả, sai dấu câu và cả thiếu cách diễn đạt tự nhiên.  
Bây giờ bạn cần trong vai là một chuyên gia về lĩnh vực viết, bạn cần chỉ ra tất cả lỗi sai về cách dùng từ trong bài viết, đề suất cải thiện nếu có. Hãy trình bày lại theo cấu trúc dạng danh sách: Đoạn văn gốc là... Tôi có đề xuất sửa đổi là...  

Ngoài ra tôi sẽ cung cấp thêm cho bạn thông tin của người viết để bạn có cái nhìn khách quan hơn:  
- Là lập trình viên.  
- Sở thích đọc sách.  
- Thích viết lách.  
- Ngôn ngữ tự nhiên, gần gũi, không khó hiểu, dễ tiếp cận.  
- Viết dựa trên kinh nghiệm thực tế.  
- Thích trình bày quan điểm và lồng ghép chúng vào trong đoạn văn.  

Đấy chỉ là về lĩnh vực viết, vậy còn các lĩnh vực khác thì sao? Sở dĩ tôi viết ra được “lời mô tả hệ thống” trên bởi vì tôi có kinh nghiệm về viết lách, biết cần cải thiện điều gì. Còn trong lĩnh vực khác, tôi hoàn toàn bị mịt mù và chắc chắn không thể tạo ra một hình mẫu về chuyên gia mà mình mong đợi. Vậy thì làm cách nào để tạo ra “chuyên gia” hữu ích cho mình?

Cuộc chơi thay đổi với GPT Store

chat.openai.com/gpts là kho GPT Store chính thức của chatGPT. Tại đây bạn sẽ thấy danh sách các bot được cộng đồng tạo ra. Sự khác biệt lớn nhất giữa chúng chỉ đơn thuần là “lời mô tả hệ thống”. Ai có khả năng viết chi tiết, viết sâu hơn, hay đơn giản là có năng lực chuyên môn trong lĩnh vực của mình thì khả năng cao họ sẽ tạo ra được một con bot có ngữ cảnh phù hợp nhất với chức năng của nó.

Nhưng để dùng được GPT Store, cũng như dùng bot của người dùng khác tạo ra thì chúng ta cần phải có GPT Plus trở lên với giá 20$ một tháng, một con số không hề nhỏ. Nhưng đổi lại, bạn được tiếp cận với rất nhiều “chuyên gia” của người khác.

Còn giải pháp nào cho người “nghèo” như tôi không?

Leaked Prompts of GPTs có vẻ lại là một trang ngược lại của GPT Store. Tôi không hiểu bằng cách nào đó mà nguồn này lại có được những “lời mô tả hệ thống” của một số con bot trên GPT Store. Một danh sách bot được liệt kê ở đây và nếu muốn dùng bot nào chỉ cần bấm vào nó, “lời mô tả hệ thống” lộ ra mồn một. Vậy có nghĩa là chỉ cần “copy” rồi “paste” chúng vào GPT của bạn, thì đã có ngay một “chuyên gia”!?

Ví dụ, tôi tìm thấy một con BOT Creative Writing Coach kèm lời mô tả là nâng cao kỹ năng viết. System Prompt là:

As a Creative Writing Coach GPT, my primary function is to assist users in improving their writing skills. With a wealth of experience in reading creative writing and fiction and providing practical, motivating feedback, I am equipped to offer guidance, suggestions, and constructive criticism to help users refine their prose, poetry, or any other form of creative writing. My goal is to inspire creativity, assist in overcoming writer's block, and provide insights into various writing techniques and styles. When you present your writing to me, I'll start by giving it a simple rating and highlighting its strengths before offering any suggestions for improvement.  

Bằng cách thông thường, tôi thử “paste” dòng này vào thẳng cuộc hội thoại mới trên web ChatGPT để xem điều này có biến ChatGPT thành chuyên gia được không. Qua nhiều lần thử thì tôi đánh giá câu trả lời vẫn không có gì nổi bật, nó vẫn trả lời chung chung và ngắn gọn, chỉ sau vài câu chat, nó ngay lập tức đã “quên” lời nhắn ban đầu và đôi khi lại trả lời như một kẻ ngốc. Vậy là giấc mơ dùng “chùa” đã tan biến.

Quay trở lại với API, đây là nơi mà chúng ta có thể thiết lập role system cho cuộc hội thoại. Bằng cách đưa “lời mô tả hệ thống” vào đây, rồi thử trò chuyện thì thật ngạc nhiên, nó đã trả lời khác, hay nói đúng hơn là trả lời như một chuyên gia thật. Câu trả lời ngắn gọn nhưng đi thẳng vào trọng tâm, đặc biệt khi tiếp tục hỏi thì vẫn khai thác được thêm thông tin chứ không bị “quên” hay lạc đề giống như GPT trên nền web.

Các cuộc gọi API là mất phí, GPT-4 thì đắt hơn rất nhiều so với 3.5. Thời gian phản hồi của 3.5 cũng chậm hơn nhiều so với 4, vì vậy nếu tiền không là vấn đề, 4 vẫn mang lại trải nghiệm tốt hơn.

Dùng công cụ để quản lý các cuộc hội thoại tạo bằng API

Web ChatGPT có một điểm cộng là nó lưu trữ lại nội dung các cuộc hội thoại quá khứ. Nhưng đối với API thì không, chúng ta cần phải lưu trữ lại mọi thứ một cách thủ công, bao gồm “lời mô tả hệ thống”, yêu cầu của user và cả câu trả lời của assistant.

Vì vậy, có thể bạn sẽ thắc mắc tôi sử dụng API như thế nào, thì câu trả lời là dùng các công cụ Open Source.

NextChat (ChatGPT Next Web) là công cụ cung cấp giao diện thân thiện cho GPT. Bạn chỉ cần chạy một lệnh để khởi động ứng dụng trên nền web, hoặc đơn giản là tải ứng dụng về, nhập GPT Key vào thế là xong. Công cụ sẽ giúp chúng ta lưu trữ lại nội dung của các cuộc hội thoại, cộng với giao diện thân thiện sử dụng được ngay lập tức.

 Biến ChatGPT thành một "chuyên gia"

Công cụ này cũng hỗ trợ bạn tạo ra GPT bot bằng cách nhập vào “lời mô tả hệ thống”. Hãy chọn một chuyên gia mà bạn thích ở trong danh sách Leaked Prompts of GPTs, sao chép lại dòng System Prompt và nhập vào system.

Ngay bây giờ bạn đã có thể nói chuyện với chuyên gia của bạn bằng cách bấm vào Mask > Find More > rồi bấm vào nút Chat bên cạnh tên của chuyên gia vừa tạo.

Hãy thử hỏi chuyên gia một câu:

 Biến ChatGPT thành một "chuyên gia"

Cá nhân tôi đã thử sử dụng và thấy rằng bằng cách này, GPT cho lời khuyên hữu ích hơn hẳn so với khi không có ngữ cảnh. Còn bạn, bạn đã sử dụng GPT Store hoặc một công cụ bên thứ ba nào chưa? Hãy chia sẻ kinh nghiệm của mình xuống phía dưới bài viết nhé. Xin cảm ơn rất nhiều!

Bài viết gốc được đăng tải tại 2coffee.dev

Xem thêm:

Tìm kiếm việc làm IT mới nhất tại TopDev!