Gaya kode Java AOSP untuk kontributor

Gaya kode di halaman ini adalah aturan ketat untuk menyumbangkan kode Java ke Proyek Open Source Android (AOSP). Kontribusi untuk platform Android yang tidak mematuhi aturan ini umumnya tidak diterima. Rab menyadari bahwa tidak semua kode yang ada mengikuti aturan ini, tapi kita mengharapkan semua kode baru agar patuh. Lihat Coding dengan hormat contoh terminologi yang dapat digunakan dan dihindari untuk ekosistem yang lebih inklusif.

Tetaplah konsisten

Salah satu aturan paling sederhana adalah BERKONSISTEN. Jika Anda mengedit kode, lakukan beberapa menit untuk melihat kode di sekitarnya dan menentukan gayanya. Jika hal tersebut kode menggunakan spasi di sekitar klausa if, Anda juga harus melakukannya. Jika kode komentar memiliki kotak-kotak bintang kecil di sekelilingnya, buat komentar Anda kotak-kotak kecil bintang di sekelilingnya.

Inti dari memiliki pedoman gaya adalah memiliki kosakata umum tentang {i>coding<i}, sehingga pembaca dapat berkonsentrasi pada apa yang Anda katakan, bukan pada bagaimana Anda mengucapkannya. Kami menyajikan aturan gaya global di sini sehingga Anda tahu kosakata, tetapi gaya lokal juga penting. Jika kode yang Anda tambahkan ke file terlihat sangat berbeda dari kode yang ada di sekitarnya, membuat pembaca tidak selaras ketika mereka membacanya. Coba hindari hal ini.

Aturan bahasa Java

Android mengikuti konvensi coding Java standar dengan aturan tambahan yang dijelaskan di bawah.

Jangan abaikan pengecualian

Anda mungkin ingin menulis kode yang mengabaikan pengecualian, seperti:

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

Jangan lakukan ini. Meskipun Anda mungkin berpikir kode Anda tidak akan pernah mengalami ini kondisi {i>error <i}atau bahwa tidak penting untuk menanganinya, mengabaikan jenis membuat ranjau di kode Anda untuk orang lain agar dipicu suatu hari nanti. Anda harus menangani setiap pengecualian dalam kode dengan dengan prinsip; penanganan spesifik akan berbeda-beda tergantung pada kasusnya.

"Kapan pun seseorang memiliki klausa tangkapan kosong, pelanggan. Pasti ada kalanya informasi tersebut yang harus dilakukan, tapi setidaknya Anda harus memikirkannya. Di Java, Anda tidak bisa terbebas dari perasaan menakutkan itu." — Jefri Gosling

Alternatif yang dapat diterima (dalam urutan preferensi) adalah:

  • Tampilkan pengecualian ke pemanggil metode Anda.
      void setServerPort(String value) throws NumberFormatException {
          serverPort = Integer.parseInt(value);
      }
    
  • Tampilkan pengecualian baru yang sesuai dengan tingkat abstraksi Anda.
      void setServerPort(String value) throws ConfigurationException {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new ConfigurationException("Port " + value + " is not valid.");
        }
      }
    
  • Tangani error dengan baik dan ganti nilai yang sesuai di Blok 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
        }
      }
    
  • Tangkap pengecualian dan tampilkan instance RuntimeException baru. Ini berbahaya, jadi lakukan hanya jika Anda yakin bahwa terjadi {i>error<i}, maka hal yang sesuai untuk dilakukan adalah {i>crash<i}.
      /** 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);
        }
      }
    
  • Sebagai upaya terakhir, jika Anda yakin bahwa mengabaikan pengecualian merupakan sesuai maka Anda boleh mengabaikannya, namun Anda juga harus memberi komentar mengapa dengan Anda memiliki alasan yang kuat.
    /** 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.
        }
    }
    

Tidak menangkap pengecualian umum

Anda mungkin ingin malas menangkap pengecualian dan melakukan sesuatu seperti ini:

  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!
  }

Jangan lakukan ini. Hampir semua kasus, tidaklah pantas untuk menangkap Exception atau Throwable (sebaiknya bukan Throwable karena menyertakan pengecualian Error). Ini berbahaya karena itu berarti bahwa pengecualian yang tidak pernah Anda duga (termasuk pengecualian runtime seperti ClassCastException) terlibat dalam penanganan kesalahan tingkat aplikasi. {i>Metadata<i} mengaburkan kegagalan menangani properti kode Anda, artinya jika seseorang menambahkan jenis dalam kode yang Anda panggil, compiler tidak akan menunjukkan bahwa Anda perlu menangani {i>error<i} secara berbeda. Dalam kebanyakan kasus, Anda seharusnya tidak menangani berbagai jenis pengecualian dengan cara yang sama.

Pengecualian yang jarang terjadi untuk aturan ini adalah kode pengujian dan kode tingkat atas dengan Anda ingin menemukan berbagai jenis {i>error<i} (untuk mencegahnya muncul di UI, atau untuk membuat tugas batch tetap berjalan). Dalam kasus ini, Anda mungkin mendapati Exception (atau Throwable) generik dan menangani error dengan tepat. Namun, pikirkan baik-baik sebelum melakukan ini, dan beri komentar menjelaskan mengapa kampanye ini aman dalam konteks ini.

Alternatif untuk menangkap pengecualian umum:

  • Tangkap setiap pengecualian secara terpisah sebagai bagian dari blok multi-tangkapan, misalnya:
    try {
        ...
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        ...
    }
  • Faktorkan ulang kode Anda agar penanganan errornya lebih mendetail, dengan beberapa blok percobaan. Memisahkan IO dari penguraian, dan menangani error secara terpisah dalam setiap kasus.
  • Tampilkan ulang pengecualian. Sering kali Anda tidak perlu menangkap pengecualian pada level ini, biarkan saja metode itu yang membuangnya.

Ingatlah bahwa Anda hanya perlu pengecualian! Ketika kompiler mengeluh bahwa Anda jangan cemberut, jangan cemberut. Senyum! Kompilatornya baru saja berhasil memudahkan Anda menangkap masalah runtime dalam kode.

Jangan gunakan finaler

Finalizer adalah cara untuk mengeksekusi sepotong kode ketika suatu objek pembersihan sampah memori. Sementara finaler dapat berguna untuk pembersihan (terutama sumber daya eksternal), tidak ada jaminan mengenai kapan finaler akan dipanggil (atau bahkan akan dipanggil sama sekali).

Android tidak menggunakan finaler. Dalam kebanyakan kasus, Anda dapat menggunakan penanganan pengecualian yang baik. Jika Anda benar-benar membutuhkan finaler, tentukan metode close() (atau yang serupa) dan dokumentasikan tepat ketika metode tersebut metode perlu dipanggil (lihat InputStream sebagai contoh). Dalam kasus ini, sudah sesuai tetapi tidak diperlukan untuk mencetak pesan log singkat dari finaler, selama tidak membanjiri log.

Impor yang memenuhi syarat sepenuhnya

Bila Anda ingin menggunakan class Bar dari paket foo, ada dua cara yang mungkin untuk mengimpornya:

  • import foo.*;

    Berpotensi mengurangi jumlah pernyataan impor.

  • import foo.Bar;

    Memperjelas class yang digunakan dan kodenya lebih dapat dibaca oleh pengelola.

Gunakan import foo.Bar; untuk mengimpor semua kode Android. Channel pengecualian eksplisit dibuat untuk library standar Java (java.util.*, java.io.*, dll.) dan kode pengujian unit (junit.framework.*).

Aturan library Java

Ada konvensi untuk menggunakan library dan alat Java Android. Di beberapa dalam beberapa kasus, konvensi telah berubah dengan cara penting dan kode lama mungkin menggunakan pola atau pustaka yang sudah tidak digunakan lagi. Saat bekerja dengan kode seperti itu, Anda dapat melanjutkan gaya yang sudah ada. Saat membuat komponen baru namun, jangan pernah menggunakan library yang tidak digunakan lagi.

Aturan gaya Java

Menggunakan komentar standar Javadoc

Setiap file harus memiliki pernyataan hak cipta di bagian atas, diikuti dengan pernyataan paket dan impor (setiap blok dipisahkan oleh baris kosong), dan terakhir deklarasi class atau antarmuka. Pada komentar Javadoc, untuk mendeskripsikan fungsi class atau antarmuka.

/*
 * 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 {
    ...
}

Setiap class dan metode publik nontrivial yang Anda tulis harus berisi komentar Javadoc dengan setidaknya satu kalimat yang menjelaskan apa yang atau metode lain. Kalimat ini harus dimulai dengan orang ketiga deskriptif.

Contoh

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

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

atau

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

Anda tidak perlu menulis Javadoc untuk metode get dan set trivial seperti setFoo() jika semua Javadoc Anda adalah "sets Foo". Jika metode ini melakukan sesuatu yang lebih kompleks (seperti menerapkan batasan atau memiliki efek samping yang penting), maka Anda harus mendokumentasikannya. Jika tidak sudah jelas apa yang dimaksud dengan properti "Foo" berarti, Anda harus mendokumentasikannya.

Setiap metode yang Anda tulis, publik atau lainnya, akan mendapat manfaat dari Javadoc. Metode publik adalah bagian dari API sehingga memerlukan Javadoc. Android tidak memberlakukan gaya khusus untuk menulis Javadoc tetapi Anda harus mengikuti petunjuk di Cara Menulis Komentar Dokumen untuk Alat Javadoc.

Menulis metode singkat

Jika memungkinkan, usahakan agar metode tetap kecil dan fokus. Kami paham bahwa lama terkadang sesuai, sehingga tidak ada batasan pasti yang ditempatkan pada metode paruh. Jika suatu metode melebihi 40 baris atau lebih, pikirkan apakah metode itu dapat diselesaikan tanpa merusak struktur program.

Menentukan kolom di tempat standar

Tentukan kolom di bagian atas file atau tepat sebelum metode yang menggunakannya.

Batasi cakupan variabel

Minimalkan cakupan variabel lokal. Ini meningkatkan keterbacaan dan pengelolaan kode Anda dan mengurangi kemungkinan terjadinya error. Deklarasikan setiap variabel di bagian terdalam yang mencakup semua penggunaan variabel.

Deklarasikan variabel lokal pada titik tempat variabel tersebut pertama kali digunakan. Hampir setiap deklarasi variabel lokal harus berisi penginisialisasi. Jika Anda belum memiliki informasi yang cukup untuk melakukan inisialisasi variabel dengan bijak, tunda pernyataan sampai Anda melakukannya.

Pengecualiannya adalah pernyataan try-catch. Jika variabel diinisialisasi dengan nilai hasil dari metode yang menampilkan pengecualian yang dicentang, maka harus diinisialisasi di dalam blok try. Jika nilai harus digunakan di luar coba, maka harus dideklarasikan sebelum blok try, di mana ia belum dapat diinisialisasi secara bijaksana:

// 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));

Namun, Anda bahkan dapat menghindari kasus ini dengan melakukan enkapsulasi {i>try-catch<i} memblokir dalam metode:

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));

Mendeklarasikan variabel loop dalam pernyataan for itu sendiri kecuali ada alasan kuat untuk melakukan yang sebaliknya:

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

dan

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

Pernyataan impor pesanan

Urutan pernyataan impor adalah:

  1. Impor Android
  2. Impor dari pihak ketiga (com, junit, net, org)
  3. java dan javax

Agar sama persis dengan setelan IDE, impornya harus berupa:

  • Menurut abjad dalam setiap grup, dengan huruf kapital sebelum huruf kecil huruf besar/kecil (misalnya, Z sebelum a)
  • Dipisahkan oleh garis kosong di antara setiap pengelompokan utama (android, com, junit, net, org, java, javax)

Awalnya, tidak ada persyaratan gaya pada pengurutan, yang berarti IDE selalu mengubah urutan atau pengembang IDE harus nonaktifkan fitur pengelolaan impor otomatis dan mengelolanya secara manual impor. Hal ini dianggap buruk. Ketika gaya Java diminta, gaya yang disukai sangat bervariasi dan bergantung pada Android yang perlu hanya "memilih pesanan dan konsisten". Jadi kita memilih gaya, memperbarui panduan gaya, dan membuat IDE mematuhinya. Kami berharap bahwa sebagai Pengguna IDE mengerjakan kode, impor dalam semua paket akan cocok dengan tanpa upaya teknis tambahan.

Kita memilih gaya ini sedemikian rupa sehingga:

  • Impor yang ingin dilihat orang pertama kali cenderung (android).
  • Impor yang ingin dilihat orang setidaknya cenderung berada di bagian bawah (java).
  • Manusia dapat dengan mudah mengikuti gaya.
  • IDE dapat mengikuti gaya.

Tempatkan impor statis di atas semua impor lainnya diurutkan dengan cara yang sama seperti impor reguler.

Menggunakan spasi untuk indentasi

Kami menggunakan empat (4) indentasi spasi untuk blok dan tidak pernah tab. Jika ragu, konsisten dengan kode di sekitarnya.

Kami menggunakan delapan (8) indentasi spasi untuk {i>line wrap<i}, termasuk panggilan fungsi dan tugas.

Direkomendasikan

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

Tidak direkomendasikan

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

Ikuti konvensi penamaan {i>field<i}

  • Nama kolom non-publik dan non-statis dimulai dengan m.
  • Nama kolom statis dimulai dengan s.
  • Kolom lain dimulai dengan huruf kecil.
  • Kolom akhir statis (konstanta, sangat tidak dapat diubah) adalah ALL_CAPS_WITH_UNDERSCORES.

Contoh:

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;
}

Gunakan gaya kurung kurawal standar

Letakkan tanda kurung kurawal pada baris yang sama dengan kode di depannya, bukan di barisnya sendiri:

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

Kita memerlukan tanda kurung kurawal di sekitar pernyataan untuk kondisional. Pengecualian: Jika seluruh kondisional (kondisi dan {i>body<i}) muat dalam satu baris, Anda dapat (tetapi tidak berkewajiban) menyatukan semuanya dalam satu baris. Misalnya, dapat diterima:

if (condition) {
    body();
}

dan ini dapat diterima:

if (condition) body();

tetapi hal ini tidak dapat diterima:

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

Batasi panjang baris

Setiap baris teks dalam kode Anda maksimal harus 100 karakter. Meskipun banyak diskusi telah mengelilingi aturan ini, keputusannya tetap bahwa 100 karakter adalah jumlah maksimum dengan pengecualian:

  • Jika baris komentar berisi contoh perintah atau URL literal yang lebih panjang dari 100 karakter, baris tersebut bisa lebih dari 100 karakter untuk kemudahan memotong dan menempel.
  • Baris impor dapat melampaui batas karena manusia jarang melihatnya (ini juga menyederhanakan penulisan alat).

Menggunakan anotasi Java standar

Anotasi harus mendahului pengubah lain untuk bahasa yang sama . Anotasi penanda sederhana (misalnya, @Override) dapat dicantumkan di baris yang sama dengan elemen bahasa. Jika ada beberapa anotasi, atau anotasi berparameter, cantumkan satu per baris sesuai abjad.

Praktik standar Android untuk tiga anotasi yang telah ditentukan sebelumnya dalam Java adalah:

  • Menggunakan anotasi @Deprecated ketika penggunaan elemen yang dianotasi tidak disarankan. Jika Anda menggunakan anotasi @Deprecated, Anda juga harus memiliki @deprecated Tag Javadoc dan harus menamai implementasi alternatif. Selain itu, ingat bahwa metode @Deprecated masih seharusnya berfungsi. Jika Anda melihat kode lama yang memiliki tag Javadoc @deprecated, tambahkan metode anotasi @Deprecated.
  • Gunakan anotasi @Override setiap kali metode mengganti deklarasi atau implementasi dari superclass. Misalnya, jika Anda menggunakan tag Javadoc @inheritdocs, dan berasal dari class (bukan antarmuka), Anda juga harus memberi anotasi bahwa metode tersebut mengganti metode class induk.
  • Menggunakan anotasi @SuppressWarnings hanya dalam keadaan di mana tidak mungkin untuk menghilangkan peringatan. Jika peringatan dianggap "tidak mungkin untuk menghilangkan" anotasi @SuppressWarnings harus digunakan, untuk memastikan bahwa semua peringatan mencerminkan masalah sebenarnya dalam pada kode sumber.

    Saat diperlukan, anotasi @SuppressWarnings harus diawali dengan komentar TODO yang menjelaskan "tidak mungkin untuk menghilangkan" . Hal ini biasanya mengidentifikasi kelas yang mengganggu yang memiliki antarmuka canggung. Contoh:

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

    Saat anotasi @SuppressWarnings diperlukan, faktorkan ulang kode untuk mengisolasi elemen software tempat anotasi berlaku.

Perlakukan akronim sebagai kata

Perlakukan akronim dan singkatan sebagai kata dalam penamaan variabel, metode, dan class untuk membuat nama lebih mudah dibaca:

Bagus Buruk
{i>XmlHttpRequest<i} Permintaan
getCustomerId getCustomerID
HTML kelas HTML kelas
URL string URL String
long id ID panjang

Karena JDK dan code base Android tidak konsisten akronim ini, hampir tidak mungkin untuk konsisten dengan kode di sekitarnya. Oleh karena itu, selalu anggap akronim sebagai kata.

Menggunakan komentar TODO

Gunakan komentar TODO untuk kode yang bersifat sementara, solusi jangka pendek, atau cukup baik tetapi tidak sempurna. Komentar ini harus menyertakan string TODO di semua huruf besar, diikuti dengan titik dua:

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

dan

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

Jika TODO Anda berbentuk "Di masa mendatang, lakukan sesuatu" memastikan bahwa Anda menyertakan tanggal tertentu ("Perbaiki paling lambat November 2005") atau peristiwa tertentu ("Hapus kode ini setelah semua mixer produksi memahami protokol V7.").

Catat dengan hemat

Meskipun logging diperlukan, hal ini berdampak negatif pada kinerja dan kehilangan kegunaannya jika tidak dijaga secara wajar singkat. Fasilitas pencatatan log menyediakan lima tingkat pencatatan yang berbeda:

  • ERROR: Gunakan saat terjadi sesuatu yang fatal, yaitu sesuatu akan memiliki konsekuensi yang terlihat oleh pengguna dan tidak akan dapat dipulihkan tanpa menghapus beberapa data, menghapus instalan aplikasi, menghapus partisi data, atau menginstal ulang seluruh perangkat (atau lebih buruk). Level ini selalu dicatat. Masalah yang terkait dengan pencatatan log di Level ERROR adalah kandidat yang baik untuk dilaporkan ke server pengumpulan statistik.
  • WARNING: Gunakan saat terjadi sesuatu yang serius dan tidak terduga terjadi, yaitu, sesuatu yang akan memiliki konsekuensi yang terlihat oleh pengguna tetapi dapat dipulihkan tanpa kehilangan data dengan melakukan beberapa tindakan eksplisit, mulai dari menunggu atau memulai ulang aplikasi untuk mengunduh ulang versi baru dari aplikasi atau me-{i>reboot<i} perangkat seluler. Level ini selalu dicatat. Masalah yang membenarkan pencatatan di tingkat WARNING juga dapat dipertimbangkan untuk pelaporan ke server pengumpulan statistik.
  • INFORMATIVE: Gunakan untuk mencatat bahwa sesuatu yang menarik terjadi, yaitu ketika sebuah situasi yang kemungkinan besar terdeteksi memiliki dampak yang luas, meskipun bukan merupakan kesalahan. Sungguh kondisi ini seharusnya hanya dicatat oleh modul yang yakin paling otoritatif di domain tersebut (untuk menghindari duplikasi log oleh komponen non-otoritatif). Level ini selalu dicatat.
  • DEBUG: Gunakan untuk mencatat lebih lanjut apa yang terjadi di perangkat yang mungkin relevan untuk diselidiki dan melakukan debug perilaku model. Catat hanya yang diperlukan untuk mengumpulkan cukup informasi tentang apa yang terjadi dengan komponen Anda. Jika debug Anda log mendominasi log, maka Anda harus menggunakan {i>verbose<i} pembuatan log.

    Level ini dicatat bahkan pada build rilis, dan diperlukan untuk dikelilingi oleh blok if (LOCAL_LOG) atau if LOCAL_LOGD), tempat LOCAL_LOG[D] ditentukan di class atau subkomponen, jadi ada kemungkinan untuk menonaktifkan semua logging tersebut. Oleh karena itu, tidak boleh ada logika yang aktif dalam blok if (LOCAL_LOG). Semua pembuatan {i>string<i} untuk log juga harus ditempatkan di dalam Blok if (LOCAL_LOG). Jangan faktorkan ulang panggilan logging ke dalam panggilan metode jika akan menyebabkan pembuatan string terjadi di luar Blok if (LOCAL_LOG).

    Ada beberapa kode yang masih bertuliskan if (localLOGV). Ini dianggap sebagai dapat diterima, meskipun namanya tidak standar.

  • VERBOSE: Digunakan untuk lainnya. Level ini hanya yang dicatat pada build debug dan harus dikelilingi oleh if (LOCAL_LOGV) blok (atau yang setara) sehingga dapat dikompilasi secara {i>default<i}. Setiap bangunan {i>string<i} dilepas dari build rilis dan harus muncul di dalam Blok if (LOCAL_LOGV).

Catatan

  • Dalam modul tertentu, selain pada level VERBOSE, error sebaiknya hanya dilaporkan satu kali jika memungkinkan. Dalam satu rantai panggilan fungsi dalam modul, hanya fungsi terdalam yang harus mengembalikan kesalahan, dan pemanggil dalam modul yang sama hanya boleh menambahkan beberapa pencatatan {i>logging<i} jika hal itu secara signifikan membantu mengisolasi masalah.
  • Dalam rantai modul, selain di level VERBOSE, saat modul level lebih rendah mendeteksi data tidak valid yang berasal dari modul tingkat rendah, seharusnya hanya mencatat situasi ini DEBUG log, dan hanya jika pencatatan log memberikan informasi yang tidak jika tidak tersedia untuk pemanggil. Secara khusus, tidak perlu situasi log tempat pengecualian ditampilkan (pengecualian harus berisi semua informasi yang relevan), atau jika satu-satunya informasi yang dicatat terdapat dalam kode {i>error<i}. Hal ini terutama penting dalam interaksi antara kerangka kerja dan aplikasi, dan kondisi yang disebabkan oleh aplikasi pihak ketiga yang ditangani oleh kerangka kerja seharusnya tidak memicu pencatatan log lebih tinggi dari Tingkat DEBUG. Satu-satunya situasi yang seharusnya memicu logging pada Level INFORMATIVE atau lebih tinggi adalah saat modul atau aplikasi mendeteksi kesalahan pada tingkatnya sendiri atau berasal dari tingkat yang lebih rendah.
  • Ketika kondisi yang biasanya membenarkan beberapa pencatatan kemungkinan terjadi berkali-kali, menjadi ide yang baik untuk menerapkan beberapa mekanisme pembatasan kapasitas untuk mencegah kelebihan beban pada log salinan duplikat dari informasi yang sama (atau sangat mirip).
  • Kehilangan konektivitas jaringan dianggap umum dan terjadi sepenuhnya diharapkan, dan tidak boleh dicatat secara serampangan. Hilangnya jaringan konektivitas yang memiliki konsekuensi dalam aplikasi harus dicatat dalam tingkat DEBUG atau VERBOSE (bergantung pada apakah konsekuensinya cukup serius dan tidak terduga sehingga tidak dapat dicatat dalam rilis build).
  • Memiliki sistem file lengkap pada sistem file yang dapat diakses oleh atau di nama aplikasi pihak ketiga tidak seharusnya dicatat di tingkat lebih tinggi daripada INFORMATIF.
  • Data yang tidak valid berasal dari sumber yang tidak tepercaya (termasuk file apa pun di penyimpanan bersama, atau data yang masuk melalui jaringan tambahan) dianggap sudah diperkirakan dan seharusnya tidak memicu mencatat log pada tingkat yang lebih tinggi dari DEBUG ketika terdeteksi tidak valid (dan log harus dibatasi sebatas mungkin).
  • Saat digunakan pada objek String, operator + secara implisit membuat instance StringBuilder dengan ukuran buffer (16 karakter) dan kemungkinan String sementara lainnya objek terstruktur dalam jumlah besar. Jadi, membuat objek StringBuilder secara eksplisit tidak lebih lebih mahal daripada mengandalkan operator + {i>default<i} (dan bisa sangat lebih efisien). Perlu diingat bahwa kode yang memanggil Log.v() dikompilasi dan dieksekusi pada build rilis, termasuk membangun {i>string<i}, bahkan jika log tidak dibaca.
  • Setiap {i>logging<i} yang dimaksudkan untuk dibaca oleh orang lain dan untuk yang tersedia dalam build rilis harus singkat tanpa samar, dan harus dapat dipahami. Hal ini termasuk semua logging hingga tingkat DEBUG.
  • Jika memungkinkan, tetap lakukan logging pada satu baris. Panjang baris hingga 80 atau 100 karakter adalah masih dapat diterima. Hindari panjang yang lebih dari 130 atau 160 karakter (termasuk panjang tag) jika memungkinkan.
  • Jika pencatatan log berhasil, jangan pernah menggunakannya pada tingkat yang lebih tinggi dari VERBOSE.
  • Jika Anda menggunakan {i>logging<i} sementara untuk mendiagnosis masalah yang sulit mereproduksi, mempertahankannya di level DEBUG atau VERBOSE, dan tambahkan blok if yang memungkinkan penonaktifan waktu kompilasi.
  • Hati-hati dengan kebocoran keamanan melalui log. Menghindari logging pribadi tidak akurat atau tidak sesuai. Secara khusus, hindari pencatatan log tentang konten yang dilindungi. Hal ini sangat penting ketika menulis kode kerangka kerja karena tidak mudah untuk mengetahui terlebih dahulu apa yang akan dan tidak akan berupa informasi pribadi atau konten yang dilindungi.
  • Jangan pernah gunakan System.out.println() (atau printf() untuk kode native). System.out dan System.err mendapatkan dialihkan ke /dev/null, sehingga pernyataan cetak Anda tidak memiliki efek yang terlihat. Namun, semua bangunan {i>string<i} yang terjadi untuk panggilan ini masih dijalankan.
  • Aturan emas pencatatan adalah log Anda mungkin tidak mendorong log lain keluar dari buffer, sama seperti yang mungkin dan bukan deployment Anda.

Aturan gaya Javatest

Ikuti konvensi penamaan metode pengujian dan gunakan garis bawah untuk memisahkan apa yang sedang diuji dari kasus tertentu yang sedang diuji. Gaya ini membuat lebih mudah untuk melihat kasus mana yang sedang diuji. Contoh:

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))
}