Katkıda bulunanlar için AOSP Java kod stili

Bu sayfadaki kod stilleri, Java kodunu Android Açık Kaynak Projesi'ne (AOSP) katkıda bulunmaya yönelik katı kurallardır. Bu kurallara uymayan Android platformuna yapılan katkılar genel olarak kabul edilmez . Mevcut kodların tamamının bu kurallara uymadığının farkındayız ancak tüm yeni kodların uyumlu olmasını bekliyoruz. Daha kapsayıcı bir ekosistem için kullanılacak ve kaçınılacak terminoloji örnekleri için Kodlama'ya bakın.

Tutarlı ol

En basit kurallardan biri TUTARLI OLMAKTIR. Kodu düzenliyorsanız, çevreleyen koda bakmak ve stilini belirlemek için birkaç dakikanızı ayırın. Eğer bu kod if cümlelerinin etrafında boşluk kullanıyorsa, siz de kullanmalısınız. Kod yorumlarının çevresinde küçük yıldız kutuları varsa, yorumlarınızın da çevresinde küçük yıldız kutuları olmasını sağlayın.

Stil yönergelerine sahip olmanın amacı ortak bir kodlama sözlüğüne sahip olmaktır, böylece okuyucular nasıl söylediğinizden ziyade ne söylediğinize odaklanabilirler. Kelimeleri bilmeniz için global stil kurallarını burada sunuyoruz, ancak yerel stil de önemlidir. Bir dosyaya eklediğiniz kod, etrafındaki mevcut koddan çok farklı görünüyorsa, okuyucuları okurken ritmi bozar. Bundan kaçınmaya çalışın.

Java dili kuralları

Android, aşağıda açıklanan ek kurallarla standart Java kodlama kurallarına uyar.

İstisnaları göz ardı etmeyin

Aşağıdaki gibi istisnaları yok sayan kod yazmak cazip gelebilir:

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

Bunu yapma. Kodunuzun bu hata durumuyla hiçbir zaman karşılaşmayacağını veya bu hatayla baş etmenin önemli olmadığını düşünseniz de, bu tür bir istisnayı göz ardı etmek, kodunuzda bir gün başka birinin tetiklemesi için mayınlar oluşturur. Kodunuzdaki her istisnayı ilkeli bir şekilde ele almalısınız; özel işlem duruma bağlı olarak değişir.

" Ne zaman biri boş bir catch cümlesi duysa, tüyler ürpertici bir duyguya sahip olmalıdır. Bunun aslında yapılacak doğru şey olduğu zamanlar vardır, ama en azından bunun hakkında düşünmelisiniz. Java'da bu tüyler ürpertici duygudan kaçamazsınız. "-James Gosling

Kabul edilebilir alternatifler (tercih sırasına göre):

  • İstisnayı yönteminizi arayana kadar atın.
      void setServerPort(String value) throws NumberFormatException {
          serverPort = Integer.parseInt(value);
      }
    
  • Soyutlama seviyenize uygun yeni bir istisna atın.
      void setServerPort(String value) throws ConfigurationException {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new ConfigurationException("Port " + value + " is not valid.");
        }
      }
    
  • Hatayı dikkatli bir şekilde ele alın ve catch {} bloğunda uygun bir değeri değiştirin.
      /** 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
        }
      }
    
  • İstisnayı yakalayın ve RuntimeException yeni bir örneğini atın. Bu tehlikelidir, bu nedenle bunu yalnızca bu hatanın oluşması durumunda yapılacak en uygun şeyin çökme olduğundan eminseniz yapın.
      /** 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);
        }
      }
    
  • Son çare olarak, istisnayı göz ardı etmenin uygun olacağından eminseniz bunu göz ardı edebilirsiniz ancak bunun nedenini de iyi bir nedenle birlikte yorumlamalısınız.
    /** 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.
        }
    }
    

Genel istisnaları yakalamayın

İstisnaları yakalarken tembel olmak ve şöyle bir şey yapmak cazip gelebilir:

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

Bunu yapma. Neredeyse tüm durumlarda, genel Exception veya Throwable yakalamak uygun değildir ( Error istisnaları içerdiğinden tercihen Throwable değildir). Bu tehlikelidir çünkü hiç beklemediğiniz istisnaların ( ClassCastException gibi çalışma zamanı istisnaları dahil) uygulama düzeyinde hata işlemede yakalandığı anlamına gelir. Bu, kodunuzun hata giderme özelliklerini gizler; yani birisi aradığınız koda yeni bir istisna türü eklerse derleyici, hatayı farklı şekilde ele almanız gerektiğini belirtmeyecektir. Çoğu durumda farklı türde istisnaları aynı şekilde ele almamalısınız.

Bu kuralın nadir istisnası, her türlü hatayı yakalamak istediğiniz (bunların bir kullanıcı arayüzünde görünmesini önlemek veya bir toplu işi çalışır durumda tutmak için) test kodu ve üst düzey koddur. Bu durumlarda, genel Exception (veya Throwable ) yakalayabilir ve hatayı uygun şekilde ele alabilirsiniz. Ancak bunu yapmadan önce dikkatlice düşünün ve bu bağlamda neden güvenli olduğunu açıklayan yorumlarda belirtin.

Genel istisnaları yakalamanın alternatifleri:

  • Çoklu yakalama bloğunun parçası olarak her istisnayı ayrı ayrı yakalayın, örneğin:
    try {
        ...
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        ...
    }
  • Birden fazla deneme bloğuyla daha ayrıntılı hata işleme sağlamak için kodunuzu yeniden düzenleyin. GÇ'yi ayrıştırmadan ayırın ve hataları her durumda ayrı ayrı ele alın.
  • İstisnayı yeniden atın. Çoğu zaman bu seviyedeki istisnayı yakalamanıza gerek yoktur, sadece yöntemin onu atmasına izin verin.

İstisnaların dostunuz olduğunu unutmayın! Derleyici bir istisnayı yakalayamadığınızdan şikayet ettiğinde kaşlarınızı çatmayın. Gülümsemek! Derleyici, kodunuzdaki çalışma zamanı sorunlarını yakalamanızı kolaylaştırdı.

Sonlandırıcıları kullanmayın

Sonlandırıcılar, bir nesne çöp toplandığında bir kod yığınının yürütülmesini sağlamanın bir yoludur. Sonlandırıcılar temizleme için kullanışlı olsa da (özellikle dış kaynaklarda), sonlandırıcının ne zaman çağrılacağına (veya hatta hiç çağrılmayacağına) dair hiçbir garanti yoktur.

Android sonlandırıcıları kullanmaz. Çoğu durumda bunun yerine iyi bir istisna yönetimi kullanabilirsiniz. Kesinlikle bir sonlandırıcıya ihtiyacınız varsa, bir close() yöntemini (veya benzerini) tanımlayın ve bu yöntemin tam olarak ne zaman çağrılması gerektiğini belgeleyin (örnek için bkz . Giriş Akışı ). Bu durumda, günlüklerin taşması beklenmediği sürece sonlandırıcıdan kısa bir günlük mesajı yazdırmak uygundur ancak gerekli değildir.

Tamamen nitelikli ithalat

foo paketinden Bar sınıfını kullanmak istediğinizde, onu içe aktarmanın iki olası yolu vardır:

  • import foo.*;

    İçe aktarma bildirimlerinin sayısını potansiyel olarak azaltır.

  • import foo.Bar;

    Hangi sınıfların kullanıldığını açıkça ortaya koyar ve kodun bakımcılar için daha okunabilir olmasını sağlar.

import foo.Bar; tüm Android kodunu içe aktarmak için. Java standart kitaplıkları ( java.util.* , java.io.* vb.) ve birim test kodu ( junit.framework.* ) için açık bir istisna yapılmıştır.

Java kitaplığı kuralları

Android'in Java kitaplıklarını ve araçlarını kullanmaya ilişkin kurallar vardır. Bazı durumlarda, kural önemli ölçüde değişmiştir ve eski kod, kullanımdan kaldırılmış bir kalıp veya kitaplık kullanıyor olabilir. Böyle bir kodla çalışırken mevcut stile devam etmekte sorun yoktur. Ancak yeni bileşenler oluştururken asla kullanımdan kaldırılmış kütüphaneleri kullanmayın.

Java stili kuralları

Javadoc standart yorumlarını kullanın

Her dosyanın üst kısmında bir telif hakkı bildirimi, ardından paket ve içe aktarma ifadeleri (her blok boş bir satırla ayrılmış) ve son olarak da sınıf veya arayüz bildirimi bulunmalıdır. Javadoc yorumlarında sınıfın veya arayüzün ne yaptığını açıklayın.

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

Yazdığınız her sınıf ve önemsiz olmayan genel yöntem, sınıfın veya yöntemin ne yaptığını açıklayan en az bir cümle içeren bir Javadoc yorumu içermelidir . Bu cümle üçüncü şahıs tanımlayıcı fiille başlamalıdır.

Örnekler

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

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

veya

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

Eğer Javadoc'unuz "sets Foo" diyorsa, setFoo() gibi önemsiz get ve set yöntemleri için Javadoc yazmanıza gerek yoktur. Yöntem daha karmaşık bir şey yapıyorsa (bir kısıtlamayı uygulamak veya önemli bir yan etkiye sahip olmak gibi), o zaman bunu belgelemeniz gerekir. "Foo" özelliğinin ne anlama geldiği açık değilse, bunu belgelemelisiniz.

Herkese açık veya başka şekilde yazdığınız her yöntem Javadoc'tan faydalanacaktır. Genel yöntemler bir API'nin parçasıdır ve bu nedenle Javadoc gerektirir. Android, Javadoc yorumlarını yazmak için belirli bir stil uygulamaz, ancak Javadoc Aracı için Doküman Yorumları Nasıl Yazılır bölümündeki talimatları izlemelisiniz.

Kısa yöntemler yazın

Mümkün olduğunda yöntemleri küçük ve odaklanmış tutun. Uzun yöntemlerin bazen uygun olduğunun farkındayız, bu nedenle yöntem uzunluğuna kesin bir sınır getirilmemektedir. Bir yöntem 40 satırı veya daha fazlasını aşarsa, programın yapısına zarar vermeden bölünüp bölünemeyeceğini düşünün.

Standart yerlerdeki alanları tanımlayın

Alanları dosyanın üst kısmında veya onları kullanan yöntemlerin hemen öncesinde tanımlayın.

Değişken kapsamını sınırla

Yerel değişkenlerin kapsamını minimumda tutun. Bu, kodunuzun okunabilirliğini ve sürdürülebilirliğini artırır ve hata olasılığını azaltır. Her değişkeni, değişkenin tüm kullanımlarını kapsayan en içteki blokta bildirin.

Yerel değişkenleri ilk kullanıldıkları noktada bildirin. Neredeyse her yerel değişken bildirimi bir başlatıcı içermelidir. Bir değişkeni mantıklı bir şekilde başlatmak için henüz yeterli bilgiye sahip değilseniz, bildirimi yapana kadar erteleyin.

Bunun istisnası try-catch ifadeleridir. Bir değişken, kontrol edilen bir istisna atan bir yöntemin dönüş değeriyle başlatılmışsa, bir try bloğu içinde başlatılmalıdır. Değerin try bloğunun dışında kullanılması gerekiyorsa, henüz mantıklı bir şekilde başlatılamadığı try bloğundan önce bildirilmelidir:

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

Ancak try-catch bloğunu bir yöntem içine alarak bu durumu önleyebilirsiniz:

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

Aksini yapmak için zorlayıcı bir neden olmadığı sürece döngü değişkenlerini for ifadesinin kendisinde bildirin:

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

Ve

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

İçe aktarma beyanlarını sipariş etme

İthalat bildirimlerinin sıralaması şöyledir:

  1. Android'den içe aktarmalar
  2. Üçüncü taraflardan yapılan ithalatlar ( com , junit , net , org )
  3. java ve javax

IDE ayarlarıyla tam olarak eşleşmek için içe aktarma işlemleri şöyle olmalıdır:

  • Her gruplamada alfabetik olarak, büyük harfler küçük harflerden önce gelecek şekilde (örneğin, a'dan önce Z)
  • Her ana gruplama arasında boş bir satırla ayrılmıştır ( android , com , junit , net , org , java , javax )

Başlangıçta, sıralamada herhangi bir stil gereksinimi yoktu; bu, IDE'lerin ya her zaman sıralamayı değiştirdiği ya da IDE geliştiricilerinin otomatik içe aktarma yönetimi özelliklerini devre dışı bırakmak ve içe aktarmaları manuel olarak sürdürmek zorunda kaldığı anlamına gelir. Bu kötü kabul edildi. Java stili sorulduğunda, tercih edilen stiller çılgınca değişiyordu ve Android'in "bir sıralama seçip tutarlı olması" gerekiyordu. Biz de bir stil seçtik, stil kılavuzunu güncelledik ve IDE'lerin buna uymasını sağladık. IDE kullanıcıları kod üzerinde çalışırken, tüm paketlerdeki içe aktarmaların ekstra mühendislik çabası gerektirmeden bu modele uymasını bekliyoruz.

Bu stili şu şekilde seçtik:

  • İnsanların ilk önce bakmak istedikleri ithalatlar genellikle en üstte ( android ) yer alır.
  • İnsanların en azından bakmak istedikleri ithalatlar en altta ( java ) olma eğilimindedir.
  • İnsanlar tarzı kolaylıkla takip edebilirler.
  • IDE'ler stili takip edebilir.

Statik içe aktarmaları, normal içe aktarmalarla aynı şekilde sıralanan diğer tüm içe aktarmaların üstüne koyun.

Girinti için boşluk kullanın

Bloklar için dört (4) boşluk girintisi kullanıyoruz ve asla sekme kullanmıyoruz. Şüpheye düştüğünüzde çevredeki kodlarla tutarlı olun.

Satır kaydırmalar için, işlev çağrıları ve atamalar da dahil olmak üzere sekiz (8) boşluk girintisi kullanırız.

Tavsiye edilen

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

Tavsiye edilmez

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

Alan adlandırma kurallarına uyun

  • Genel olmayan, statik olmayan alan adları m ile başlar.
  • Statik alan adları s ile başlar.
  • Diğer alanlar küçük harfle başlar.
  • Statik son alanlar (sabitler, derinlemesine değişmez) ALL_CAPS_WITH_UNDERSCORES .

Örneğin:

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

Standart ayraç stilini kullan

Parantezleri kendi satırlarına değil, önlerindeki kodla aynı satıra koyun:

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

Koşullu ifadeler için ifadelerin etrafına parantez koymamız gerekir. İstisna: Koşulun tamamı (koşul ve gövde) tek bir satıra sığıyorsa, hepsini tek bir satıra koyabilirsiniz (ancak zorunlu değilsiniz). Örneğin, bu kabul edilebilir:

if (condition) {
    body();
}

ve bu kabul edilebilir:

if (condition) body();

ama bu kabul edilemez:

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

Hat uzunluğunu sınırla

Kodunuzdaki her metin satırı en fazla 100 karakter uzunluğunda olmalıdır. Bu kuralın etrafında çok fazla tartışma olmasına rağmen, aşağıdaki istisnalar dışında maksimum 100 karakter olduğu kararı devam etmektedir:

  • Bir yorum satırı örnek bir komut veya 100 karakterden uzun bir gerçek URL içeriyorsa, kesme ve yapıştırma kolaylığı için bu satır 100 karakterden uzun olabilir.
  • İçe aktarma satırları sınırı aşabilir çünkü insanlar bunları nadiren görür (bu aynı zamanda araç yazmayı da kolaylaştırır).

Standart Java ek açıklamalarını kullanın

Ek açıklamalar aynı dil öğesi için diğer değiştiricilerden önce gelmelidir. Basit işaretleyici açıklamaları (örneğin, @Override ) dil öğesiyle aynı satırda listelenebilir. Birden fazla ek açıklama veya parametreli ek açıklamalar varsa, bunları her satırda bir tane olmak üzere alfabetik sıraya göre listeleyin.

Java'da önceden tanımlanmış üç ek açıklama için Android standart uygulamaları şunlardır:

  • Açıklamalı öğenin kullanımı önerilmediğinde @Deprecated ek açıklamasını kullanın. @Deprecated ek açıklamasını kullanırsanız, ayrıca bir @deprecated Javadoc etiketine sahip olmanız ve bunun alternatif bir uygulamayı adlandırması gerekir. Ayrıca, @Deprecated yönteminin hala çalışması gerektiğini unutmayın. @deprecated Javadoc etiketine sahip eski bir kod görürseniz @Deprecated ek açıklamasını ekleyin.
  • Bir yöntem bir üst sınıfın bildirimini veya uygulamasını geçersiz kıldığında @Override ek açıklamasını kullanın. Örneğin, @inheritdocs Javadoc etiketini kullanıyorsanız ve bir sınıftan (arabirimden değil) türetiyorsanız, yöntemin üst sınıfın yöntemini geçersiz kıldığını da belirtmeniz gerekir.
  • @SuppressWarnings ek açıklamasını yalnızca bir uyarıyı ortadan kaldırmanın imkansız olduğu durumlarda kullanın. Bir uyarı bu "ortadan kaldırılması imkansız" testini geçerse, tüm uyarıların koddaki gerçek sorunları yansıttığından emin olmak için @SuppressWarnings ek açıklaması kullanılmalıdır .

    @SuppressWarnings ek açıklaması gerekli olduğunda, "ortadan kaldırılması imkansız" koşulunu açıklayan bir TODO açıklamasının önüne eklenmelidir. Bu normalde garip bir arayüze sahip rahatsız edici bir sınıfı tanımlar. Örneğin:

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

    @SuppressWarnings ek açıklaması gerektiğinde, ek açıklamanın uygulandığı yazılım öğelerini izole etmek için kodu yeniden düzenleyin.

Kısaltmaları kelime olarak ele alın

Adları daha okunaklı hale getirmek için değişkenleri, yöntemleri ve sınıfları adlandırırken kısaltmaları ve kısaltmaları sözcük olarak kullanın:

İyi Kötü
XmlHttpRequest XMLHTTPİsteği
Müşteri Kimliğini al Müşteri Kimliğini al
sınıf Html sınıf HTML'si
Dize URL'si Dize URL'si
uzun kimlik uzun kimlik

Hem JDK hem de Android kod tabanları kısaltmalar konusunda tutarsız olduğundan, çevreleyen kodla tutarlı olmak neredeyse imkansızdır. Bu nedenle kısaltmaları her zaman kelime olarak değerlendirin.

TODO yorumlarını kullan

Geçici, kısa vadeli bir çözüm olan veya yeterince iyi ancak mükemmel olmayan kodlar için TODO yorumlarını kullanın. Bu yorumların tümü büyük harflerle TODO dizesini ve ardından iki nokta üst üste işareti içermelidir:

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

Ve

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

TODO "Gelecek bir tarihte bir şeyler yapın" biçimindeyse, belirli bir tarihi ("Kasım 2005'e kadar düzeltin") veya belirli bir olayı ("Tüm üretim karıştırıcıları V7 protokolünü anladıktan sonra bu kodu kaldırın") eklediğinizden emin olun. ).

Tasarruflu bir şekilde oturum açın

Günlük kaydı gerekli olsa da, performans üzerinde olumsuz bir etkiye sahiptir ve makul ölçüde kısa tutulmazsa kullanışlılığını kaybeder. Günlük kaydı olanakları beş farklı düzeyde günlük kaydı sağlar:

  • ERROR : Ölümcül bir şey olduğunda, yani bir şeyin kullanıcı tarafından görülebilecek sonuçları olacağı ve bazı verileri silmeden, uygulamaları kaldırmadan, veri bölümlerini silmeden veya cihazın tamamını yeniden başlatmadan (veya daha kötüsü) kurtarılamayacağı durumlarda kullanın. Bu seviye her zaman günlüğe kaydedilir. ERROR seviyesinde bazı kayıtların tutulmasını haklı çıkaran sorunlar, bir istatistik toplama sunucusuna rapor edilmek için iyi adaylardır.
  • WARNING : Ciddi ve beklenmedik bir şey olduğunda, yani kullanıcının görebileceği sonuçlar doğuracak ancak bir uygulamayı beklemek veya yeniden başlatmaktan yeniden indirmeye kadar uzanan açık bir işlem gerçekleştirerek veri kaybı olmadan kurtarılması muhtemel bir şey olduğunda kullanın. bir uygulamanın yeni bir sürümü veya cihazın yeniden başlatılması. Bu seviye her zaman günlüğe kaydedilir. WARNING düzeyinde günlüğe kaydetmeyi haklı kılan sorunlar, bir istatistik toplama sunucusuna rapor vermek için de düşünülebilir.
  • INFORMATIVE : İlginç bir şeyin gerçekleştiğini not etmek için kullanın; yani, mutlaka bir hata olmasa da geniş çapta etki yaratması muhtemel bir durum tespit edildiğinde. Böyle bir koşulun yalnızca söz konusu etki alanındaki en yetkili modül olduğuna inanan bir modül tarafından günlüğe kaydedilmesi gerekir (yetkili olmayan bileşenler tarafından yinelenen günlük kaydının önlenmesi için). Bu seviye her zaman günlüğe kaydedilir.
  • DEBUG : Beklenmeyen davranışları araştırmak ve hata ayıklamak için cihazda neler olup bittiğini daha ayrıntılı olarak not etmek için kullanın. Yalnızca bileşeninizde olup bitenler hakkında yeterli bilgi toplamak için gerekenleri günlüğe kaydedin. Hata ayıklama günlükleriniz günlüğe hakimse ayrıntılı günlük kaydı kullanmalısınız.

    Bu düzey sürüm sürümlerinde bile günlüğe kaydedilir ve bir if (LOCAL_LOG) veya if LOCAL_LOGD) bloğuyla çevrelenmesi gerekir; burada LOCAL_LOG[D] sınıfınızda veya alt bileşeninizde tanımlanır, böylece tüm bu tür günlüğe kaydetmeyi devre dışı bırakma olasılığı vardır . Bu nedenle if (LOCAL_LOG) bloğunda aktif bir mantık olmamalıdır. Günlüğe ilişkin tüm dize yapısının da if (LOCAL_LOG) bloğunun içine yerleştirilmesi gerekir. Dize oluşturmanın if (LOCAL_LOG) bloğunun dışında gerçekleşmesine neden olacaksa, günlüğe kaydetme çağrısını bir yöntem çağrısına yeniden düzenlemeyin.

    Hala if (localLOGV) diyen bazı kodlar var. Adı standart olmasa da bu da kabul edilebilir olarak kabul edilir.

  • VERBOSE : Diğer her şey için kullanın. Bu düzey yalnızca hata ayıklama yapılarında günlüğe kaydedilir ve varsayılan olarak derlenebilmesi için bir if (LOCAL_LOGV) bloğu (veya eşdeğeri) ile çevrelenmesi gerekir. Herhangi bir dize yapısı, sürüm yapılarından çıkarılır ve if (LOCAL_LOGV) bloğunun içinde görünmesi gerekir.

Notlar

  • Belirli bir modül içinde, VERBOSE düzeyi dışında, bir hata mümkünse yalnızca bir kez rapor edilmelidir. Bir modül içindeki tek bir işlev çağrıları zincirinde, yalnızca en içteki işlev hatayı döndürmelidir ve aynı modüldeki arayanlar, yalnızca sorunun yalıtılmasına önemli ölçüde yardımcı olması durumunda bir miktar günlük kaydı eklemelidir.
  • VERBOSE düzeyi dışındaki bir modül zincirinde, alt düzey bir modül, üst düzey bir modülden gelen geçersiz verileri tespit ettiğinde, alt düzey modül bu durumu yalnızca DEBUG günlüğüne kaydetmelidir ve yalnızca günlük kaydının sağlanması durumunda başka türlü arayan kişinin erişemeyeceği bilgiler. Özellikle, bir istisnanın oluştuğu (istisnanın ilgili tüm bilgileri içermesi gerekir) veya günlüğe kaydedilen tek bilginin bir hata kodunda yer aldığı durumları günlüğe kaydetmeye gerek yoktur. Bu, özellikle çerçeve ile uygulamalar arasındaki etkileşimde önemlidir ve çerçeve tarafından uygun şekilde işlenen üçüncü taraf uygulamaların neden olduğu koşullar, günlüğe kaydetme işleminin DEBUG düzeyinden daha yüksek olmasını tetiklememelidir. INFORMATIVE düzeyde veya daha yüksek düzeyde günlüğe kaydetmeyi tetiklemesi gereken tek durum, bir modülün veya uygulamanın kendi düzeyinde veya daha düşük bir düzeyden gelen bir hata tespit etmesidir.
  • Normalde bazı günlüğe kaydetmeyi haklı çıkaracak bir koşulun birçok kez meydana gelmesi muhtemel olduğunda, günlüklerin aynı (veya çok benzer) bilgilerin birçok kopya kopyasıyla taşmasını önlemek için bazı hız sınırlayıcı mekanizmalar uygulamak iyi bir fikir olabilir.
  • Ağ bağlantısı kayıpları yaygın olarak kabul edilir ve tamamen beklenen bir durumdur ve gereksiz yere günlüğe kaydedilmemelidir. Bir uygulama içinde sonuçları olan bir ağ bağlantısı kaybı, DEBUG veya VERBOSE düzeyinde günlüğe kaydedilmelidir (sonuçların yeterince ciddi olup olmadığına ve bir sürüm yapısında günlüğe kaydedilecek kadar beklenmedik olup olmadığına bağlı olarak).
  • Üçüncü taraf uygulamaların erişebildiği veya onlar adına erişilebilen bir dosya sisteminde tam bir dosya sistemine sahip olmak, BİLGİLENDİRME düzeyinden daha yüksek bir düzeyde günlüğe kaydedilmemelidir.
  • Güvenilmeyen herhangi bir kaynaktan gelen geçersiz veriler (paylaşılan depolama alanındaki herhangi bir dosya veya bir ağ bağlantısı üzerinden gelen veriler dahil) beklenen kabul edilir ve geçersiz olduğu tespit edildiğinde DEBUG daha yüksek bir düzeyde herhangi bir günlük kaydı tetiklememelidir (ve hatta bu durumda günlüğe kaydetme yapılmalıdır) mümkün olduğu kadar sınırlı olmalıdır).
  • + operatörü, String nesnelerinde kullanıldığında, varsayılan arabellek boyutuna (16 karakter) ve potansiyel olarak diğer geçici String nesnelerine sahip, örtülü olarak bir StringBuilder örneği oluşturur. Yani açıkça StringBuilder nesneleri oluşturmak, varsayılan + operatörüne güvenmekten daha pahalı değildir (ve çok daha verimli olabilir). Log.v() öğesini çağıran kodun, günlükler okunmuyor olsa bile dizelerin oluşturulması da dahil olmak üzere yayın sürümlerinde derlendiğini ve yürütüldüğünü unutmayın.
  • Başkaları tarafından okunması ve sürüm yapılarında mevcut olması amaçlanan herhangi bir günlük kaydı, şifreli olmadan kısa ve anlaşılır olmalıdır. Bu, DEBUG düzeyine yapılan tüm oturum açma işlemlerini içerir.
  • Mümkün olduğunda tek bir satırda oturum açmaya devam edin. 80 veya 100 karaktere kadar satır uzunlukları kabul edilebilir. Mümkünse yaklaşık 130 veya 160 karakterden (etiketin uzunluğu dahil) daha uzun olan uzunluklardan kaçının.
  • Günlüğe kaydetme başarılı olduğunu bildirirse, asla VERBOSE daha yüksek düzeylerde kullanmayın.
  • Yeniden oluşturulması zor bir sorunu teşhis etmek için geçici günlük kaydı kullanıyorsanız, bunu DEBUG veya VERBOSE düzeyinde tutun ve derleme zamanında devre dışı bırakılmasına izin veren if blokları içine alın.
  • Günlük yoluyla güvenlik sızıntılarına karşı dikkatli olun. Özel bilgileri günlüğe kaydetmekten kaçının. Özellikle korumalı içerikle ilgili bilgileri günlüğe kaydetmekten kaçının. Neyin özel bilgi veya korumalı içerik olacağını önceden bilmek kolay olmadığından, çerçeve kodu yazarken bu özellikle önemlidir.
  • Asla System.out.println() (veya yerel kod için printf() ) işlevini kullanmayın. System.out ve System.err , /dev/null yönlendirilir, böylece print ifadelerinizin görünür bir etkisi olmaz. Ancak bu çağrılar için gerçekleşen tüm dizi oluşturma işlemleri yine de yürütülür.
  • Günlüğe kaydetmenin altın kuralı, başkalarının sizinkini dışarı itemeyeceği gibi, günlüklerinizin de diğer günlükleri gereksiz yere arabelleğin dışına itmemesidir.

Javatest stil kuralları

Test yöntemi adlandırma kurallarına uyun ve test edileni, test edilen özel durumdan ayırmak için bir alt çizgi kullanın. Bu stil, hangi vakaların test edildiğini görmeyi kolaylaştırır. Örneğin:

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