Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
Một dự án có nhiều mô-đun Gradle được gọi là một dự án đa mô-đun. Hướng dẫn này trình bày các phương pháp hay nhất cũng như các mẫu đề xuất để phát triển ứng dụng Android nhiều mô-đun.
Vấn đề về sự tăng vọt của cơ sở mã
Trong khi cơ sở mã không ngừng phát triển, khả năng mở rộng quy mô, khả năng đọc và chất lượng mã tổng thể thường giảm dần theo thời gian. Điều này là kết quả của việc kích thước cơ sở mã tăng lên mà không có các trình bảo trì thực hiện các biện pháp chủ động để tạo ra một cấu trúc dễ bảo trì. Mô-đun hoá là một phương pháp để cơ cấu cơ sở mã theo cách cải thiện khả năng bảo trì và giúp tránh các vấn đề nói trên.
Mô-đun hoá là gì?
Mô-đun hoá là phương pháp sắp xếp cơ sở mã thành các phần được khớp nối lỏng lẻo và có khả năng tự chứa. Mỗi phần là một mô-đun. Mỗi mô-đun thường độc lập và phục vụ một mục đích rõ ràng. Bằng cách chia nhỏ vấn đề để dễ giải quyết hơn, bạn sẽ giảm bớt được độ phức tạp của việc thiết kế và duy trì một hệ thống lớn.
Hình 1: Biểu đồ phần phụ thuộc của cơ sở mã mẫu đa mô-đun
Lợi ích của việc mô-đun hoá
Việc mô-đun hoá có rất nhiều lợi ích, mặc dù mỗi mô-đun đều tập trung vào việc cải thiện khả năng bảo trì và chất lượng tổng thể của cơ sở mã. Bảng sau đây tóm tắt các lợi ích chính.
Lợi ích
Tóm tắt
Khả năng tái sử dụng
Mô-đun hoá tạo ra cơ hội để chia sẻ mã và xây dựng nhiều ứng dụng từ cùng một nền tảng. Các mô-đun là những khối xây dựng hiệu quả. Ứng dụng phải là tập hợp của nhiều tính năng, trong đó các tính năng được sắp xếp dưới dạng mô-đun riêng biệt. Chức năng mà một mô-đun nhất định cung cấp có thể được bật hoặc không được bật trong một ứng dụng cụ thể. Ví dụ: :feature:news có thể là một tính năng của phiên bản đầy đủ và phiên bản ứng dụng Wear nhưng không phải là tính năng của phiên bản minh hoạ.
Kiểm soát chế độ hiển thị nghiêm ngặt
Các mô-đun cho phép bạn dễ dàng kiểm soát nội dung mà bạn hiển thị với các phần khác của cơ sở mã. Bạn có thể đánh dấu mọi đối tượng (ngoại trừ giao diện công khai của mình) là internal hoặc private để ngăn việc sử dụng các đối tượng đó bên ngoài mô-đun.
Phân phối có thể tuỳ chỉnh
Play Feature Delivery sử dụng các tính năng nâng cao của gói ứng dụng để cho phép bạn phân phối một số tính năng cụ thể của ứng dụng theo điều kiện hoặc theo yêu cầu.
Bạn chỉ có thể đạt được các lợi ích của việc mô-đun hoá bằng cơ sở mã đã được mô-đun hoá.
Bạn có thể đạt được các lợi ích sau bằng những kỹ thuật khác, nhưng việc mô-đun hoá có thể giúp bạn thực thi những kỹ thuật này thậm chí còn tốt hơn.
Lợi ích
Tóm tắt
Khả năng mở rộng quy mô
Trong một cơ sở mã có tính khớp nối chặt chẽ, chỉ một thay đổi cũng có thể kích hoạt một loạt các thay đổi trong các phần mã có vẻ không liên quan. Một dự án được mô-đun hoá đúng cách sẽ áp dụng nguyên tắc tách biệt vấn đề và do đó hạn chế tính khớp nối. Điều này giúp các thành phần có được quyền tự chủ lớn hơn.
Quyền sở hữu
Ngoài việc cho phép quyền tự chủ, các mô-đun cũng có thể được dùng để thực thi trách nhiệm. Một mô-đun có thể có một chủ sở hữu riêng chịu trách nhiệm duy trì mã, sửa lỗi, thêm các quy trình kiểm thử và xem xét các thay đổi.
Đóng gói
Đóng gói nghĩa là mỗi phần mã của bạn phải có lượng kiến thức nhỏ nhất có thể về các phần khác. Các phần mã tách biệt sẽ dễ đọc và dễ hiểu hơn.
Khả năng thử nghiệm
Khả năng thử nghiệm mô tả mức độ dễ dàng của việc kiểm thử mã. Cơ sở mã có thể kiểm thử là cơ sở mã mà bạn có thể dễ dàng kiểm thử các thành phần một cách riêng biệt.
Thời gian tạo bản dựng
Một số chức năng của Gradle như mô hình bản dựng gia tăng, bộ nhớ đệm bản dựng hoặc bản dựng song song có thể tận dụng mô-đun để cải thiện hiệu suất bản dựng.
Các lỗi phổ biến
Mức độ chi tiết của cơ sở mã là mức độ mà cơ sở mã đó được cấu tạo bởi các mô-đun. Cơ sở mã càng có nhiều mô-đun nhỏ hơn thì càng chi tiết hơn. Khi thiết kế cơ sở mã được mô-đun hoá, bạn nên quyết định mức độ chi tiết. Để thực hiện việc này, hãy tính đến quy mô và độ phức tạp tương đối của cơ sở mã. Việc triển khai quá chi tiết sẽ khiến chi phí vận hành trở thành gánh nặng, còn việc triển khai sơ sài sẽ làm giảm lợi ích của quá trình mô-đun hoá.
Một số lỗi phổ biến như sau:
Quá chi tiết: Mỗi mô-đun sẽ mang lại một mức hao tổn nhất định dưới dạng độ phức tạp tăng dần của bản dựng và mã nguyên mẫu. Cấu hình bản dựng phức tạp khiến việc duy trì tính nhất quán của cấu hình giữa các mô-đun trở nên khó khăn. Quá nhiều mã nguyên mẫu sẽ tạo ra một cơ sở mã cồng kềnh, khó duy trì. Nếu mức hao tổn ảnh hưởng đến việc cải thiện khả năng mở rộng, bạn nên xem xét hợp nhất một số mô-đun.
Quá ít chi tiết: Ngược lại, nếu các mô-đun của bạn quá lớn, kết quả cuối cùng mà bạn xây dựng nên có thể là một nguyên khối cồng kềnh và bỏ lỡ những lợi ích mà mô-đun mang lại. Ví dụ: trong một dự án nhỏ, bạn có thể đặt lớp dữ liệu bên trong một mô-đun duy nhất. Tuy nhiên, khi dự án phát triển, bạn có thể cần phải tách riêng các kho lưu trữ và nguồn dữ liệu thành các mô-đun độc lập.
Quá phức tạp: Không phải lúc nào bạn cũng nên mô-đun hoá dự án. Yếu tố chiếm ưu thế chính là kích thước của cơ sở mã. Nếu bạn không tính trước rằng dự án của mình sẽ vượt quá một ngưỡng nhất định, thì lợi ích về khả năng mở rộng và thời gian xây dựng sẽ không đạt được.
Mô-đun hoá có phải là kỹ thuật phù hợp với tôi không?
Nếu bạn cần hưởng các lợi ích từ khả năng tái sử dụng, kiểm soát chế độ hiển thị nghiêm ngặt hoặc sử dụng Play Feature Delivery, thì bạn cũng cần phải mô-đun hoá. Nếu bạn không cần, nhưng vẫn muốn hưởng lợi từ việc cải thiện khả năng mở rộng, quyền sở hữu, đóng gói hoặc thời gian xây dựng, thì hãy xem xét và cân nhắc việc mô-đun hoá.
Mẫu
Now in Android – ứng dụng Android đầy đủ chức năng có tính năng mô-đun hoá.
Nội dung và mã mẫu trên trang này phải tuân thủ các giấy phép như mô tả trong phần Giấy phép nội dung. Java và OpenJDK là nhãn hiệu hoặc nhãn hiệu đã đăng ký của Oracle và/hoặc đơn vị liên kết của Oracle.
Cập nhật lần gần đây nhất: 2025-08-17 UTC.
[[["Dễ hiểu","easyToUnderstand","thumb-up"],["Giúp tôi giải quyết được vấn đề","solvedMyProblem","thumb-up"],["Khác","otherUp","thumb-up"]],[["Thiếu thông tin tôi cần","missingTheInformationINeed","thumb-down"],["Quá phức tạp/quá nhiều bước","tooComplicatedTooManySteps","thumb-down"],["Đã lỗi thời","outOfDate","thumb-down"],["Vấn đề về bản dịch","translationIssue","thumb-down"],["Vấn đề về mẫu/mã","samplesCodeIssue","thumb-down"],["Khác","otherDown","thumb-down"]],["Cập nhật lần gần đây nhất: 2025-08-17 UTC."],[],[],null,["# Guide to Android app modularization\n\nA project with multiple Gradle modules is known as a multi-module project. This\nguide encompasses best practices and recommended patterns for developing\nmulti-module Android apps.\n| **Note:** This page assumes a basic familiarity with the [recommended app\n| architecture](/topic/architecture).\n\nThe growing codebase problem\n----------------------------\n\nIn an ever-growing codebase, scalability, readability, and overall code quality\noften decrease through time. This comes as a result of the codebase increasing\nin size without its maintainers taking active measures to enforce a structure\nthat is easily maintainable. Modularization is a means of structuring your\ncodebase in a way that improves maintainability and helps avoid these problems.\n\nWhat is modularization?\n-----------------------\n\nModularization is a practice of organizing a codebase into loosely coupled and\nself contained parts. Each part is a module. Each module is independent and\nserves a clear purpose. By dividing a problem into smaller and easier to solve\nsubproblems, you reduce the complexity of designing and maintaining a large\nsystem.\n**Figure 1**: Dependency graph of a sample multi-module codebase\n\nBenefits of modularization\n--------------------------\n\nThe benefits of modularization are many, though they each center upon improving\nthe maintainability and overall quality of a codebase. The following table\nsummarizes the key benefits.\n\n| Benefit | Summary |\n|---------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Reusability | Modularization enables opportunities for code sharing and building multiple apps from the same foundation. Modules are effectively building blocks. Apps should be a sum of their features where the features are organized as separate modules. The functionality that a certain module provides may or may not be enabled in a particular app. For example, a `:feature:news` can be a part of the full version flavor and wear app but not part of the demo version flavor. |\n| Strict visibility control | Modules enable you to easily control what you expose to other parts of your codebase. You can mark everything but your public interface as `internal` or `private` to prevent it from being used outside the module. |\n| Customizable delivery | [Play Feature Delivery](/guide/playcore/feature-delivery) uses the advanced capabilities of app bundles, allowing you to deliver certain features of your app conditionally or on demand. |\n\nThe benefits of modularization are only achievable with a modularized codebase.\nThe following benefits might be achieved with other techniques but\nmodularization can help you enforce them even more.\n\n| Benefit | Summary |\n|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Scalability | In a tightly coupled codebase a single change can trigger a cascade of alterations in seemingly unrelated parts of code. A properly modularized project will embrace the [separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns) principle and therefore limit the coupling. This empowers the contributors through greater autonomy. |\n| Ownership | In addition to enabling autonomy, modules can also be used to enforce accountability. A module can have a dedicated owner who is responsible for maintaining the code, fixing bugs, adding tests, and reviewing changes. |\n| Encapsulation | Encapsulation means that each part of your code should have the smallest possible amount of knowledge about other parts. Isolated code is easier to read and understand. |\n| Testability | Testability characterizes how easy it is to [test](/training/testing) your code. A testable codebase is one where components can be easily tested in isolation. |\n| Build time | Some Gradle functionalities such as incremental build, build cache or parallel build, can leverage modularity to [improve build performance](/studio/build/optimize-your-build). |\n\nCommon pitfalls\n---------------\n\nThe granularity of your codebase is the extent to which it is composed of\nmodules. A more granular codebase has more, smaller modules. When designing a\nmodularized codebase, you should decide on a level of granularity. To do so,\ntake into account the size of your codebase and its relative complexity. Going\ntoo fine-grained will make the overhead a burden, and going too coarse will\nlessen the benefits of modularization.\n\nSome common pitfalls are as follows:\n\n- **Too fine-grained** : Every module brings a certain amount of overhead in the form of increased build complexity and [boilerplate code](https://en.wikipedia.org/wiki/Boilerplate_code). A complex build configuration makes it difficult to [keep configurations consistent](/topic/modularization/patterns#consistent-configuration) across modules. Too much boilerplate code results in a cumbersome codebase that is difficult to maintain. If overhead counteracts scalability improvements, you should consider consolidating some modules.\n- **Too coarse-grained**: Conversely, if your modules are growing too large you might end up with yet another monolith and miss the benefits that modularity has to offer. For example, in a small project it's ok to put the data layer inside a single module. But as it grows, it might be necessary to separate repositories and data sources into standalone modules.\n- **Too complex**: It doesn't always make sense to modularize your project. A dominating factor is the size of the codebase. If you don't expect your project to grow beyond a certain threshold, the scalability and build time gains won't apply.\n\nIs modularization the right technique for me?\n---------------------------------------------\n\nIf you need the benefits of reusability, strict visibility control or to use the\n[Play Feature Delivery](/guide/playcore/feature-delivery), then modularization is a necessity for you. If you\ndon't, but still want to benefit from improved scalability, ownership,\nencapsulation, or build times, then modularization is something worth\nconsidering.\n\nSamples\n-------\n\n- [Now in Android](https://github.com/android/nowinandroid) - fully functional Android app featuring modularization.\n- [Multi module architecture sample](https://github.com/android/architecture-samples/tree/multimodule)"]]