Gaya Kode Java AOSP untuk Kontributor

Gaya kode di halaman ini adalah aturan ketat untuk menyumbangkan kode Java ke Android Open Source Project (AOSP). Kontribusi ke platform Android yang tidak mematuhi aturan ini umumnya tidak diterima . Kami menyadari bahwa tidak semua kode yang ada mengikuti aturan ini, tetapi kami berharap semua kode baru mematuhinya. Lihat Pengodean dengan Hormat untuk contoh terminologi yang digunakan dan dihindari untuk ekosistem yang lebih inklusif.

Konsisten

Salah satu aturan paling sederhana adalah BE KONSISTEN. Jika Anda mengedit kode, luangkan beberapa menit untuk melihat kode di sekitarnya dan menentukan gayanya. Jika kode itu menggunakan spasi di sekitar klausa if , Anda juga harus melakukannya. Jika komentar kode memiliki kotak-kotak kecil bintang di sekelilingnya, buatlah komentar Anda memiliki kotak-kotak kecil bintang di sekelilingnya juga.

Inti dari memiliki pedoman gaya adalah untuk memiliki kosakata pengkodean yang umum, sehingga pembaca dapat berkonsentrasi pada apa yang Anda katakan, bukan pada bagaimana Anda mengatakannya. Kami menyajikan aturan gaya global di sini agar Anda tahu kosa kata, tetapi gaya lokal juga penting. Jika kode yang Anda tambahkan ke file terlihat sangat berbeda dari kode yang ada di sekitarnya, pembaca akan kehilangan ritme saat mereka membacanya. Cobalah untuk menghindari ini.

aturan bahasa jawa

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

Jangan abaikan pengecualian

Anda mungkin tergoda untuk 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 kondisi kesalahan ini atau bahwa tidak penting untuk menanganinya, mengabaikan jenis pengecualian ini membuat ranjau dalam kode Anda untuk dipicu oleh orang lain suatu hari nanti. Anda harus menangani setiap pengecualian dalam kode Anda dengan cara yang berprinsip; penanganan khusus bervariasi tergantung pada kasusnya.

" Setiap kali seseorang memiliki klausa tangkapan kosong, mereka harus memiliki perasaan menyeramkan. Pasti ada saat-saat ketika itu sebenarnya hal yang benar untuk dilakukan, tetapi setidaknya Anda harus memikirkannya. Di Jawa Anda tidak dapat menghindari perasaan menyeramkan. " — James Gosling

Alternatif yang dapat diterima (dalam urutan preferensi) adalah:

  • Lemparkan pengecualian ke pemanggil metode Anda.
      void setServerPort(String value) throws NumberFormatException {
          serverPort = Integer.parseInt(value);
      }
    
  • Lempar 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 kesalahan dengan baik dan gantikan 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 lempar instance baru RuntimeException . Ini berbahaya, jadi lakukan hanya jika Anda yakin jika kesalahan ini terjadi, hal yang tepat untuk dilakukan adalah crash.
      /** 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 itu tepat maka Anda dapat mengabaikannya, tetapi Anda juga harus berkomentar mengapa dengan alasan yang bagus.
    /** 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.
        }
    }
    

Jangan menangkap pengecualian umum

Mungkin tergoda untuk menjadi malas ketika 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. Dalam hampir semua kasus, tidak tepat untuk menangkap Exception umum atau Throwable (sebaiknya tidak Throwable karena menyertakan pengecualian Error ). Ini berbahaya karena itu berarti pengecualian yang tidak pernah Anda harapkan (termasuk pengecualian runtime seperti ClassCastException ) terjebak dalam penanganan kesalahan tingkat aplikasi. Ini mengaburkan properti penanganan kegagalan kode Anda, yang berarti jika seseorang menambahkan jenis pengecualian baru dalam kode yang Anda panggil, kompilator tidak akan menunjukkan bahwa Anda perlu menangani kesalahan secara berbeda. Dalam kebanyakan kasus, Anda tidak boleh menangani berbagai jenis pengecualian dengan cara yang sama.

Pengecualian yang jarang terjadi untuk aturan ini adalah kode pengujian dan kode tingkat atas tempat Anda ingin menangkap semua jenis kesalahan (untuk mencegahnya muncul di UI, atau untuk membuat pekerjaan batch tetap berjalan). Dalam kasus ini, Anda dapat menangkap Exception umum (atau Throwable ) dan menangani kesalahan dengan tepat. Pikirkan baik-baik sebelum melakukan ini, dan berikan komentar yang menjelaskan mengapa ini aman dalam konteks ini.

Alternatif untuk menangkap pengecualian umum:

  • Tangkap setiap pengecualian secara terpisah sebagai bagian dari blok multi-tangkap, misalnya:
    try {
        ...
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        ...
    }
  • Memfaktorkan ulang kode Anda agar memiliki penanganan kesalahan yang lebih halus, dengan beberapa blok percobaan. Pisahkan IO dari penguraian, dan tangani kesalahan secara terpisah di setiap kasus.
  • Ulangi pengecualian. Sering kali Anda tidak perlu menangkap pengecualian pada level ini, biarkan saja metode membuangnya.

Ingatlah bahwa pengecualian adalah teman Anda! Ketika kompiler mengeluh bahwa Anda tidak menangkap pengecualian, jangan cemberut. Senyum! Kompiler hanya mempermudah Anda untuk menangkap masalah runtime dalam kode Anda.

Jangan gunakan finalizer

Finalizer adalah cara untuk mengeksekusi sepotong kode ketika suatu objek adalah sampah yang dikumpulkan. Meskipun finalizer dapat berguna untuk pembersihan (khususnya sumber daya eksternal), tidak ada jaminan kapan finalizer akan dipanggil (atau bahkan akan dipanggil sama sekali).

Android tidak menggunakan finalizer. Dalam kebanyakan kasus, Anda dapat menggunakan penanganan pengecualian yang baik sebagai gantinya. Jika Anda benar-benar membutuhkan finalizer, tentukan metode close() (atau sejenisnya) dan dokumentasikan secara tepat kapan metode itu perlu dipanggil (lihat InputStream untuk contoh). Dalam hal ini, itu tepat tetapi tidak diharuskan untuk mencetak pesan log singkat dari finalizer, selama itu tidak diharapkan untuk membanjiri log.

Impor yang memenuhi syarat sepenuhnya

Saat Anda ingin menggunakan class Bar dari package foo , ada dua cara yang memungkinkan untuk mengimpornya:

  • import foo.*;

    Berpotensi mengurangi jumlah pernyataan impor.

  • import foo.Bar;

    Memperjelas kelas apa yang digunakan dan kode lebih mudah dibaca oleh pengelola.

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

Aturan perpustakaan Java

Ada konvensi untuk menggunakan perpustakaan dan alat Java Android. Dalam beberapa kasus, konvensi telah berubah dengan cara yang penting dan kode yang lebih lama mungkin menggunakan pola atau pustaka yang tidak digunakan lagi. Saat bekerja dengan kode seperti itu, boleh saja melanjutkan gaya yang ada. Namun, saat membuat komponen baru, jangan pernah menggunakan pustaka yang tidak digunakan lagi.

Aturan gaya Java

Gunakan komentar standar Javadoc

Setiap file harus memiliki pernyataan hak cipta di bagian atas, diikuti oleh pernyataan paket dan impor (setiap blok dipisahkan oleh baris kosong), dan terakhir deklarasi kelas atau antarmuka. Dalam komentar Javadoc, jelaskan apa yang dilakukan kelas atau antarmuka.

/*
 * Copyright 2022 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 kelas dan metode publik nontrivial yang Anda tulis harus berisi komentar Javadoc dengan setidaknya satu kalimat yang menjelaskan apa yang dilakukan oleh kelas atau metode tersebut. Kalimat ini harus dimulai dengan kata kerja deskriptif orang ketiga.

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 yang sepele seperti setFoo() jika semua yang dikatakan Javadoc adalah "sets Foo". Jika metode melakukan sesuatu yang lebih kompleks (seperti memberlakukan batasan atau memiliki efek samping yang penting), maka Anda harus mendokumentasikannya. Jika tidak jelas apa arti properti "Foo", Anda harus mendokumentasikannya.

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

Tulis metode singkat

Jika memungkinkan, pertahankan metode tetap kecil dan fokus. Kami menyadari bahwa metode panjang terkadang tepat, jadi tidak ada batasan keras yang ditempatkan pada panjang metode. Jika suatu metode melebihi 40 baris atau lebih, pikirkan apakah metode tersebut dapat dipecah tanpa merusak struktur program.

Tentukan bidang di tempat standar

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

Batasi cakupan variabel

Pertahankan cakupan variabel lokal seminimal mungkin. Ini meningkatkan keterbacaan dan pemeliharaan kode Anda dan mengurangi kemungkinan kesalahan. Deklarasikan setiap variabel di blok terdalam yang mencakup semua penggunaan variabel.

Deklarasikan variabel lokal pada titik di mana mereka pertama kali digunakan. Hampir setiap deklarasi variabel lokal harus berisi inisialisasi. Jika Anda belum memiliki informasi yang cukup untuk menginisialisasi variabel dengan bijaksana, tunda deklarasi sampai Anda melakukannya.

Pengecualiannya adalah pernyataan try-catch. Jika sebuah variabel diinisialisasi dengan nilai kembalian dari metode yang melontarkan pengecualian yang dicentang, variabel tersebut harus diinisialisasi di dalam blok try. Jika nilai harus digunakan di luar blok try, maka nilai tersebut harus dideklarasikan sebelum blok try, di mana ia belum dapat diinisialisasi dengan 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 mengenkapsulasi blok try-catch dalam suatu 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));

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

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

dan

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

Pesan impor pernyataan

Urutan pernyataan impor adalah:

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

Agar sama persis dengan pengaturan IDE, impor harus:

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

Awalnya, tidak ada persyaratan gaya pada pemesanan, artinya IDE selalu mengubah pemesanan atau pengembang IDE harus menonaktifkan fitur manajemen impor otomatis dan mempertahankan impor secara manual. Ini dianggap buruk. Ketika gaya Java ditanya, gaya yang disukai sangat bervariasi dan Android hanya perlu "memilih pemesanan dan konsisten." Jadi kami memilih gaya, memperbarui panduan gaya, dan membuat IDE mematuhinya. Kami berharap bahwa saat pengguna IDE mengerjakan kode, impor di semua paket akan cocok dengan pola ini tanpa upaya rekayasa ekstra.

Kami memilih gaya ini sedemikian rupa sehingga:

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

Letakkan impor statis di atas semua impor lain yang dipesan dengan cara yang sama seperti impor biasa.

Gunakan spasi untuk lekukan

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

Kami menggunakan delapan (8) indentasi spasi untuk pembungkus baris, termasuk pemanggilan fungsi dan penetapan.

Direkomendasikan

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

Tidak direkomendasikan

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

Ikuti konvensi penamaan bidang

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

Sebagai 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 penjepit standar

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

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

Kami membutuhkan kurung kurawal di sekitar pernyataan untuk kondisional. Pengecualian: Jika seluruh conditional (kondisi dan badan) muat dalam satu baris, Anda boleh (tetapi tidak wajib) meletakkan semuanya dalam satu baris. Misalnya, ini dapat diterima:

if (condition) {
    body();
}

dan ini dapat diterima:

if (condition) body();

tetapi ini tidak dapat diterima:

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

Batasi panjang garis

Setiap baris teks dalam kode Anda harus memiliki panjang maksimal 100 karakter. Sementara banyak diskusi telah melingkupi aturan ini, keputusannya tetap bahwa 100 karakter adalah maksimum dengan pengecualian berikut :

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

Gunakan anotasi Java standar

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

Praktik standar Android untuk tiga anotasi standar di Java adalah:

  • Gunakan anotasi @Deprecated setiap kali penggunaan elemen beranotasi tidak disarankan. Jika Anda menggunakan anotasi @Deprecated , Anda juga harus memiliki tag Javadoc @deprecated dan harus menyebutkan implementasi alternatif. Selain itu, ingatlah bahwa metode @Deprecated seharusnya masih berfungsi . Jika Anda melihat kode lama yang memiliki tag Javadoc @deprecated , tambahkan anotasi @Deprecated .
  • Gunakan anotasi @Override setiap kali suatu metode menimpa deklarasi atau implementasi dari superclass. Misalnya, jika Anda menggunakan tag Javadoc @inheritdocs , dan diturunkan dari kelas (bukan antarmuka), Anda juga harus memberi anotasi bahwa metode tersebut menggantikan metode kelas induk.
  • Gunakan anotasi @SuppressWarnings hanya dalam keadaan di mana tidak mungkin untuk menghilangkan peringatan. Jika peringatan lolos uji "mustahil untuk dihilangkan" ini, anotasi @SuppressWarnings harus digunakan, untuk memastikan bahwa semua peringatan mencerminkan masalah aktual dalam kode.

    Jika anotasi @SuppressWarnings diperlukan, anotasi harus diawali dengan komentar TODO yang menjelaskan kondisi "mustahil untuk dihilangkan". Ini biasanya mengidentifikasi kelas yang menyinggung yang memiliki antarmuka yang canggung. Sebagai 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 perangkat lunak tempat anotasi diterapkan.

Perlakukan akronim sebagai kata-kata

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

Bagus Buruk
Permintaan XmlHttp Permintaan XMLHTTP
dapatkanIdPelanggan dapatkanIDPelanggan
kelas HTML kelas HTML
Url string URL string
id panjang ID panjang

Karena basis kode JDK dan Android tidak konsisten terkait akronim, hampir tidak mungkin untuk konsisten dengan kode di sekitarnya. Oleh karena itu, selalu perlakukan akronim sebagai kata-kata.

Gunakan 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 dalam bentuk "Pada tanggal yang akan datang lakukan sesuatu" pastikan Anda menyertakan tanggal tertentu ("Perbaiki pada November 2005") atau peristiwa tertentu ("Hapus kode ini setelah semua mixer produksi memahami protokol V7." ).

Log hemat

Meskipun logging diperlukan, ini berdampak negatif pada kinerja dan kehilangan kegunaannya jika tidak disimpan dengan cukup singkat. Fasilitas logging menyediakan lima tingkat logging yang berbeda:

  • ERROR : Gunakan ketika sesuatu yang fatal telah terjadi, yaitu, sesuatu akan memiliki konsekuensi yang terlihat oleh pengguna dan tidak akan dapat dipulihkan tanpa menghapus beberapa data, mencopot pemasangan aplikasi, menghapus partisi data, atau mem-flash ulang seluruh perangkat (atau lebih buruk lagi). Level ini selalu dicatat. Masalah yang membenarkan beberapa logging di tingkat ERROR adalah kandidat yang baik untuk dilaporkan ke server pengumpulan-statistik.
  • WARNING : Gunakan ketika sesuatu yang serius dan tidak terduga terjadi, yaitu, sesuatu yang akan memiliki konsekuensi yang terlihat oleh pengguna tetapi kemungkinan dapat dipulihkan tanpa kehilangan data dengan melakukan beberapa tindakan eksplisit, mulai dari menunggu atau memulai ulang aplikasi hingga mengunduh ulang versi baru aplikasi atau me-reboot perangkat. Level ini selalu dicatat. Masalah yang membenarkan pencatatan di tingkat WARNING mungkin juga dipertimbangkan untuk pelaporan ke server pengumpulan statistik.
  • INFORMATIVE : Digunakan untuk mencatat bahwa sesuatu yang menarik terjadi, yaitu ketika suatu situasi terdeteksi yang kemungkinan akan berdampak luas, meskipun belum tentu error. Kondisi seperti itu hanya boleh dicatat oleh modul yang percaya bahwa itu adalah yang paling otoritatif di domain itu (untuk menghindari duplikasi logging oleh komponen non-otoritatif). Level ini selalu dicatat.
  • DEBUG : Gunakan untuk mencatat lebih lanjut apa yang terjadi pada perangkat yang mungkin relevan untuk menyelidiki dan men-debug perilaku tak terduga. Catat hanya apa yang diperlukan untuk mengumpulkan informasi yang cukup tentang apa yang terjadi dengan komponen Anda. Jika log debug Anda mendominasi log, maka Anda harus menggunakan verbose logging.

    Level ini dicatat bahkan pada build rilis, dan harus dikelilingi oleh blok if (LOCAL_LOG) atau if LOCAL_LOGD) , di mana LOCAL_LOG[D] didefinisikan di kelas atau subkomponen Anda, sehingga ada kemungkinan untuk menonaktifkan semua logging tersebut . Oleh karena itu, tidak boleh ada logika aktif dalam blok if (LOCAL_LOG) . Semua bangunan string untuk log juga perlu ditempatkan di dalam blok if (LOCAL_LOG) . Jangan memfaktorkan ulang panggilan logging menjadi panggilan metode jika itu akan menyebabkan pembuatan string terjadi di luar blok if (LOCAL_LOG) .

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

  • VERBOSE : Gunakan untuk segala sesuatu yang lain. Level ini hanya dicatat pada build debug dan harus dikelilingi oleh blok if (LOCAL_LOGV) (atau yang setara) sehingga dapat dikompilasi secara default. Setiap bangunan string dikeluarkan dari versi rilis dan perlu muncul di dalam blok if (LOCAL_LOGV) .

Catatan

  • Dalam modul yang diberikan, selain pada tingkat VERBOSE , kesalahan hanya boleh dilaporkan satu kali jika memungkinkan. Dalam satu rantai panggilan fungsi dalam modul, hanya fungsi terdalam yang akan mengembalikan kesalahan, dan pemanggil dalam modul yang sama hanya boleh menambahkan beberapa pencatatan jika itu secara signifikan membantu mengisolasi masalah.
  • Dalam rantai modul, selain di tingkat VERBOSE , ketika modul tingkat yang lebih rendah mendeteksi data yang tidak valid yang berasal dari modul tingkat yang lebih tinggi, modul tingkat yang lebih rendah seharusnya hanya mencatat situasi ini ke log DEBUG , dan hanya jika logging menyediakan informasi yang tidak tersedia untuk pemanggil. Secara khusus, tidak perlu mencatat situasi di mana pengecualian dilemparkan (pengecualian harus berisi semua informasi yang relevan), atau di mana satu-satunya informasi yang dicatat terkandung dalam kode kesalahan. Ini sangat penting dalam interaksi antara framework dan aplikasi, dan kondisi yang disebabkan oleh aplikasi pihak ketiga yang ditangani dengan benar oleh framework tidak boleh memicu logging lebih tinggi dari level DEBUG . Satu-satunya situasi yang seharusnya memicu logging pada level INFORMATIVE atau lebih tinggi adalah ketika modul atau aplikasi mendeteksi kesalahan pada levelnya sendiri atau berasal dari level yang lebih rendah.
  • Ketika kondisi yang biasanya membenarkan beberapa logging kemungkinan terjadi berkali-kali, itu bisa menjadi ide yang baik untuk menerapkan beberapa mekanisme pembatasan tingkat untuk mencegah meluapnya log dengan banyak salinan duplikat dari informasi yang sama (atau sangat mirip).
  • Hilangnya konektivitas jaringan dianggap umum dan diharapkan sepenuhnya, dan tidak boleh dicatat secara serampangan. Hilangnya konektivitas jaringan yang memiliki konsekuensi dalam aplikasi harus dicatat di tingkat DEBUG atau VERBOSE (bergantung pada apakah konsekuensinya cukup serius dan tidak terduga untuk dicatat dalam versi rilis).
  • Memiliki sistem file lengkap pada sistem file yang dapat diakses atau atas nama aplikasi pihak ketiga tidak boleh dicatat pada tingkat yang lebih tinggi dari INFORMATIVE.
  • Data tidak valid yang berasal dari sumber yang tidak tepercaya (termasuk file apa pun di penyimpanan bersama, atau data yang datang melalui koneksi jaringan) dianggap diharapkan dan tidak boleh memicu logging apa pun pada tingkat yang lebih tinggi dari DEBUG saat terdeteksi tidak valid (dan bahkan saat logging harus seminimal mungkin).
  • Saat digunakan pada objek String , operator + secara implisit membuat instance StringBuilder dengan ukuran buffer default (16 karakter) dan kemungkinan objek String sementara lainnya. Jadi secara eksplisit membuat objek StringBuilder tidak lebih mahal daripada mengandalkan operator + default (dan bisa jauh lebih efisien). Ingatlah bahwa kode yang memanggil Log.v() dikompilasi dan dieksekusi pada build rilis, termasuk membuat string, meskipun log tidak sedang dibaca.
  • Setiap logging yang dimaksudkan untuk dibaca oleh orang lain dan tersedia dalam rilis build harus singkat tanpa samar, dan harus dapat dimengerti. Ini termasuk semua masuk ke tingkat DEBUG .
  • Jika memungkinkan, tetap masuk dalam satu baris. Panjang baris hingga 80 atau 100 karakter dapat diterima. Hindari panjang yang lebih panjang dari sekitar 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 pencatatan log sementara untuk mendiagnosis masalah yang sulit untuk direproduksi, pertahankan pada tingkat DEBUG atau VERBOSE dan sertakan dengan blok if yang memungkinkan untuk menonaktifkannya pada waktu kompilasi.
  • Hati-hati dengan kebocoran keamanan melalui log. Hindari mencatat informasi pribadi. Secara khusus, hindari mencatat informasi tentang konten yang dilindungi. Ini sangat penting ketika menulis kode kerangka kerja karena tidak mudah untuk mengetahui sebelumnya apa yang akan dan tidak akan menjadi informasi pribadi atau konten yang dilindungi.
  • Jangan pernah menggunakan System.out.println() (atau printf() untuk kode asli). System.out dan System.err dialihkan ke /dev/null , sehingga pernyataan cetak Anda tidak memiliki efek yang terlihat. Namun, semua pembuatan string yang terjadi untuk panggilan ini masih akan dieksekusi.
  • Aturan utama logging adalah bahwa log Anda mungkin tidak perlu mendorong log lain keluar dari buffer, sama seperti yang lain mungkin tidak mendorong log Anda.

Aturan gaya Javatests

Ikuti konvensi penamaan metode pengujian dan gunakan garis bawah untuk memisahkan apa yang sedang diuji dari kasus tertentu yang sedang diuji. Gaya ini memudahkan untuk melihat kasus mana yang sedang diuji. Sebagai 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))
}