סגנון קוד Java של AOSP לתורמים

סגנונות הקוד בדף זה הם כללים נוקשים לתרומת קוד ג'אווה לפרויקט קוד פתוח של Android (AOSP). תרומות לפלטפורמת אנדרואיד שאינם מצייתים לכללים אלה בדרך כלל אינם מתקבלים. אנו מכירים בכך שלא כל הקוד הקיים עומד בכללים אלה, אך אנו מצפים שכל הקוד החדש יהיה תואם. ראה Coding ביחס לדוגמאות של המינוח להשתמש ולהימנע עבור מערכת אקולוגית כוללני יותר.

היה עקבי

אחד הכללים הפשוטים ביותר הוא להיות עקבי. אם אתה עורך קוד, הקדש מספר דקות לבחון את הקוד שמסביב ולקבוע את סגנונו. אם קוד המשתמש מקומות ברחבי if הסעיפים, אתה צריך גם. אם להערות הקוד יש קופסאות כוכבים קטנות סביבן, גרמו להערות שלכם להיות קופסאות קטנות של כוכבים מסביב.

הנקודה שיש להנחיות בסגנון היא שיהיה אוצר מילים משותף של קידוד, כך שהקוראים יוכלו להתרכז במה שאתה אומר, ולא באופן שאתה אומר את זה. אנו מציגים כאן כללי סגנון עולמיים כך שתכיר את אוצר המילים, אך גם סגנון מקומי חשוב. אם הקוד שאתה מוסיף לקובץ נראה שונה באופן דרסטי מהקוד הקיים סביבו, הוא מוציא את הקוראים מהקצב כאשר הם קוראים אותו. נסה להימנע מכך.

כללי שפת Java

Android פועל בהתאם למוסכמות קידוד סטנדרטיות של Java עם הכללים הנוספים המתוארים להלן.

אל תתעלם מחריגים

זה יכול להיות מפתה לכתוב קוד שמתעלם מחריגה, כגון:

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

אל תעשה זאת. למרות שאתה עשוי לחשוב שהקוד שלך לעולם לא יתקל במצב שגיאה זה או שלא חשוב לטפל בו, התעלמות מסוג חריגים זה יוצרת מוקשים בקוד שלך כדי שמישהו אחר יפעיל יום אחד. עליך להתייחס לכל חריג בקוד שלך באופן עקרוני; הטיפול הספציפי משתנה בהתאם למקרה.

"מישהו פעם יש סעיף לתפוס ריק שהם צריכים הרגשה מחורבנת. בהחלט יש פעמים כאשר הוא בעצם הדבר הנכון לעשות, אבל לפחות אתה צריך לחשוב על זה. ב- Java אתה לא יכול לברוח ההרגשה המצמררת. "- ג'יימס גוסלינג

חלופות מקובלות (לפי סדר עדיפות) הן:

  • שלח את החריג למתקשר של השיטה שלך.
      void setServerPort(String value) throws NumberFormatException {
          serverPort = Integer.parseInt(value);
      }
    
  • זרוק חריג חדש המתאים לרמת ההפשטה שלך.
      void setServerPort(String value) throws ConfigurationException {
        try {
            serverPort = Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new ConfigurationException("Port " + value + " is not valid.");
        }
      }
    
  • טפל השגיאה בחנתי להחליף ערך מתאים 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
        }
      }
    
  • תפוס למעט ולזרוק מופע חדש של RuntimeException . זה מסוכן, אז עשה זאת רק אם אתה בטוח שאם שגיאה זו מתרחשת, הדבר המתאים לעשות הוא לקרוס.
      /** 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);
        }
      }
    
  • כמוצא אחרון, אם אתה בטוח שהתעלמות מהחריג היא ראויה, תוכל להתעלם ממנו, אך עליך גם להגיב מדוע עם סיבה טובה.
    /** 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.
        }
    }
    

אל תתפסו יוצאים מן הכלל

זה יכול להיות מפתה להתעצל כשאתה תופס יוצאים מן הכלל ועושה משהו כזה:

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

אל תעשה זאת. כמעט בכול מקרים, זה לא מתאים לתפוס הגנרית Exception או Throwable (רצוי לא Throwable משום שהיא כוללת Error חריגה). זה מסוכן כי זה אומר חריגים אתה אף פעם לא צפוי (כולל חריגים ריצה כמו ClassCastException ) להיתפס טיפול בשגיאות ברמת היישום. זה מטשטש את תכונות הטיפול בכשל בקוד שלך, כלומר אם מישהו מוסיף סוג חדש של חריגה בקוד שאליו אתה מתקשר, המהדר לא יציין שאתה צריך לטפל בשגיאה אחרת. ברוב המקרים אתה לא אמור להתמודד עם סוגים שונים של חריגים באותו אופן.

היוצא מן הכלל הנדיר לכלל זה הוא קוד בדיקה וקוד ברמה העליונה שבהם ברצונך לתפוס כל מיני שגיאות (כדי למנוע מהן להופיע בממשק משתמש, או כדי להריץ עבודת אצווה). במקרים אלה, ייתכן לתפוס הגנרית Exception (או Throwable ) ולטפל השגיאה כראוי. עם זאת, חשוב היטב לפני שאתה עושה זאת והכנס הערות המסבירות מדוע זה בטוח בהקשר זה.

חלופות לתפיסת חריגים גנריים:

  • לתפוס כל פרט בנפרד כחלק בלוק רב לתפוס, למשל:
    try {
        ...
    } catch (ClassNotFoundException | NoSuchMethodException e) {
        ...
    }
  • בצע מחדש את הקוד שלך כדי לקבל טיפול שגיאות עדין יותר, עם מספר בלוקים של ניסיון. חלוק את ה- IO מהניתוח, ועסק בשגיאות בנפרד בכל מקרה ומקרה.
  • חזור על החריג. הרבה פעמים בכל מקרה אתה לא צריך לתפוס את החריג ברמה הזו, פשוט תן לשיטה לזרוק אותו.

זכור שחריגים הם החבר שלך! כאשר המהדר מתלונן שאתה לא תופס יוצא מן הכלל, אל תזיין. חיוך! המהדר פשוט הקל עליך לתפוס בעיות זמן ריצה בקוד שלך.

אל תשתמש בגמר

מכשירי גמר הם דרך להפעיל נתח קוד כאשר אובייקט נאסף באשפה. למרות שסיימי הגמר יכולים להיות נוחים לניקוי (במיוחד למשאבים חיצוניים), אין אחריות מתי ייקרא לגמר (או אפילו שהוא ייקרא בכלל).

אנדרואיד אינה משתמשת בגמרים. ברוב המקרים, תוכל להשתמש בטיפול חריג טוב במקום זאת. אם אתה ממש צריך Finalizer, להגדיר close() שיטה (או וכדומה) וכן מסמך בדיוק כאשר הצרכים שיטה להיקרא (ראה InputStream לדוגמא). במקרה זה, ראוי אך לא חובה להדפיס הודעת יומן קצרה מהגמר, כל עוד לא צפוי להציף את יומני היומן.

ייבוא ​​מלא

כאשר אתה רוצה להשתמש בכיתה Bar מהאריזה foo , ישנן שתי דרכים אפשריות כדי לייבא אותו:

  • import foo.*;

    מקטין באופן פוטנציאלי את מספר הצהרות היבוא.

  • import foo.Bar;

    מבהיר באילו שיעורים משתמשים והקוד קריא יותר עבור מתחזקים.

השתמש import foo.Bar; לייבוא ​​כל קוד אנדרואיד. חריג מפורש נעשה עבור ספריות סטנדרטיות ג'אווה ( java.util.* , java.io.* , וכו ') ואת קוד בדיקה יחידה ( junit.framework.* ).

חוקי ספריית ג'אווה

ישנן מוסכמות לשימוש בספריות ובכלים של אנדרואיד. במקרים מסוימים, האמנה השתנתה בדרכים חשובות וקוד ישן עשוי להשתמש בדפוס או בספרייה שהוצא משימוש. כאשר עובדים עם קוד כזה, זה בסדר להמשיך את הסגנון הקיים. אולם בעת יצירת רכיבים חדשים, לעולם אל תשתמש בספריות שהוצאו משימוש.

כללי סגנון ג'אווה

השתמש בהערות סטנדרטיות של Javadoc

כל קובץ צריך להיות בעל הצהרת זכויות יוצרים בראש, ואחריו הצהרות חבילה ויבוא (כל בלוק מופרד בשורה ריקה), ולבסוף הצהרת המחלקה או הממשק. בהערות Javadoc, תאר מה עושה הכיתה או הממשק.

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

כל הכיתה ושיטת הציבור טריוויאלי שאתה כותב חייב לכלול תגובה Javadoc עם לפחות משפט אחד המתאר את מה הכיתה או השיטה עושה. משפט זה צריך להתחיל בפועל תיאור של גוף שלישי.

דוגמאות

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

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

אוֹ

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

אתה לא צריך Javadoc כתיבה עבור שיטות להגיע ולהגדיר טריוויאלי כגון setFoo() אם כל Javadoc שלך היה אומר הוא "סטים Foo". אם השיטה עושה משהו מורכב יותר (כגון אכיפת אילוץ או שיש לה תופעת לוואי חשובה), עליך לתעד זאת. אם לא ברור מה המשמעות של הנכס "פו", עליך לתעד אותו.

כל שיטה שאתה כותב, ציבורית או אחרת, תרוויח מ- Javadoc. שיטות ציבוריות הן חלק ממשק API ולכן הן דורשות Javadoc. אנדרואיד לא לאכוף סגנון ספציפי לכתיבת הערות Javadoc, אבל אתה צריך לבצע את ההוראות כיצד לכתוב תגובות דוק עבור כלי Javadoc .

כתוב שיטות קצרות

במידת האפשר, שמור על שיטות קטנות וממוקדות. אנו מכירים בכך שלפעמים שיטות ארוכות מתאימות, ולכן אין הגבלה קשה על אורך השיטה. אם שיטה עולה על 40 שורות בערך, חשבו האם ניתן לפרק אותה מבלי לפגוע במבנה התוכנית.

הגדר שדות במקומות סטנדרטיים

הגדר שדות בחלק העליון של הקובץ או מיד לפני השיטות שמשתמשות בהם.

הגבל היקף משתנה

צמצם את היקף המשתנים המקומיים למינימום. זה מגביר את הקריאות והתחזוקה של הקוד שלך ומפחית את הסיכוי לטעות. הכריז על כל משתנה בבלוק הפנימי ביותר המקיף את כל השימושים של המשתנה.

הצהיר על משתנים מקומיים בנקודה שבה נעשה בהם שימוש ראשון. כמעט כל הצהרת משתנה מקומי צריכה להכיל אתחול. אם עדיין אין לך מספיק מידע לאתחול משתנה בצורה הגיונית, דחה את ההצהרה עד שתעשה זאת.

היוצא מן הכלל הוא הצהרות נסיונות. אם משתנה מאתחל עם ערך ההחזרה של שיטה שזורקת חריג מסומן, יש לאתחל אותו בתוך בלוק נסיון. אם יש להשתמש בערך מחוץ לגוש הניסיון, יש להכריז עליו לפני בלוק הניסיון, שם עדיין לא ניתן לאתחל אותו בצורה הגיונית:

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

עם זאת, אתה יכול אפילו להימנע ממקרה זה על ידי כיתוב בלוק הניסיונות לתפוס בשיטה:

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

הצהיר על משתני לולאה בהצהרה עצמה אלא אם יש סיבה משכנעת לעשות אחרת:

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

ו

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

הזמנת הצהרות יבוא

הזמנת הצהרות היבוא היא:

  1. ייבוא ​​אנדרואיד
  2. יבוא מצדדים שלישיים ( com , junit , net , org )
  3. java ו- javax

כדי להתאים בדיוק את הגדרות IDE, הייבוא ​​צריך להיות:

  • אלפביתי בתוך כל קיבוץ, עם אותיות גדולות לפני אותיות קטנות (למשל Z לפני א)
  • מופרדים על ידי קו ריק בין קיבוץ מרכזי ( android , com , junit , net , org , java , javax )

במקור, לא הייתה דרישת סגנון להזמנה, כלומר IDE תמיד שינו את ההזמנה או שמפתחי IDE היו צריכים להשבית את תכונות ניהול הייבוא ​​האוטומטי ולשמור באופן ידני על הייבוא. הדבר נחשב גרוע. כשנשאל בסגנון ג'אווה, הסגנונות המועדפים השתנו מאוד וזה הגיע לאנדרואיד שצריך פשוט "לבחור הזמנה ולהיות עקבי". אז בחרנו סגנון, עדכנו את מדריך הסגנונות וגרמנו למנהלי ה- IDE לציית לו. אנו מצפים שככל שמשתמשי IDE עובדים על הקוד, היבוא בכל החבילות יתאים לדפוס הזה ללא מאמץ הנדסי נוסף.

בחרנו בסגנון זה כך:

  • מייבא שאנשים רוצים להסתכל הראשונה נוטה להיות בחלק העליון ( android ).
  • מייבאת שאנשים רוצים להיראות לפחות נוטים להיות בתחתית ( java ).
  • בני אדם יכולים לעקוב בקלות אחר הסגנון.
  • IDEs יכולים לעקוב אחר הסגנון.

שים יבוא סטטי מעל כל שאר היבוא שהוזמן באותו אופן כמו יבוא רגיל.

השתמש ברווחים לצורך הזחה

אנו משתמשים בארבעה (4) כניסות שטח לבלוקים ולעולם לא בכרטיסיות. במקרה של ספק, היו עקביים עם הקוד שמסביב.

אנו משתמשים בשמונה (8) כניסות שטח לעטיפות קווים, כולל שיחות פונקציות והקצאות.

מוּמלָץ

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

לא מומלץ

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

עקוב אחר מוסכמות שמות השדות

  • שאינו ציבורי, שאינו סטטי שמות שדות להתחיל עם m .
  • שמות שדות סטטי להתחיל עם s .
  • שדות אחרים מתחילים באות קטנה.
  • שדות סופיים ציבוריים סטטי (קבוע) הם ALL_CAPS_WITH_UNDERSCORES .

לדוגמה:

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

השתמש בסגנון סד סטנדרטי

שים פלטה על אותה קו כמו הקוד שלפניהם, לא על השורה שלהם:

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

אנו דורשים פלטה סביב ההצהרות לצורך תנאי. יוצא מן הכלל: אם כל התנאי (המצב והגוף) מתאים לקו אחד, אתה יכול (אך אינך מחויב) לשים את הכל על שורה אחת. לדוגמה, זה מקובל:

if (condition) {
    body();
}

וזה מקובל:

if (condition) body();

אבל זה לא מקובל:

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

הגבל את אורך הקו

כל שורת טקסט בקוד שלך צריכה להיות באורך לכל היותר 100 תווים. בעוד הדיון הרבה הקיף את הכלל הזה, ההחלטה נשארת כי 100 תווים המקסימום עם החריגים הבאים:

  • אם שורת הערה מכילה פקודה לדוגמה או כתובת URL מילולית שאורכה יותר מ -100 תווים, שורה זו עשויה להיות ארוכה מ -100 תווים כדי להקל על הגזירה וההדבקה.
  • קווי ייבוא ​​יכולים לעבור את הגבול מכיוון שבני אדם רואים אותם לעתים רחוקות (זה גם מפשט את כתיבת הכלים).

השתמש בהערות Java סטנדרטיות

ביאורים צריכים להקדים שינויים אחרים לאותו רכיב שפה. הסברים סמן פשוטים (למשל, @Override ) יכול להיות רשום על אותו קו עם אלמנט השפה. אם יש ביאורים מרובים, או הערות פרמטריות, רשום אותן אחת לשורה בסדר אלפביתי.

שיטות סטנדרטיות של Android לשלושת ההערות המוגדרות מראש ב- Java הן:

  • השתמש @Deprecated ביאור בכל פעם את השימוש באלמנט המבואר הוא מיואש. אם אתה משתמש @Deprecated ביאור, אתה חייב להיות גם @deprecated תג Javadoc וזה צריך לנקוב יישום חלופי. בנוסף, יש לזכור כי @Deprecated שיטה עדיין אמורה לעבוד. אם אתה רואה את קוד ישן כי יש @deprecated תג Javadoc, להוסיף את @Deprecated ביאור.
  • השתמש @Override ביאור בכל פעם שיטה עוקפת את ההצהרה או יישום של העל. לדוגמא, אם אתה משתמש @inheritdocs תג Javadoc, ונובע בכיתה (לא ממשק), אתה חייב גם לכתוב הערות שהשיטה עוקפת את שיטת ההורה של הכיתה.
  • השתמש @SuppressWarnings ביאור רק בנסיבות שבהן אי אפשר לחסל אזהרה. אם אזהרה עובר זה "בלתי אפשרי לחסל" המבחן, @SuppressWarnings ביאור חייב לשמש, כדי להבטיח כי כל האזהרות משקפות בעיות בפועל בקוד.

    כאשר @SuppressWarnings סבר הנו הכרחי, זה חייב להופיע עם TODO תגובה המסבירה את "אי אפשר לחסל" מצבו. בדרך כלל זה מזהה מעמד פוגע שיש לו ממשק מביך. לדוגמה:

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

    כאשר @SuppressWarnings ביאור נדרש, לארגן מחדש את הקוד כדי לבודד את מרכיבי התוכנה שבה הביאור חל.

התייחסו לראשי תיבות כמילים

התייחסו לראשי תיבות וקיצורים כמילים במתן משתני שמות, שיטות ומחלקות כדי להפוך את השמות לקריאים יותר:

טוֹב רַע
XmlHttpRequest בקשת XMLHTTP
getCustomerId getCustomerID
כיתת HTML HTML בכיתה
כתובת אתר מחרוזת כתובת URL של מחרוזת
מזהה ארוך תעודת זהות ארוכה

מכיוון שבסיסי הקוד של JDK וגם אנדרואיד אינם עקביים סביב ראשי תיבות, כמעט בלתי אפשרי להיות עקבי עם הקוד שמסביב. לכן, תמיד התייחסו לראשי תיבות כמילים.

השתמש בהערות TODO

השתמש TODO הערות עבור קוד זה זמני, פתרון לטווח קצר, או מספיק טוב אבל לא מושלם. הערות אלו צריכות לכלול את המחרוזת TODO בכל כובעים, ולאחריו נקודתיים:

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

ו

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

אם שלך TODO הוא מהצורה "בתאריך עתידי לעשות משהו" לוודא כי אתה גם לכלול תאריך ספציפי ( "Fix עד נובמבר 2005") או אירוע מסוים ( "הסר את הקוד הזה אחרי כל מערבלי הייצור להבין V7 פרוטוקול." ).

היכנס במשורה

אף על פי שיש צורך בכריתת הרישום, יש לו השפעה שלילית על הביצועים ומאבד את התועלת שלו אם לא שומרים על צמצום סביר. מתקני הכריסה מספקים חמש רמות שונות של כריתה:

  • ERROR : השתמש כשמשהו קטלני קרה, כלומר, משהו, יהיה לכך השלכות גלוי למשתמש ולא יהיה השבה מבלי למחוק נתונים מסוימים, סרה של יישומים, מנגבים את מחיצות נתונים, או reflashing את המכשיר כול (או גרוע). רמה זו תמיד נרשמת. סוגיות מצדיקות כמה ורישום בבית ERROR הרמה הם מועמדים טובים ידווחו לשרת סטטיסטיקת איסוף.
  • WARNING : שימוש כשמשהו קרה חמור ובלתי צפוי, כלומר, דבר אשר יש לו השלכות וגלוי למשתמשים אך סביר להניח כי ניתן יהיה להשיבן ללא אובדן נתונים על ידי ביצוע פעולה מפורשת, החל מחכה או הפעלת אפליקציה מחדש כול הדרך מחדש והורדה גירסה חדשה של אפליקציה או אתחול מחדש של המכשיר. רמה זו תמיד נרשמת. סוגיות מצדיקות הרישום ביומן WARNING הרמה עלולות להיחשב גם לדיווח לשרת סטטיסטיקת איסוף.
  • INFORMATIVE : השתמש לציין כי המעניין קרה משהו, כי הוא, כאשר מצב מתגלה כי היא להשפיע נפוצה סבירה, אם כי לא בהכרח טעות. יש לרשום מצב כזה רק על ידי מודול הסבור כי הוא הסמכותי ביותר בתחום זה (כדי להימנע מכניסה כפולה על ידי רכיבים לא סמכותיים). רמה זו תמיד נרשמת.
  • DEBUG : השתמש פתק נוסף המתרחש על מכשיר שיכול להיות רלוונטי לחקור התנהגויות באגים בלתי צפויים. רשום רק את מה שצריך כדי לאסוף מספיק מידע על מה שקורה ברכיב שלך. אם יומני הבאגים שלך שולטים ביומן, עליך להשתמש ברישום מילולי.

    רמה זו מחוברת גם שחרור בונה, והוא נדרש להיות מוקף if (LOCAL_LOG) או if LOCAL_LOGD) לחסום, שבו LOCAL_LOG[D] מוגדר בכיתה או רכיב המשנה שלך, כך שיש אפשרות להשבית את כול רישום כזה . לכן, יש לוודא שאין כל היגיון פעיל if (LOCAL_LOG) הבלוק. כול בניין המחרוזת עבור היומן גם צריך להיות ממוקם בתוך if (LOCAL_LOG) הבלוק. אין לארגן מחדש את השיחה תתנתק לשיחת שיטה אם זה הולך לגרום מחרוזת בנייה להתקיים מחוץ if (LOCAL_LOG) הבלוק.

    יש כמה קוד שעדיין אומר if (localLOGV) . זה נחשב מקובל גם כן, אם כי השם אינו סטנדרטי.

  • VERBOSE : השתמש עבור כל השאר. רמה זו נרשמת רק על באגים בונה וצריך מוקף if (LOCAL_LOGV) לחסום (או שווה ערך), כך שהוא יכול להיות מופק מתוך כברירת מחדל. כל הבניין מחרוזת פשט את שחרורו בונה חייב להופיע בתוך if (LOCAL_LOGV) הבלוק.

הערות

  • בתוך מודול נתון, למעט בבית VERBOSE ברמה, שגיאה צריכה רק להיות מדווחת פעם אם אפשר. בתוך שרשרת יחידה של קריאות פונקציות בתוך מודול, רק הפונקציה הפנימית ביותר צריכה להחזיר את השגיאה, והמתקשרים באותו מודול צריכים להוסיף רק קצת רישום אם זה עוזר באופן משמעותי לבודד את הבעיה.
  • בשרשרת של מודולים, למעט בבית VERBOSE ברמה, כאשר מודול ברמה נמוכה מזהה נתונים לא חוקיים המגיעים מודול ברמה גבוהה יותר, מודול ברמה הנמוכה צריך רק להיכנס למצב הזה אל DEBUG היומן, ורק אם רישום מספק מידע שאינו זמין אחרת למתקשר. באופן ספציפי, אין צורך לרשום מצבים שבהם נזרק חריג (החריג צריך להכיל את כל המידע הרלוונטי), או כאשר המידע היחיד שנרשם נמצא בקוד שגיאה. זה חשוב במיוחד באינטראקציה בין המסגרת לבין האפליקציות, ואת התנאים שנגרמה על ידי יישומי צד שלישיים אשר מטופלים כראוי על ידי המסגרת לא אמור להפעיל כניסה גבוהה יותר DEBUG ברמה. המצבים רק שצריך להפעיל רישום בבית INFORMATIVE הרם ומעלה כאשר מודול או אפליקציה מזהה שגיאה ברמה משלה או מגיע לרמה נמוכה יותר.
  • כאשר מצב שבדרך כלל יצדיק כמה רישומים עשוי להתרחש פעמים רבות, יכול להיות רעיון טוב ליישם מנגנון הגבלת קצב כלשהו כדי למנוע הצפת היומנים עם עותקים כפולים רבים של אותו מידע (או דומה מאוד).
  • אובדן קישוריות לרשת נחשבים שכיחים וצפויים במלואם, ואין לרשום אותם ללא עלות. פסד של קישוריות רשת שיש לה השלכות באפליקציה עצמה צריך להיות מחובר על DEBUG או VERBOSE רמה (תלוי אם התוצאות הן די רציניים מספיק לא צפוי להיות מחובר לבנות שחרור).
  • אין צורך לרשום מערכת קבצים מלאה במערכת קבצים הנגישה או מטעמה של אפליקציות של צד שלישי ברמה גבוהה יותר מ- INFORMATIVE.
  • נתונים שגויים מגיעים מכול מקור מהימן (כולל כול קובץ על אחסון משותף, או נתונים שמגיעים דרך חיבור רשת) נחשבים צפוי ואינו לעורר שום רישום ברמה גבוהה יותר מאשר DEBUG כאשר הוא זוהה הכלא תקף (וגם אז ורישום צריך להיות מוגבל ככל האפשר).
  • כאשר נעשה שימוש על String אובייקטים, + מפעיל במרומז יוצר StringBuilder למשל עם גודל מאגר ברירת מחדל (16 תווים) וזמניים פוטנציאליים אחרים String חפצים. אז במפורש יצירת StringBuilder האובייקטים אינה יקרה יותר מאשר להסתמך על ברירת המחדל + המפעיל (והוא יכול להיות הרבה יותר יעיל). זכור כי קוד הקוראת Log.v() נערך והוצא להורג על שחרורו בונה, כולל בניית המחרוזות, אפילו אם היומנים אינו קריאה.
  • כל רישום שנועד להיקרא על ידי אנשים אחרים ויהיה זמין בבניית מהדורות צריך להיות סבוך מבלי להיות קריפי, ואמור להיות מובן. זה כולל הכל תלוי בכניסה לבית DEBUG הרמה.
  • במידת האפשר, המשך להיכנס בכניסה אחת. אורכי שורה עד 80 או 100 תווים מקובלים. הימנע במידת האורך מ- 130 או 160 תווים (כולל אורך התג).
  • אם כניסת הצלחות דיווחים, לא להשתמש בו ברמות גבוהות יותר מאשר VERBOSE .
  • אם אתה משתמש רישום זמני לאבחן בעיה כי קשה מאוד לחזור, להשאיר אותו בבית DEBUG או VERBOSE ברמה הקף אותו עם אם בלוקים המאפשרים שתשבית אותו בזמן ההידור.
  • היזהר לגבי דליפות אבטחה דרך היומן. הימנע מחיבור מידע פרטי. בפרט, הימנע מחיבור מידע על תוכן מוגן. הדבר חשוב במיוחד בעת כתיבת קוד מסגרת מכיוון שלא קל לדעת מראש מה יהיה ומה לא יהיה מידע פרטי או תוכן מוגן.
  • לעולם אל תשתמשו System.out.println() (או printf() עבור קוד מקורי). System.out ו System.err לקבל מנותב אל /dev/null , כך דוחות ההדפסה שלך אין תופעות גלוי. עם זאת, כל בניית המחרוזת שקורה לשיחות אלה עדיין מבוצעת.
  • כלל הזהב של הרישום הוא שהיומנים שלך לא עשויים לדחוף יומנים אחרים שלא לצורך מחוץ למאגר, כשם שאחרים לא יכולים לדחוף את שלך.

כללי סגנון Javatests

עקוב אחר מוסכמות שמות שיטות הבדיקה והשתמש בקו תחתון כדי להפריד בין מה שנבדק לבין המקרה הספציפי הנבדק. סגנון זה מקל לראות את המקרים הנבדקים. לדוגמה:

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