Get in touch
or send us a question?
CONTACT

6 điều nhỏ giúp bạn trở thành một nhà phát triển Flutter tốt hơn

Dưới đây là tập hợp 6 điều nhỏ mà nhiều nhà phát triển quên hoặc không biết trong khi phát triển ứng dụng Flutter của họ nhưng có thể cải thiện đáng kể quá trình phát triển.

Widget, widget, widget!

Bạn có thể đã nghe nói rằng Flutter là tất cả về các widget. Widget ở đây, widget ở đó, v.v. Lời khuyên đầu tiên của tôi là:

Giảm các phần tử giao diện người dùng của bạn thành nhiều widget nhỏ nhất có thể.

Hãy để tôi nói rõ hơn. Hai trường hợp phổ biến mà chúng tôi muốn ngăn chặn như sau:

  1. Một lớp widget khổng lồ với một phương pháp xây dựng khổng lồ (hay còn gọi là trường hợp tồi tệ nhất có thể tưởng tượng được)
  2. Một lớp widget khổng lồ với nhiều phương pháp xây dựng (tốt hơn tùy chọn trước đó, nhưng vẫn không lý tưởng)

Lý do tại sao những trường hợp này gây ra vấn đề trong quá trình phát triển là:

  • Các lớp dài có nghĩa là quá tải nhận thức lớn hơn trong khi điều hướng qua chúng, điều đó có nghĩa là các nhà phát triển nhanh chóng mệt mỏi hơn và khả năng mắc lỗi trong khi cố gắng sửa đổi mã là lớn hơn.
  • Nói chung, việc tạo ra nhiều widget hơn đi đôi với khái niệm tăng khả năng tái sử dụng mã của bạn. Bằng cách đó, bạn có thể dễ dàng thay đổi một khía cạnh chung của ứng dụng bằng cách chỉ cần sửa đổi một tiện ích con thay vì cần phải thay đổi hàng trăm phương thức trong mỗi lớp riêng biệt.

Nếu bạn là một lập trình viên mới bắt đầu, hãy lưu ý rằng các tiện ích con chung chung và các tiện ích con trừu tượng sẽ rất quan trọng khi cố gắng chia nhỏ các phần tử giao diện người dùng của bạn thành các lớp tiện ích con có thể sử dụng lại.

Câu lệnh if

Một vấn đề nhỏ khác liên quan đến việc tối ưu hóa nếu các câu lệnh trong mã Flutter của bạn. Bạn có biết rằng bạn có thể sử dụng chúng trong các phương pháp xây dựng của mình bằng cách đặt chúng trực tiếp vào danh sách con như thế này không?

Column(
   children: [
     _buildCancelButton(),
     _buildTitle(),
     if (dataCorrect) _buildSubmitButton(),
   ],
)

Nó được chứng minh là một mã sạch để xây dựng logic giao diện người dùng của bạn một cách có điều kiện. Bạn cũng có thể kết hợp nó cùng với spread operator để nối có điều kiện danh sách widget vào một danh sách được chỉ định. Đây là một ví dụ:

Column(
   children: [
     _buildTitle(),
     if (showButtons) ..._buildButtons(),
   ],
)

List<Widget> _buildButtons() {
   // ...
}

Throw in some errors

Một số lập trình viên sợ các cô gái và một số khác đang ném lỗi trong mã của họ. Hãy tập trung vào phần sau. Trong khi phát triển ứng dụng của mình, đôi khi bạn sẽ tìm thấy các đường dẫn mà mã có thể thực thi mà không có triển khai hiện tại. Trong trường hợp đó, bạn nên đặt một lỗi như UnimplementedError trong trường hợp một tính năng chưa được triển khai hoặc UnsupportedError nếu thao tác đã cho không hợp lệ.

Ngoài ra, bạn nên cung cấp giải thích cho lỗi đã cho trong hàm tạo. Dưới đây là một ví dụ về việc tạo ra một lỗi trong câu lệnh switch được sử dụng để ánh xạ một chuỗi với một enum:

switch (status) {
  case 'AVAILABLE':
    return PromotionStatus.available;
  case 'ACTIVE':
    return PromotionStatus.active;
  case 'EXPIRED':
    return PromotionStatus.expired;
  default:
    throw UnsupportedError('Promotion status $status is not supported!');
}

const constructors

Bạn nên sử dụng hàm tạo const nếu có thể. Tại sao? Nói một cách đơn giản, nó giúp tăng hiệu suất của Flutter bằng cách cho biết những phần tử nào sẽ không thay đổi, có nghĩa là Flutter không cần phải xây dựng lại chúng.

Dưới đây là một ví dụ dễ hiểu để minh họa quy trình. Giả sử chúng tôi muốn xây dựng một biểu tượng không thay đổi và có lợi nhuận trên cùng là 20 đồng thời là biểu tượng tĩnh. Chúng tôi sẽ xác định phương pháp để xây dựng tiện ích như thế này:

Widget _buildIcon() {
   return Container(
     margin: const EdgeInsets.only(top: 20),
     child: const Icon(Icons.home),
   );
}

Bạn không muốn theo dõi thời điểm thêm từ khóa const? Bạn thật may mắn vì bạn không cần phải làm như vậy! Chỉ cần nhìn vào mẹo tiếp theo bên dưới.

Lint rules

Một công cụ hữu ích khác là sử dụng gói lint cho dự án của bạn. Nếu bạn không quen thuộc với lint, đây chỉ là một công cụ tự động phân tích mã nguồn để gắn cờ các lỗi lập trình, lỗi hoặc lỗi văn phong phổ biến. Để đưa nó vào dự án Flagship của chúng tôi, chúng tôi bắt đầu bằng cách thêm hai gói vào tệp pubspec.yaml của chúng tôi:

  • Linter – gói xơ vải chính.
  • Lint – chứa các quy tắc lint do cộng đồng chọn.
dev_dependencies:
 flutter_test:
   sdk: flutter
 flutter_driver:
   sdk: flutter
 test:
 linter: ^0.1.116
 lint: ^1.2.0

Sau đó, chúng tôi tạo một tệp có tên là analysis_options.yaml trong thư mục gốc của chúng tôi. Ở đó, chúng tôi bao gồm gói cộng đồng của mình và tùy chỉnh bất kỳ quy tắc nào khác.

include: package:lint/analysis_options.yaml

analyzer:
 exclude:
   - "lib/presentation/localization/**"
 errors:
   missing_required_param: error

Chúng tôi có thể loại trừ một số thư mục nhất định khỏi được phân tích, chẳng hạn như thư mục tệp localization được tạo của chúng tôi. Ở đây, chúng tôi cũng có thể nói rằng chúng tôi muốn các thông số bắt buộc bị thiếu của chúng tôi được báo cáo là lỗi ngăn chúng tôi chạy mã.

@required & assert

Hãy bắt đầu với một ví dụ về hàm tạo cho lớp Sản phẩm sẽ minh họa những điều bạn nên tránh khi xác định các hàm tạo và phương thức:

const Product(
   this.id,
   this.name,
   this.description,
   this.category,
);

Trước hết, nếu bạn có nhiều tham số trong các phương thức hoặc hàm tạo của mình và một số trong số chúng có thể là tùy chọn, bạn chủ yếu nên sử dụng các tham số được đặt tên thay vì các tham số vị trí. Bằng cách đó, mã dễ đọc hơn và dễ phát hiện lỗi hơn trong khi xem xét mã.

Ngoài ra, bạn phải luôn chú thích chính xác các thông số của mình bằng cách sử dụng từ khóa @required nếu không thể bỏ qua chúng. Vì vậy, hãy làm điều này. Đây là hiệu ứng:

const Product({
   @required this.id,
   @required this.name,
   this.description,
   this.category,
});

Nếu bạn sử dụng các quy tắc lint này mà tôi đã chia sẻ với bạn, trình biên dịch sẽ thông báo lỗi nếu bạn quên chỉ định một tham số bắt buộc, điều này rất hữu ích.

Xác nhận là một yếu tố khác mà chúng tôi có thể sử dụng để cải thiện mã này. Bằng cách chỉ định rằng các thông số bắt buộc của chúng tôi không được có giá trị null, chúng tôi sẽ được thông báo nhanh hơn về một lỗi tiềm ẩn trong ứng dụng.

const Product({
   @required this.id,
   @required this.name,
   this.description,
   this.category,
}): assert(id != null),
    assert(name != null);

Kết luận

Tôi hy vọng bạn tìm thấy ít nhất một trong những điều chúng tôi đã chia sẻ là có giá trị. Một số mẹo có vẻ vụn vặt nhưng trên thực tế, bộ kỹ năng của nhà phát triển là sự kết hợp của các chi tiết nhỏ khác nhau kết hợp với nhau để tạo thành cấp độ năng lực tổng thể của mình.