Kiểu mã Java AOSP cho người đóng góp

Kiểu mã trên trang này là các quy tắc nghiêm ngặt để đóng góp mã Java vào Dự án nguồn mở Android (AOSP). Đóng góp cho nền tảng Android không tuân thủ các quy tắc này thường không được chấp nhận. T4 nhận thấy rằng không phải tất cả mã hiện tại đều tuân theo các quy tắc này, nhưng chúng tôi kỳ vọng tất cả mã mới để tuân thủ chính sách. Xem bài viết Thận trọng khi lập trình để biết các ví dụ về thuật ngữ cần sử dụng và tránh sử dụng để có một hệ sinh thái hoà nhập hơn.

Đảm bảo sự đều đặn

Một trong những quy tắc đơn giản nhất là phải nhất quán. Nếu bạn đang chỉnh sửa mã, hãy thực hiện một vài phút để xem mã xung quanh và xác định kiểu của mã. Nếu có mã sử dụng dấu cách xung quanh mệnh đề if. Bạn cũng nên làm như vậy. Nếu mã nhận xét có ít hộp dấu sao xung quanh, hãy làm cho nhận xét của bạn cả những hộp ngôi sao nhỏ xung quanh họ.

Mục đích của việc có nguyên tắc văn phong là phải có từ vựng chung lập trình để người đọc có thể tập trung vào những gì bạn nói thay vì cách bạn nói điều đó. Chúng tôi trình bày quy tắc kiểu toàn cầu ở đây để bạn biết nhưng phong cách địa phương cũng rất quan trọng. Nếu mã mà bạn thêm vào một tệp trông khác đáng kể so với mã hiện có xung quanh tệp đó, thì nội dung đó khiến người đọc mất tập trung khi họ đọc. Cố gắng hãy tránh điều này.

Các quy tắc ngôn ngữ Java

Android tuân theo các quy ước lập trình Java tiêu chuẩn cùng với những quy tắc bổ sung được mô tả bên dưới.

Không bỏ qua các ngoại lệ

Bạn có thể dễ dàng viết mã bỏ qua một ngoại lệ, chẳng hạn như:

  void setServerPort(String value) {
      try {
          serverPort = Integer.parseInt(value);
      } catch (NumberFormatException e) { }
  }

Đừng làm việc này. Mặc dù bạn có thể nghĩ rằng mã của mình sẽ không bao giờ gặp phải lỗi này tình trạng lỗi hoặc việc xử lý lỗi đó không quan trọng, hãy bỏ qua loại ngoại lệ sẽ tạo ra các vùng chứa trong mã của bạn để người khác kích hoạt vào ngày nào đó. Bạn phải xử lý mọi ngoại lệ trong mã của mình trong phương pháp theo nguyên tắc; cách xử lý cụ thể sẽ khác nhau tuỳ theo trường hợp.

"Bất cứ khi nào ai đó có mệnh đề bắt bóng trống thì họ nên có một mệnh đề đáng sợ cảm xúc. Đôi khi, đây thực sự là câu trả lời chính xác việc cần làm, nhưng ít nhất bạn phải suy nghĩ về nó. Trong Java, bạn không thể thoát khỏi cảm giác đáng sợ." – James Gosling

Các lựa chọn thay thế được chấp nhận (theo thứ tự ưu tiên) là:

  • Gửi ngoại lệ cho phương thức gọi của phương thức.
      void setServerPort(String value) throws NumberFormatException {
          serverPort = Integer.parseInt(value);
      }
    
  • Gửi một ngoại lệ mới phù hợp với cấp độ trừu tượng của bạn.
      void setServerPort(String value) throws ConfigurationException {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new ConfigurationException("Port " + value + " is not valid.");
        }
      }
    
  • Xử lý lỗi một cách linh hoạt và thay thế một giá trị thích hợp trong Khối catch {}.
      /** Set port. If value is not a valid number, 80 is substituted. */
    
      void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            serverPort = 80;  // default port for server
        }
      }
    
  • Phát hiện ngoại lệ và gửi một thực thể mới của RuntimeException. Điều này nguy hiểm, vì vậy chỉ thực hiện nếu bạn chắc chắn rằng nếu điều này lỗi xảy ra, thì biện pháp thích hợp là sự cố.
      /** Set port. If value is not a valid number, die. */
    
      void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("port " + value " is invalid, ", e);
        }
      }
    
  • Khi không còn cách nào khác, nếu bạn chắc chắn rằng việc bỏ qua ngoại lệ thích hợp thì bạn có thể bỏ qua nội dung đó, nhưng bạn cũng phải nhận xét lý do đó là một lý do chính đáng.
    /** If value is not a valid number, original port number is used. */
    
    void setServerPort(String value) {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            // Method is documented to just ignore invalid user input.
            // serverPort will just be unchanged.
        }
    }
    

Không phát hiện các trường hợp ngoại lệ chung

Tôi có thể rất muốn trở nên lười biếng khi phát hiện ra ngoại lệ và tương tự như sau:

  try {
      someComplicatedIOFunction();        // may throw IOException
      someComplicatedParsingFunction();   // may throw ParsingException
      someComplicatedSecurityFunction();  // may throw SecurityException
      // phew, made it all the way
  } catch (Exception e) {                 // I'll just catch all exceptions
      handleError();                      // with one generic handler!
  }

Đừng làm việc này. Trong hầu hết mọi trường hợp, bạn không nên bắt gặp những vấn đề chung chung Exception hoặc Throwable (tốt nhất không nên dùng Throwable vì nó bao gồm Error ngoại lệ). Nguy hiểm vì điều này có nghĩa là các ngoại lệ mà bạn chưa từng mong đợi (bao gồm cả các trường hợp ngoại lệ đối với thời gian chạy như ClassCastException) vướng vào quá trình xử lý lỗi cấp ứng dụng. Nó che giấu lỗi- xử lý các thuộc tính của mã, nghĩa là nếu ai đó thêm một loại thuộc tính mới ngoại lệ trong mã bạn đang gọi, trình biên dịch sẽ không chỉ ra bạn cần xử lý lỗi theo cách khác. Trong hầu hết các trường hợp, bạn không nên xử lý nhiều loại ngoại lệ theo cùng một cách.

Ngoại lệ hiếm hoi đối với quy tắc này là mã kiểm thử và mã cấp cao nhất trong đó bạn muốn phát hiện tất cả các loại lỗi (để ngăn chúng hiển thị trong giao diện người dùng hoặc để tiếp tục chạy một công việc hàng loạt). Trong những trường hợp này, bạn có thể Exception chung (hoặc Throwable) và xử lý lỗi một cách thích hợp. Tuy nhiên, hãy suy nghĩ kỹ trước khi đưa ra nhận xét rồi đưa ra nhận xét giải thích tại sao ứng dụng an toàn trong bối cảnh này.

Lựa chọn thay thế để phát hiện các trường hợp ngoại lệ chung:

  • Phát hiện riêng từng trường hợp ngoại lệ trong khối nhiều lần phát hiện, ví dụ:
    try {
        ...
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        ...
    }
  • Tái cấu trúc mã của bạn để xử lý lỗi chi tiết hơn bằng nhiều khối thử. Tách IO khỏi quá trình phân tích cú pháp và xử lý các lỗi riêng biệt trong mỗi trường hợp.
  • Gửi lại trường hợp ngoại lệ. Nhiều khi bạn không cần nắm bắt ngoại lệ ở cấp này, chỉ cần để phương thức gửi nó.

Hãy nhớ rằng bạn cũng cần lưu ý rằng các trường hợp ngoại lệ cũng ảnh hưởng đến bạn! Khi trình biên dịch phàn nàn rằng bạn không phát hiện trường hợp ngoại lệ, đừng cau có. Cười lên! Trình biên dịch vừa tạo giúp bạn dễ dàng phát hiện các vấn đề về thời gian chạy trong mã hơn.

Không sử dụng ký tự hoàn tất

Trình hoàn thiện là một cách để thực thi một đoạn mã khi một đối tượng được rác được thu thập. Mặc dù bạn có thể dễ dàng dọn dẹp gọn gàng (đặc biệt là các nguồn lực bên ngoài), không có gì đảm bảo về thời điểm trình hoàn tất sẽ được gọi (hoặc thậm chí nó sẽ được gọi).

Android không sử dụng thành phần hoàn thiện. Trong hầu hết các trường hợp, bạn có thể sử dụng xử lý ngoại lệ tốt. Nếu bạn thực sự cần một đoạn mã hoàn thiện, xác định một phương thức close() (hoặc tương tự) và ghi lại chính xác thời điểm phương thức cần được gọi (xem InputStream). Trong trường hợp này, thì thích hợp nhưng không bắt buộc in một thông điệp nhật ký ngắn từ hoàn tất, miễn là hệ thống không làm tràn nhật ký.

Dữ liệu nhập đủ điều kiện

Khi bạn muốn sử dụng lớp Bar trong gói foo, có hai các cách có thể sử dụng để nhập dữ liệu:

  • import foo.*;

    Có thể làm giảm số lượng câu lệnh nhập.

  • import foo.Bar;

    Làm rõ lớp nào được dùng và mã nào được sử dụng nhiều hơn dễ đọc đối với nhà bảo trì.

Sử dụng import foo.Bar; để nhập tất cả mã Android. Một ngoại lệ rõ ràng được thực hiện cho các thư viện chuẩn Java (java.util.*, java.io.*, v.v.) và mã kiểm thử đơn vị (junit.framework.*).

Quy tắc của thư viện Java

Có một số quy ước sử dụng thư viện và công cụ Java của Android. Trong một số trường hợp, quy ước đã thay đổi theo các cách quan trọng và mã cũ hơn có thể sử dụng mẫu hoặc thư viện không được dùng nữa. Khi làm việc với những mã như vậy, thì bạn có thể tiếp tục kiểu hiện tại. Khi tạo thành phần mới tuy nhiên, đừng bao giờ sử dụng các thư viện không dùng nữa.

Các quy tắc kiểu Java

Sử dụng nhận xét chuẩn trong Javadoc

Mỗi tệp phải có tuyên bố bản quyền ở trên cùng, theo sau là câu lệnh cho gói và câu lệnh nhập (mỗi khối được phân tách bằng một dòng trống) và cuối cùng là khai báo lớp hoặc giao diện. Trong các nhận xét trên Javadoc, mô tả chức năng của lớp hoặc giao diện.

/*
 * Copyright yyyy The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.foo;

import android.os.Blah;
import android.view.Yada;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Does X and Y and provides an abstraction for Z.
 */

public class Foo {
    ...
}

Mọi lớp và phương thức công khai không quan trọng mà bạn viết phải chứa nhận xét trong Javadoc có ít nhất một câu mô tả lớp hoặc phương thức nào khác. Câu này phải bắt đầu bằng một người thứ ba động từ mô tả.

Ví dụ

/** Returns the correctly rounded positive square root of a double value. */

static double sqrt(double a) {
    ...
}

hoặc

/**
 * Constructs a new String by converting the specified array of
 * bytes using the platform's default character encoding.
 */
public String(byte[] bytes) {
    ...
}

Bạn không cần phải viết Javadoc cho các phương thức nhận và thiết lập đơn giản như setFoo() nếu tất cả Javadoc của bạn đều là "đặt Foot". Nếu phương thức thực hiện một việc phức tạp hơn (chẳng hạn như thực thi một quy tắc ràng buộc hoặc có tác dụng phụ quan trọng), thì bạn phải ghi chép lại. Nếu không rõ ràng thuộc tính "Foo" nghĩa là bạn nên ghi chép lại.

Mọi phương thức bạn viết, công khai hay theo cách khác, đều được hưởng lợi từ Javadoc. Các phương thức công khai là một phần của một API và do đó cần phải có Javadoc. của Android không thực thi một kiểu cụ thể để viết Javadoc nhận xét, nhưng bạn nên làm theo hướng dẫn trong Cách viết nhận xét trong tài liệu bằng Công cụ Javadoc.

Viết các phương thức ngắn

Nếu có thể, hãy duy trì các phương pháp đơn giản và tập trung. Chúng tôi nhận ra rằng phương pháp đôi khi thích hợp, vì vậy không có giới hạn cố định nào được đặt cho phương thức thời lượng. Nếu một phương thức vượt quá 40 dòng, hãy suy nghĩ xem nó có thể bị phân tách mà không làm tổn hại đến cấu trúc của chương trình.

Xác định trường ở vị trí chuẩn

Xác định các trường ở đầu hoặc ngay trước tệp sử dụng chúng.

Giới hạn phạm vi biến

Hạn chế tối đa phạm vi của biến cục bộ. Chiến dịch này làm tăng khả năng đọc và bảo trì mã, đồng thời giảm khả năng xảy ra lỗi. Khai báo mỗi biến trong lớp trong cùng khối chứa tất cả các cách sử dụng biến.

Khai báo các biến cục bộ tại điểm sử dụng lần đầu tiên. Hầu như mọi khai báo biến cục bộ đều phải chứa trình khởi tạo. Nếu bạn chưa có đủ thông tin để khởi tạo một biến hãy trì hoãn việc khai báo cho đến khi bạn làm thế.

Trường hợp ngoại lệ là các câu lệnh try-catch. Nếu một biến được khởi tạo bằng giá trị trả về của một phương thức gửi ra một ngoại lệ đã đánh dấu, thì giá trị đó phải được khởi tạo bên trong một khối try. Nếu bạn phải sử dụng giá trị này bên ngoài khối try, thì khối này phải được khai báo trước khối try, tại đó chưa thể khởi chạy hợp lý:

// Instantiate class cl, which represents some sort of Set

Set s = null;
try {
    s = (Set) cl.newInstance();
} catch(IllegalAccessException e) {
    throw new IllegalArgumentException(cl + " not accessible");
} catch(InstantiationException e) {
    throw new IllegalArgumentException(cl + " not instantiable");
}

// Exercise the set
s.addAll(Arrays.asList(args));

Tuy nhiên, bạn thậm chí có thể tránh trường hợp này bằng cách đóng gói try-catch chặn trong một phương thức:

Set createSet(Class cl) {
    // Instantiate class cl, which represents some sort of Set
    try {
        return (Set) cl.newInstance();
    } catch(IllegalAccessException e) {
        throw new IllegalArgumentException(cl + " not accessible");
    } catch(InstantiationException e) {
        throw new IllegalArgumentException(cl + " not instantiable");
    }
}

...

// Exercise the set
Set s = createSet(cl);
s.addAll(Arrays.asList(args));

Khai báo các biến vòng lặp trong chính câu lệnh for trừ phi có lý do thuyết phục để làm điều khác:

for (int i = 0; i < n; i++) {
    doSomething(i);
}

for (Iterator i = c.iterator(); i.hasNext(); ) {
    doSomethingElse(i.next());
}

Bảng sao kê nhập đơn đặt hàng

Thứ tự của các câu lệnh nhập là:

  1. Nhập dữ liệu từ Android
  2. Nội dung nhập từ các bên thứ ba (com, junit, net, org)
  3. javajavax

Để khớp chính xác với các chế độ cài đặt IDE, dữ liệu nhập phải:

  • Theo thứ tự bảng chữ cái trong mỗi nhóm, với chữ cái viết hoa trước chữ thường chữ cái viết hoa (ví dụ: Z trước a)
  • Phân tách bằng một dòng trống giữa mỗi nhóm chính (android, com, junit, net, org, java javax)

Ban đầu, không có yêu cầu nào về kiểu định dạng, tức là IDE luôn thay đổi thứ tự hoặc nhà phát triển IDE phải tắt các tính năng quản lý nhập tự động và duy trì dữ liệu nhập. Vấn đề này bị coi là không tốt. Khi kiểu Java được hỏi, các phong cách được ưa thích khác nhau rất nhiều và đến nay, Android cần chỉ cần "chọn thứ tự và nhất quán". Vì vậy, chúng tôi đã chọn một phong cách, đã cập nhật hướng dẫn quy tắc và làm cho IDE tuân theo hướng dẫn đó. Chúng tôi hy vọng rằng Người dùng IDE thao tác trên mã, các lệnh nhập trong tất cả các gói sẽ khớp với mã này mà không cần sử dụng thêm kỹ thuật nào.

Chúng tôi chọn phong cách này sao cho:

  • Các mục nhập mà mọi người muốn xem trước tiên có xu hướng ở trên cùng (android).
  • Các mục nhập mà mọi người muốn xem ít nhất có xu hướng ở dưới cùng (java).
  • Con người có thể dễ dàng làm theo phong cách.
  • IDE có thể tuân theo kiểu.

Đặt lệnh nhập tĩnh lên trên tất cả các lệnh nhập khác được sắp xếp theo cách tương tự như các lệnh nhập thông thường.

Dùng dấu cách để thụt lề

Chúng tôi dùng bốn (4) thụt lề khoảng trắng cho các khối và không bao giờ cho thẻ. Khi nghi ngờ, nhất quán với mã xung quanh.

Chúng ta sử dụng 8 (8) thụt lề khoảng trắng để ngắt dòng, bao gồm cả các lệnh gọi hàm và bài tập.

Recommended (Nên dùng)

Instrument i =
        someLongExpression(that, wouldNotFit, on, one, line);

Không nên

Instrument i =
    someLongExpression(that, wouldNotFit, on, one, line);

Tuân thủ quy ước đặt tên trường

  • Tên trường không công khai, không tĩnh bắt đầu bằng m.
  • Tên trường tĩnh bắt đầu bằng s.
  • Các trường khác bắt đầu bằng một chữ cái thường.
  • Các trường cuối cùng tĩnh (hằng số, không thể thay đổi sâu) là ALL_CAPS_WITH_UNDERSCORES.

Ví dụ:

public class MyClass {
    public static final int SOME_CONSTANT = 42;
    public int publicField;
    private static MyClass sSingleton;
    int mPackagePrivate;
    private int mPrivate;
    protected int mProtected;
}

Sử dụng kiểu dấu ngoặc nhọn tiêu chuẩn

Đặt dấu ngoặc nhọn trên cùng một dòng như mã trước đó, không phải trên dòng riêng:

class MyClass {
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

Chúng ta yêu cầu dấu ngoặc nhọn cho câu lệnh có điều kiện. Trường hợp ngoại lệ: Nếu toàn bộ điều kiện (điều kiện và nội dung) nằm vừa vặn trên một dòng, bạn có thể (nhưng không bắt buộc) nêu tất cả trên một dòng. Ví dụ: được chấp nhận:

if (condition) {
    body();
}

và điều này được chấp nhận:

if (condition) body();

nhưng điều này không được chấp nhận:

if (condition)
    body();  // bad!

Độ dài dòng giới hạn

Mỗi dòng văn bản trong mã của bạn phải dài tối đa 100 ký tự. Mặc dù đã có nhiều cuộc thảo luận xoay quanh quy tắc này, nhưng quyết định vẫn được giữ nguyên đó là tối đa 100 ký tự với các giá trị sau ngoại lệ:

  • Nếu một dòng nhận xét chứa lệnh mẫu hoặc một URL cố định dài hơn hơn 100 ký tự, dòng đó có thể dài hơn 100 ký tự đối với dễ dàng cắt và dán.
  • Các dòng nhập có thể vượt quá giới hạn vì con người hiếm khi nhìn thấy chúng (điều này cũng giúp đơn giản hoá quá trình viết công cụ).

Sử dụng chú giải Java tiêu chuẩn

Chú thích phải đứng trước các đối tượng sửa đổi khác cho cùng một ngôn ngữ . Chú thích điểm đánh dấu đơn giản (ví dụ: @Override) có thể được liệt kê trên cùng một dòng với phần tử ngôn ngữ. Nếu có nhiều chú thích, hoặc các chú thích có tham số, hãy liệt kê chúng từng dòng trong theo thứ tự bảng chữ cái.

Các phương pháp tiêu chuẩn Android cho 3 chú giải được xác định trước trong Java là:

  • Sử dụng chú giải @Deprecated bất cứ khi nào việc sử dụng phần tử được chú giải không được khuyến khích. Nếu bạn sử dụng chú thích @Deprecated, bạn cũng phải có @deprecated Thẻ Javadoc và thẻ này phải đặt tên cho phương thức triển khai thay thế. Ngoài ra, hãy nhớ rằng phương thức @Deprecated vẫn được cho là hoạt động. Nếu bạn thấy mã cũ có thẻ Javadoc @deprecated, hãy thêm Chú thích @Deprecated.
  • Sử dụng chú giải @Override bất cứ khi nào một phương thức sẽ ghi đè phần khai báo hoặc triển khai từ lớp cao cấp. Ví dụ: nếu bạn sử dụng thẻ Javadoc @inheritdocs và bắt nguồn từ một lớp (không phải giao diện), bạn cũng phải chú thích rằng phương thức này sẽ ghi đè phương thức của lớp mẹ.
  • Sử dụng chú giải @SuppressWarnings chỉ trong những trường hợp không thể loại bỏ một cảnh báo. Nếu một cảnh báo vượt qua bước này "không thể loại bỏ" kiểm thử, chú giải @SuppressWarnings phải là để đảm bảo rằng tất cả các cảnh báo đều phản ánh các vấn đề thực tế trong .

    Khi cần chú thích @SuppressWarnings, chú thích đó phải có tiền tố là chú thích TODO giải thích rằng "không thể loại bỏ" . Mã này thường xác định một lớp vi phạm có giao diện khó sử dụng. Ví dụ:

    // TODO: The third-party class com.third.useful.Utility.rotate() needs generics
    @SuppressWarnings("generic-cast")
    List<String> blix = Utility.rotate(blax);
    

    Khi cần chú giải @SuppressWarnings, hãy tái cấu trúc mã để tách riêng các thành phần phần mềm nơi chú thích sẽ được áp dụng.

Coi từ viết tắt là từ

Coi từ viết tắt và chữ viết tắt là từ ngữ khi đặt tên cho biến, phương thức, và lớp để làm cho tên dễ đọc hơn:

Tốt Kém chất lượng
XmlHttpRequest Yêu cầu XMLHTTP
getCustomerId getCustomerID
lớp html HTML của lớp
URL chuỗi URL chuỗi
mã dài mã nhận dạng dài

Vì cả JDK và cơ sở mã Android đều không nhất quán từ viết tắt, nên hầu như không thể nhất quán với xung quanh mã. Do đó, hãy luôn coi từ viết tắt là từ ngữ.

Sử dụng nhận xét trong TODO

Hãy dùng nhận xét TODO cho đoạn mã chỉ mang tính tạm thời, một giải pháp ngắn hạn, hoặc đủ tốt nhưng chưa hoàn hảo. Những nhận xét này phải bao gồm chuỗi TODO trong tất cả viết hoa, theo sau là dấu hai chấm:

// TODO: Remove this code after the UrlTable2 has been checked in.

// TODO: Change this to use a flag instead of a constant.

Nếu TODO của bạn có dạng "Vào một ngày trong tương lai, hãy làm việc gì đó" đảm bảo bạn đưa vào một ngày cụ thể ("Khắc phục trước tháng 11 năm 2005") hoặc một sự kiện cụ thể ("Xóa mã này sau tất cả các trình kết hợp sản xuất hiểu giao thức V7.").

Ghi nhật ký một cách thận trọng

Mặc dù việc ghi nhật ký là cần thiết nhưng nó có tác động tiêu cực đến hiệu suất và mất đi tính hữu ích nếu không được lưu giữ một cách hợp lý ngắn gọn. Các cơ sở ghi nhật ký cung cấp năm cấp độ ghi nhật ký:

  • ERROR: Sử dụng khi có chuyện nghiêm trọng xảy ra, chẳng hạn như một nội dung nào đó sẽ gây ra hậu quả mà người dùng có thể nhận thấy và sẽ không khôi phục được mà không cần xoá một số dữ liệu, gỡ cài đặt ứng dụng, xóa sạch các phân vùng dữ liệu hoặc cài đặt ROM cho toàn bộ thiết bị (hoặc tệ hơn). Cấp độ này luôn được ghi lại. Những vấn đề chứng minh cho một số việc ghi nhật ký ở Cấp độ ERROR là ứng cử viên phù hợp để báo cáo cho máy chủ thu thập số liệu thống kê.
  • WARNING: Sử dụng khi nội dung nào đó nghiêm trọng và không mong muốn đã xảy ra, tức là một điều gì đó sẽ dẫn đến hậu quả mà người dùng có thể nhận thấy nhưng có thể khôi phục được mà không bị mất dữ liệu bằng cách thực hiện một số hành động rõ ràng, chẳng hạn như chờ hoặc khởi động lại ứng dụng bằng mọi cách tải xuống lại phiên bản mới của ứng dụng hoặc khởi động lại thiết bị. Cấp độ này luôn được ghi lại. Các vấn đề phù hợp với việc ghi nhật ký ở cấp WARNING cũng có thể được xem xét cho việc báo cáo cho máy chủ thu thập số liệu thống kê.
  • INFORMATIVE: Sử dụng để ghi chú rằng thông tin nào đó thú vị tức là khi một tình huống được phát hiện có khả năng để có tác động trên diện rộng, dù không hẳn là lỗi. Đúng là điều kiện chỉ nên được ghi nhật ký bởi một mô-đun tin rằng rằng đây là dịch vụ có căn cứ nhất trong miền đó (để tránh bị trùng lặp ghi nhật ký bằng các thành phần không được phép). Cấp độ này luôn được ghi lại.
  • DEBUG: Sử dụng để ghi chú thêm những gì đang diễn ra trên thiết bị có thể liên quan để điều tra và gỡ lỗi ngoài dự kiến của Google. Chỉ ghi lại những dữ liệu cần thiết để thu thập đủ thông tin về những gì đang xảy ra với thành phần của bạn. Nếu gỡ lỗi của bạn nhật ký đang chiếm ưu thế trong nhật ký, thì bạn nên sử dụng thông tin chi tiết ghi nhật ký.

    Cấp độ này được ghi lại ngay cả trên bản phát hành và là cấp độ bắt buộc được bao quanh bởi một khối if (LOCAL_LOG) hoặc if LOCAL_LOGD), trong đó LOCAL_LOG[D] được xác định trong lớp hoặc thành phần phụ để có khả năng để tắt tất cả các hoạt động ghi nhật ký đó. Do đó, không được có logic hoạt động trong khối if (LOCAL_LOG). Toàn bộ quá trình tạo chuỗi cho nhật ký cũng cần được đặt bên trong Khối if (LOCAL_LOG). Không tái cấu trúc lệnh gọi ghi nhật ký tham gia vào lệnh gọi phương thức nếu việc đó sẽ khiến sẽ diễn ra bên ngoài Khối if (LOCAL_LOG).

    Vẫn còn một số mã cho biết if (localLOGV). Chiến dịch này cũng được coi là chấp nhận được, mặc dù tên đó không theo chuẩn.

  • VERBOSE: Dùng cho mọi trường hợp khác. Cấp độ này chỉ được ghi lại trên các bản gỡ lỗi và sẽ được đặt ở giữa if (LOCAL_LOGV) khối (hoặc tương đương) để có thể được biên dịch theo mặc định. Mọi hoạt động tạo chuỗi đều bị loại bỏ bản phát hành và cần xuất hiện bên trong Khối if (LOCAL_LOGV).

Ghi chú

  • Trong một mô-đun nhất định, không phải ở cấp VERBOSE, sẽ xảy ra lỗi chỉ nên báo cáo một lần nếu có thể. Trong một chuỗi lệnh gọi hàm trong một mô-đun, chỉ hàm trong cùng mới được trả về lỗi và phương thức gọi trong cùng một mô-đun chỉ nên thêm một số nhật ký nếu việc đó giúp tách biệt vấn đề một cách đáng kể.
  • Trong một chuỗi mô-đun, không phải ở cấp VERBOSE, khi một mô-đun cấp thấp hơn phát hiện dữ liệu không hợp lệ đến từ cấp cao mô-đun cấp thấp hơn chỉ nên ghi nhật ký tình huống này vào nhật ký DEBUG và chỉ khi việc ghi nhật ký cung cấp thông tin không phải nếu không có sẵn cho người gọi. Cụ thể, bạn không cần các tình huống nhật ký khi xảy ra ngoại lệ (ngoại lệ này sẽ chứa tất cả thông tin có liên quan) hoặc trong đó thông tin duy nhất đang được ghi nhật ký lại có trong một mã lỗi. Điều này đặc biệt quan trọng trong quá trình tương tác giữa khung và ứng dụng, và tình trạng do các ứng dụng bên thứ ba gây ra. do khung xử lý không kích hoạt việc ghi nhật ký cao hơn Cấp độ DEBUG. Các trường hợp duy nhất sẽ kích hoạt việc ghi nhật ký ở Cấp độ INFORMATIVE trở lên là khi một mô-đun hoặc ứng dụng phát hiện thấy lỗi ở cấp độ riêng hoặc cấp thấp hơn.
  • Khi có thể xảy ra một điều kiện thường dùng để xác minh một số hoạt động ghi nhật ký xảy ra nhiều lần, bạn nên triển khai một số cơ chế giới hạn tốc độ để ngăn tình trạng tràn nhật ký có nhiều dữ liệu bản sao trùng lặp của cùng một thông tin (hoặc rất giống nhau).
  • Mất kết nối mạng được xem là phổ biến và hoàn toàn xảy ra và không nên được ghi lại vô cớ. Mất mạng kết nối gây ra các hậu quả trong ứng dụng nên được ghi lại tại cấp DEBUG hoặc VERBOSE (tùy thuộc vào việc hậu quả đủ nghiêm trọng và đủ bất ngờ để được ghi lại trong bản phát hành bản dựng).
  • Có một hệ thống tệp đầy đủ trên một hệ thống tệp có thể truy cập hoặc bật các ứng dụng bên thứ ba không được ghi nhật ký ở cấp độ cao hơn GIÁ TRỊ.
  • Dữ liệu không hợp lệ đến từ bất kỳ nguồn không đáng tin cậy nào (bao gồm bất kỳ tệp nào trên bộ nhớ dùng chung hoặc dữ liệu qua mạng kết nối) được coi là dự kiến và không kích hoạt bất kỳ ghi nhật ký ở cấp độ cao hơn DEBUG khi hệ thống phát hiện thấy không hợp lệ (và thậm chí khi đó nên hạn chế tối đa việc ghi nhật ký).
  • Khi được sử dụng trên các đối tượng String, toán tử + ngầm ẩn sẽ tạo một phiên bản StringBuilder với giá trị mặc định dung lượng bộ nhớ đệm (16 ký tự) và có thể là String tạm thời khác . Vì vậy, việc tạo đối tượng StringBuilder một cách rõ ràng không hơn tốn kém hơn so với việc dựa vào toán tử + mặc định (và có thể rất tốn kém hiệu quả hơn). Xin lưu ý rằng mã gọi Log.v() được biên dịch và thực thi trên các bản phát hành, bao gồm cả việc tạo chuỗi, ngay cả khi hệ thống không đọc nhật ký.
  • Mọi nhật ký dành cho người khác và được đọc trong các bản phát hành phải ngắn gọn mà không gây khó hiểu, và phải dễ hiểu. Bao gồm cả toàn bộ hoạt động ghi nhật ký lên tới cấp DEBUG.
  • Khi có thể, hãy tiếp tục ghi nhật ký trên một dòng. Độ dài dòng tối đa 80 hoặc 100 ký tự có thể chấp nhận được. Tránh sử dụng độ dài quá khoảng 130 hoặc 160 ký tự (bao gồm cả độ dài thẻ) nếu có thể.
  • Nếu việc ghi nhật ký báo cáo thành công, đừng bao giờ sử dụng báo cáo ở cấp cao hơn hơn VERBOSE.
  • Nếu bạn đang sử dụng tính năng ghi nhật ký tạm thời để chẩn đoán một vấn đề khó tái tạo, hãy duy trì ở cấp độ DEBUG hoặc VERBOSE và đính kèm thông báo này bằng các khối if cho phép tắt tuỳ chọn này tại thời gian biên dịch.
  • Hãy cẩn thận với các trường hợp rò rỉ bảo mật thông qua nhật ký. Tránh ghi nhật ký ở chế độ riêng tư của bạn. Cụ thể, hãy tránh ghi nhật ký thông tin về nội dung được bảo vệ. Điều này đặc biệt quan trọng khi viết mã khung vì không dễ để biết trước cái gì sẽ và sẽ không phải là thông tin riêng tư hoặc nội dung được bảo vệ.
  • Không bao giờ dùng System.out.println() (hoặc printf() đối với mã gốc). System.outSystem.err nhận được đã chuyển hướng đến /dev/null, nên các câu lệnh in của bạn sẽ không có các hiệu ứng rõ ràng. Tuy nhiên, tất cả quá trình tạo chuỗi xảy ra cho các lệnh gọi này vẫn được thực thi.
  • Nguyên tắc vàng của việc ghi nhật ký là nhật ký của bạn không được đẩy các nhật ký khác ra khỏi vùng đệm một cách không cần thiết, giống như những nhật ký khác có thể chứ không phải mở rộng ra.

Quy tắc định kiểu trong Javatests

Tuân theo quy ước đặt tên của phương thức thử nghiệm và sử dụng dấu gạch dưới để phân tách những gì được kiểm tra từ trường hợp cụ thể đang được kiểm tra. Phong cách này giúp để bạn dễ dàng biết được trường hợp nào đang được thử nghiệm. Ví dụ:

testMethod_specificCase1 testMethod_specificCase2

void testIsDistinguishable_protanopia() {
    ColorMatcher colorMatcher = new ColorMatcher(PROTANOPIA)
    assertFalse(colorMatcher.isDistinguishable(Color.RED, Color.BLACK))
    assertTrue(colorMatcher.isDistinguishable(Color.X, Color.Y))
}