ラベル tips の投稿を表示しています。 すべての投稿を表示
ラベル tips の投稿を表示しています。 すべての投稿を表示

2012年3月30日金曜日

Androidコードスタイルガイド 日本語訳

(This is a copy of Androidコードスタイルガイド 日本語訳)

Androidコードスタイルルール

ここに挙げたルールはガイドラインや推奨という位置付けではなく、厳格な決まり事です。そのため、 ここに挙げたルールを無視してはいけません。ただし、"need-to-use" の原則にのっとり認められた場合は、この限りではありません。
既存のコードのすべてがこれらのルールに従っているわけではありませんが、新しく書いたコードはすべてこれらのルールに従うべきです。

Java言語に関するルール

私たちは標準のJavaコーディング規約に従いますが、いくつかルールを追加しています。
  1. 例外: 説明なしに、例外をキャッチしながら無視してはいけません。
  2. 例外: 汎用の Exception をキャッチしてはいけません。ただし、スタックのルートにあるライブラリコードの場合は除きます。
  3. ファイナライザ: 通常、ファイナライザを使ってはいけません。
  4. インポート: インポートはうまく限定してください。

Javaライブラリに関するルール

AndroidのJavaライブラリおよびツールにも規約があります。時として規約が大きく変更されて、以前書いたコードが推奨されないパターンやライブラリを使うことになるかもしれません。このようなコードで作業するときには、これまでのスタイルを使い続けても構いません(一貫性を参照)。ただし、新しくコンポーネントを作る場合には、推奨されないライブラリを使ってはいけません。

Javaのスタイルに関するルール

すべてのファイルのスタイルに一貫性があると、プログラムは非常にメンテナンスしやすくなります。私たちは Sun が策定した Code Conventions for the Java Programming Language に書かれている標準のJavaコーディングスタイルに、いくつか例外と追加を加えたものに従います。Sun のスタイルガイドは幅広い範囲にわたって詳細な説明があり、Javaコミュニティでは広く使われているものです。
この Sun のスタイルガイドに加えて、私たちは次のルールに従います。
  1. コメント/Javadoc: コメント/Javadocを書いてください。標準のスタイルを使ってください。
  2. 簡潔なメソッド: 巨大なメソッドを書いてはいけません。
  3. フィールド: フィールドはファイルの先頭か、そのフィールドを使うメソッドの直前に書いてください。
  4. ローカル変数: ローカル変数のスコープを限定してください。
  5. インポート: android関連; サードパーティ製(アルファベット順で); java(x) という順にインポートしてください。
  6. インデント: インデントにはスペース4つを使ってください。タブを使ってはいけません。
  7. 行の長さ: 1行は100カラムまでにしてください。
  8. フィールド名: 非パブリック、非スタティックフィールドは m で始めてください。スタティックフィールドは s で始めてください。
  9. 中括弧: 開き中括弧で行を始めてはいけません。
  10. アノテーション: 標準のアノテーションを使うこと。
  11. 頭字語(アクロニム)は単語: 名前では頭字語を単語として扱ってください。例えば、XmlHttpRequestgetUrl() など。
  12. TODOのスタイル: 「TODO: こんな風に書いてください」
  13. 一貫性: まわりをよく見ましょう!
  14. ログ記録: ログを記録するときには注意してください。コストがかかります。

Javatestのスタイルに関するルール

  1. テストメソッドの名前付け: testMethod_specificCase という形式にするとよい。

Java言語に関するルール

例外を無視してはいけません

次のように、例外を完全に無視するようなコードを書いてしまうことがあります。
void setServerPort(String value) {
    try {
        serverPort = Integer.parseInt(value);
    } catch (NumberFormatException e) {
    }
}
これは絶対にやってはいけないことです。「こんなエラーが起こるわけない」とか「このエラー処理はそんなに大事ではない」と考えたのかもしれません。でも、このように例外を無視していると、いつか誰かがつまずいて、あなたのコードにある地雷を踏んでしまいます。信念をもって、コードにあるすべての Exception を処理する必要があります。どのように処理するかは、場合によって違ってきます。
空のcatch節を見たときには必ず気持ち悪いと思わなきゃいけないよ。最終的には、そうするのが正しい場合もあるだろう。たとえそうだとしても、少なくとも検討はしなきゃならない。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
        }
  • Exception をキャッチして、新しい 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);
        }
    元の例外が RuntimeException のコンストラクタの引数に渡されていることに注意してください。例外をラップするという考え方はとても役に立ちますが、このコードはJava 1.4以降でしか動きません。もしJava 1.3でもコンパイルする必要があるなら、元の例外を省略する必要があります。
  • 最後の手段: 自信をもって例外を無視するのが本当に適切だと言えるのなら、例外を無視しても構いません。でも、なぜそうするのか、きちんとした理由をコメントに入れておく必要があります。
    /** 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.
        }
    }

汎用の Exception をキャッチしてはいけません

例外をキャッチして何かするとき、次のように手を抜いてしまうことがよくあります。
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 を使わないのが望ましいです。Throwable には Error 例外も含まれるためです。これは非常に危険です。予期せぬ例外(ClassCastException といった RuntimeException も含みます)が起こると、結局、アプリケーションレベルにあるエラー処理でキャッチすることになります。こうすると、誰がその失敗を処理するのかわかりにくくなります。また、もし誰かがあなたの呼び出しているコードに新しい型の Exception を追加しても、コンパイラは別のエラー処理が必要になったことを教えてはくれません。たいていの場合、異なるタイプの例外を同じ方法で処理しようとすべきではありません。
めったにないことですが、このルールには例外があります。テストコードやトップレベルのコードの場合、あらゆるタイプのエラーをキャッチしたいことがあります。エラーがUI上に現れるのを防いだり、バッチ処理を継続するためです。このような場合には、汎用の Exception(あるいは Throwable)をキャッチして、エラーを適切に処理しても構いません。ただし、そうする前に、よく注意して考えましょう。そして、なぜそこでそうしても安全なのか、理由を説明するコメントを付けておくべきです。
汎用の Exception をキャッチする代わりに、次のような手段をとることができます。
  • try の後、例外ごとに別の catch ブロックでキャッチします。不恰好に見えるかもしれませんが、すべての Exception をキャッチするよりましです。catch ブロックでは、あまりコードを繰り返さないよう注意しましょう。
  • 複数の try ブロックを使って、もっときめ細かくエラー処理するようリファクタリングします。パースから IO を分離して、それぞれ個別にエラー処理するようにしましょう。
  • 例外を投げ直します。たいていの場合、このレベルでどうしても例外をキャッチする必要がなければ、メソッドではその例外を投げるだけにしましょう。
覚えておきましょう: 例外はともだちです! 「あなたは例外をキャッチしていません」とコンパイラがエラーを出しても、嫌な顔をしてはいけません。にっこりしましょう。コンパイラはコードの実行時に発生する問題をキャッチしやすくしてくれているだけなのです。

ファイナライザ

定義: ファイナライザとは、オブジェクトがガベージコレクトされるときに実行されるコードのことです。
賛成: クリーンナップするときに便利です。リソースが外部にあるときには特に便利です。
反対: ファイナライザがいつ呼び出されるか保証はありません。そもそもまったく呼び出されないことさえあるのです。
結論: ファイナライザを使ってはいけません。うまく例外処理することで、ファイナライザでやりたいことはたいていできます。どうしてもファイナライザが必要であれば、close() メソッド(のようなもの)を定義して、そのメソッドをいつ呼び出す必要があるのか、ドキュメントに明記しておきましょう。例えば、InputStream を見てください。この場合、ログがあふれそうにない限りは、ファイナライザで簡潔なログメッセージを出力するのはよいですが、必ずしも必要ありません。
ひとつ例外があります。X.assertTrue() を呼び出すだけであれば、ファイナライザを書いても構いません。

インポート

インポートにおけるワイルドカード

定義: パッケージ foo にあるクラス Bar を使いたいとき、2つのインポート方法があります。
  1. import foo.*;
  2. import foo.Bar;
#1 に賛成: インポート文の数を減らせます。
#2 に賛成: 実際にどのクラスが使われているのかが明確になります。
結論: Androidでコードをインポートするときは、必ず #2 のスタイルを使ってください。ただし、Java標準ライブラリ(java.util.*, java.io.* など)とユニットテストコード(junit.framework.*)についてはその限りではありません。

コメント/Javadoc

すべてのファイルの先頭には、まずコピーライト文を入れておくべきです。その後に、package 文と import 文を続けましょう。各ブロックの間は1行空けておいてください。その後に、クラスやインタフェースの宣言を書きましょう。Javadoc コメントには、そのクラスやインタフェースが何をするものなのかを書いてください。
/*
 * Copyright (C) 2007 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) {
}
setFoo() といった簡単な get/set メソッドの場合、「Fooを設定する」というだけの Javadoc を書く必要はありません。メソッドがもっと複雑な場合(制約があったり、重大な副作用があるなど)には、それについて明記しておかなくてはなりません。また、もしプロパティ "Foo" が何を意味しているのかわかりにくければ、それも説明しておくべきでしょう。
コードを書くときには、そのメソッドがパブリックであろうとなかろうと、すべてのメソッドに Javadoc を書いておくと役に立ちます。パブリックメソッドは API の一部なので、Javadoc を書かなくてはいけません。
現在のところ、Android では Javadoc コメントの書き方について何も強制していませんが、Sun Javadoc conventions に従うべきです。

簡潔なメソッド

メソッドはできるだけ小さくポイントを絞ったものにするべきです。でも、長いメソッドの方がふさわしい場合もあります。そのため、メソッドの長さには厳しい制限を設けていません。もしメソッドが40行を超えるようであれば、プログラムの構造に影響を与えずに分割できないか検討しましょう。

ローカル変数

ローカル変数のスコープは最小限にするべきです(Effective Java Item 29を参照)。そうすることで、コードは読みやすくメンテナンスしやすくなり、間違いも起こりにくくなります。変数は、その変数が使われている箇所をすべて含むブロックのうち、いちばん内側にあるブロックで宣言すべきです。
ローカル変数は初めて使うところで宣言すべきです。ほとんどの場合、ローカル変数の宣言はイニシャライザに入れておくべきでしょう。まだ変数を初期化するのに十分な情報がない場合には、その情報が得られてから宣言すべきです。
try-catch 文については、このルールから除外されます。 メソッドの戻り値によって変数を初期化しようとしていて、そのメソッドがどこかでキャッチされる例外を投げる可能性があるなら、この変数は try ブロックのなかで初期化しておかなくてはいけません。もしその値を try ブロックの外でも使う必要があるなら、try ブロックの前に宣言しておかなくてはいけません。ただし、この時点ではまだきちんと初期化できていないことに注意しましょう。
// 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));
この場合でも、try-catch ブロックをメソッドのなかにカプセル化することで回避できます。
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 文のなかで宣言すべきです。
for (int i = 0; i < n; i++) {
    doSomething(i);
}

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

インポート

インポート文は次のような順序でインポートしてください。

  • Android 関係



  • サードパーティ製ライブラリ (com, junit, net, org) 



  • java と javax
    IDE の設定とうまく合うよう、次のようにインポートすべきです。



  • 各グループ内では、アルファベット順にインポートします。
        大文字は小文字よりも前にあるものと見なします。(例えば Z は a より前)。



  • 大きなグループ分け (android, com, junit, net, org, java, javax) の間には空行を入れておくべきです。

    なぜ?

    もともとは、インポートの順序についてのスタイルはありませんでした。これは、常に IDE が順序を変えるのに任せるか、さもなくば、IDE にある自動のインポート管理機能を無効にして手動でインポートを管理しなければならない、ということを意味します。これはひどい話のように思えました。java-style が尋ねられると、望ましいスタイルはすべてここにあることでした。結局「順序をひとつ選んで一貫性をもたせる」ことが必要になりました。そこで、私たちはスタイルをひとつ選んで、javaguideをアップデートし、IDEがそれに従うようにしました。私たちが期待しているのは、IDEのユーザがコードを書いているうちに、余計なエンジニアリング作業をせずとも、すべてのパッケージがこのパターンに沿ってインポートされることです。
    私たちの選んだスタイルは次のようなものです。



  • 最初に調べたいインポートを先頭に置きます (android)。



  • 最後に調べたいインポートを最後に置きます (java)。



  • 人間というものは簡単にスタイルに従えるものです。



  • IDE はスタイルに従うことができます。

    スタティックインポートをどうするか?

    スタティックインポートを使うか、また、どこに置くのかについては、少し議論になりました。 インポートにスタティックインポートをちりばめるのが好みの人もいれば、他のすべてのインポートの上または下にまとめて置くのが好みの人もいます。しかも、すべての IDE で同じ順序になるような方法はまだありません。
    ほとんどの人がこれを優先度の低い問題だと考えているので、各自の判断にまかせることにしました。ただし、一貫性をもたせるようにしてください。

    インデント

    ブロックのインデントにはスペース4つを使ってください。タブを使ってはいけません。迷ったときには、まわりにあるコードを見て一貫性をもたせてください。
    関数呼び出しと引数を含んだ行の折り返しは、スペース8つでインデントしてください。例えば、これは正しいインデントです。
    Instrument i
            = someLongExpression(that, wouldNotFit, on, one, line);
    これは正しくないインデントです。
    Instrument i
        = someLongExpression(that, wouldNotFit, on, one, line);

    フィールド名

    • 非パブリック、非スタティックフィールドの名前は m で始めてください。
    • スタティックフィールドの名前は s で始めてください。
    • それ以外のフィールドは小文字で始めてください。
    • パブリックな static final フィールド(定数)はアンダースコアを含む大文字だけにしてください(例えば、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 {
                // ...
            }
        }
    }
    条件文には中括弧を付けてください。ただし、条件文全体(条件と本体)が1行に収まるのであれば、中括弧を付けなくても構いません(そうしなければならないわけではありません)。つまり、これも許されます。
    if (condition) {
        body; // ok
    }
    if (condition) body; // ok
    でも、これは許されません。
    if (condition)
        body; // bad

    行の長さ

    コードにおけるテキスト行は、せいぜい100文字までにするべきです。
    このルールについてはかなり議論があったのですが、結局は最長100文字のままとなりました。
    例外: コメント行に100文字以上のコマンド例やURL文字列が含まれる場合には、100文字を超えても構いません。コピー&ペーストしやすくするためです。
    例外: インポートの行はこの制限を超えても構いません。ただし、めったにないでしょう。この方がツールを書くのも簡単になります。

    Java 1.5 アノテーション

    アノテーションは同じ言語要素にある他の修飾子よりも前に置くべきです。単純なマーカーアノテーション(例えば @Override)であれば、言語要素と同じ行に並べても置いても構いません。アノテーションが複数あったり、パラメータ付きのアノテーションの場合には、アルファベット順に1行ずつ並べるべきです。
    Java 1.5 で定義された3つのアノテーションについて、以下が Android 標準のプラクティスです。
    @Deprecated
    その要素の利用がもはや推奨されないときには、@Deprecated アノテーションを必ず付けなければなりません。@Deprecated アノテーションを使うときには、@deprecated Javadoc タグも付けなければなりません。そして、その代わりに使う実装について説明しておくべきです。@Deprecated メソッドはまだ動作がサポートされていることも意味していることを忘れてはいけません。
    もし @deprecated Javadoc タグが付いた古いコードがあれば、@Deprecated アノテーションを追加しておきましょう。
    @Override
    メソッドがスーパークラスにある宣言や実装をオーバーライドしているときには、@Override アノテーションを必ず付けなければなりません。
    例えば、もし {@inheritdocs} Javadoc タグを使っていて、クラス(インタフェースではなく)から派生しているときには、メソッドが親クラスのメソッドをオーバーライドしていることを示すために @Override アノテーションを付けなければなりません。
    @SuppressWarnings
    @SuppressWarnings アノテーションは、どうしても警告を取り除けない事情がある場合にのみ使うべきです。警告を「取り除けない」と判断したときには、@SuppressWarnings アノテーションを付けなければなりません。すべての警告がコード上にある実際の問題を反映できるようにしておくためです。
    @SuppressWarnings アノテーションが必要になったときには、その直前に TODO コメントを入れて、その警告を「取り除けない」事情について説明しておかなくてはいけません。こうすることで、やっかいなインタフェースをもつ問題のあるクラスだということがわかります。例:
    // TODO: The third-party class com.third.useful.Utility.rotate() needs generics
    @SuppressWarnings({"generic-cast"})
    List blix = Utility.rotate(blax);
    @SuppressWarnings アノテーションが必要になったときには、コードをリファクタリングして、アノテーションが適用されるソフトウェア要素を他から分離すべきです。

    名前における頭字語(アクロニム)

    頭字語や略語は単語として扱ってください。その方が読みやすい名前になるためです。
    よいわるい
    XmlHttpRequest XMLHTTPRequest
    getCustomerId getCustomerID
    頭字語や略語そのものが名前の場合にも、このスタイルが適用されます。
    よいわるい
    class Html class HTML
    String url; String URL;
    long id; long ID;
    頭字語について、JDK と Android のコードベースはいずれも、まったくと言っていいほど一貫性がありません。そのため、まわりのコードとの一貫性をもたせることは事実上不可能です。それでもグッとこらえて、どうか頭字語を単語として扱ってください。
    このスタイルルールについて、もっと理由が必要であれば、 Effective Java Item 38 と Java Puzzlers Number 68 を読んでください。

    TODO のスタイル

    コード中の 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 が「将来の日付に何かする」という形式であれば、具体的な日付が入っているか(「2005年11月までに修正」など)、もしくは具体的なイベントが入っているか(「すべての製造ミキサーがプロトコルV7を理解できるようになればこのコードを削除する」など)を確認しましょう。

    一貫性

    最後に考えること: 一貫性をもたせましょう。コードを書いているなら、数分かけてまわりのコードを調べて、スタイルを決めましょう。もし if 節のまわりに空白があれば、あなたもそうすべきです。もしスターで囲まれた小さなボックス型のコメントが使われていれば、あなたのコメントもそうしましょう。
    スタイルガイドラインがあるということは、コーディングに共通のボキャブラリがあるということです。これがあるおかげで、どうやって話すのかではなく、何を話すのかに全員が集中できるようになります。このガイドラインでは、全般的なスタイルに関するルールを説明しました。これでボキャブラリについてはわかったはずです。ただし、ローカルなスタイルも重要です。あなたの追加したコードが、まわりにある既存のコードと全然違って見えてしまうと、コードを読む人は不連続さを感じて、リズムが狂ってしまいます。これは避けましょう。

    ログ記録

    ログ記録は必要不可欠なものですが、適度に簡潔にしておかないとパフォーマンスにかなり悪影響を与えて、すぐに役立たずなものになります。ログ記録ファシリティには5つのレベルがあります。それぞれのレベルをいつどのように使うべきか、以下に説明します。
    • ERROR: このレベルは何か致命的なことが発生したときに使うべきです。つまり、ユーザにとって目に見えて重大で、明確にデータの削除やアプリケーションのアンインストール、データパーティションの削除、電話全体の再起動(あるいは、もっともっと悪いこと)をしなければ復旧不能な問題が発生したときです。このレベルは必ずログに記録しておきましょう。 通常、ERROR レベルでログ記録するような問題は、統計収集サーバに報告するようにしておくのが望ましいです。
    • WARNING: このレベルは深刻な予期せぬことが発生したときに使うべきです。つまり、ユーザにとって目に見えて重大ですが、特定のアクションを実行すればデータを失うことなく復旧可能な問題が発生したときです。このアクションには、しばらく待つだけやアプリを再起動することから、アプリケーションの新しいバージョンを再ダウンロードしたり、デバイスをリブートすることまで、さまざまです。このレベルは必ずログに記録しておきましょう。 WARNING レベルでログ記録するような問題も、統計収集サーバに報告するのを検討した方が望ましいです。
    • INFORMATIVE: このレベルは多くの人にとって関心のあることが発生したことを通知するために使うべきです。つまり、広範囲に影響がありそうだが、必ずしもエラーではないような状況です。これは、そのドメインでいちばん信頼できると思われるモジュールだけが、ログを記録すべきです。(信頼できないコンポーネントによって、ログが二重に記録されるのを防ぐため)。このレベルは必ずログに記録しておきましょう。
    • DEBUG: このレベルはデバイスに何が発生しているのか、想定外の動作を調査、デバッグするための情報を記録するときに使うべきだ。あなたのコンポーネントに何が起こっているのか、必要十分な情報だけをログに記録すべきです。 もしデバッグログがログの大部分を占めるようであれば、VERBOSE レベルで記録すべきでしょう。DEBUG レベルはリリースビルドでも記録されるため、if (LOCAL_LOG) ブロックや if (LOCAL_LOGD) ブロックで囲んでおく必要があります。この LOCAL_LOG[D] はクラスやサブコンポーネントで定義され、こうしたログをすべて無効にできるようになっています。 そのため、if (LOCAL_LOG) ブロックにはアクティブな論理を入れてはいけません。ログのための文字列構築も if (LOCAL_LOG) ブロックのなかに入れておく必要があります。もし if (LOCAL_LOG) ブロックの外側で文字列構築しようとしているなら、ログ記録の呼び出しをメソッド呼び出しにリファクタリングすべきではありません。まだ if (localLOGV) を使っているコードもあります。これもまだ使えますが、名前付けは Android の標準に従っていません。
    • VERBOSE: 以上のどのレベルにも当てはまらないログはすべて、VERBOSE レベルを使うべきです。このレベルはデバッグビルドだけでログが記録されるよう、if (LOCAL_LOGV) ブロック(あるいは同等のもの)で囲んでおくべきです。こうすることで、デフォルトではコンパイルされなくなります。ログに関する文字列構築はリリースビルドに入らないよう、if (LOCAL_LOGV) ブロックのなかに入れておく必要があります。
    注意: VERBOSE レベルを除いて、可能な限り、エラー報告はモジュール内で一度だけにすべきです。モジュール内の一連の関数呼び出しでは、いちばん内側にある関数だけがエラーを返すべきです。そして、同一モジュールにある呼び出し元がログを追記するのは、問題を切り分けるのに非常に有益なときにだけにすべきです。
    注意: 複数のモジュールが連携している場合には、上位レベルのモジュールからやってきた不正なデータを、下位レベルのモジュールで検出することがあります。このときには、VERBOSE レベルを除いて、下位レベルのモジュールでのみ、その状況を DEBUG ログに記録すべきです。しかも、ログ記録するのは、呼び出し元からはわからない情報がある場合にのみにしましょう。具体的に言うと、例外が投げられたり(例外には関連する情報がすべて含まれているはずです)、ログ記録する唯一の情報がエラーコードに含まれている場合には、ログに記録する必要はありません。このことは、フレームワークとアプリケーション間のやりとりでは特に重要になります。サードパーティ製アプリケーションに原因があり、フレームワークがそれをうまく処理する場合には、DEBUG レベルよりも高いレベルでログ記録すべきではありません。モジュールやアプリケーションでは、同レベルあるいは下位レベルからやってきたエラーを検出したときにのみ、INFORMATIVE レベル以上でログ記録しましょう。
    注意: 通常でも、ログを記録する必要のある状況が何度も発生する可能性があるときには、同じ(あるいはよく似た)情報でログがあふれないよう、ログ記録を制限する仕組みを実装するとよいでしょう。
    注意: ネットワークの切断はよくあることなので、あらかじめ十分想定しておきましょう。特別な理由がない限り、これをログに記録すべきではありません。アプリケーションに重大な影響を及ぼすようなネットワークの切断は、DEBUG レベルか VERBOSE レベルでログ記録しておくべきです(リリースビルドでもログ記録しておくほど結果が深刻であり想定外であるかによります)。
    注意: ファイルシステムへのアクセスあるいはサードパーティ製アプリケーションの動作によって、ファイルシステムがいっぱいになったとき、この状況を INFORMATIVE レベル以上でログ記録すべきではありません。
    注意: 信頼できないソース(共有ストレージにあるファイルやネットワーク経由のデータも含みます)から不正なデータがやって来ることは十分想定されることであり、たとえ不正なデータを検出しても、DEBUG レベルよりも高いレベルでログ記録すべきではありません。(できるだけログを記録するするのを限定すべきです)。
    注意: String オブジェクトに対して '+' 演算子を使うと、知らないうちにデフォルトのバッファサイズ(16文字)をもつ StringBuilder オブジェクトと、ごくわずかな一時的な String オブジェクトが生成されていることを覚えておきましょう。 つまり、デフォルトの '+' 演算子に任せるよりも、明示的に StringBuffer オブジェクトを生成した方がコストがかからない(しかも、実際にはずっと効率がよくなる)ということです。また、Log.v() の呼び出しは、リリースビルドでもコンパイルされて実行されることを覚えておきましょう。たとえログが読めなくても、文字列構築は実行されています。
    注意: 他人に読んでもらうようなリリースビルドでも有効なログは、曖昧さのない簡潔なものにすべきです。そして、非常に理解しやすいものにすべきです。これには DEBUG レベルまでの、すべてのログ記録が含まれます。
    注意: ログ記録は意味が通じる限り、1行に収めるべきです。1行が80文字から100文字であれば、まったく問題ありません。(タグの長さも入れて)130文字あるいは160文字を超えるのは、できる限り避けるべきです。
    注意: 成功したことをログに記録するときには、VERBOSE レベルより高いレベルにしてはいけません。
    注意: 再現困難な問題を調査するために一時的にログを記録するときには、DEBUG もしくは VERBOSE レベルにするべきです。そして、if ブロックで囲んで、コンパイル時にすべて無効にできるようにしておくべきです。
    注意: ログ全体を通して、情報漏洩には注意しましょう。プライベートな情報をログに記録するのは避けるべきです。保護されている内容に関する情報は、絶対に記録してはいけません。フレームワークのコードを書いているときには、これは特に重要になります。ある情報がプライベートもしくは保護されている内容であるか否か、事前に知るのは簡単ではないためです。
    注意: System.out.println()(またはネイティブコードの printf())を使ってはいけません。System.out と System.err は /dev/null にリダイレクトされます。したがって、いくら print 文を書いても見えません。にもかかわらず、呼び出しに伴って発生する文字列構築はすべて実行されてしまいます。
    注意: ログ記録には鉄則があります。あなたのログが不必要に他人のログを押し出さないようにしてください。他人のログがあなたのログを押し出さないようにするのと同じようにね。

    Javatestのスタイルに関するルール

    テストメソッドの名前付け

    テストメソッドに名前を付けるときは、アンダースコアでテスト対象と個々のテストケースを分けるのが望ましいです。こうしておくと、どのケースがテストされるのか、わかりやすくなります。
        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))
    }
  • Gmailのエラーコード一覧

    Gmailのエラーコード一覧
    (copy of http://gmail.1o4.jp/error-code.html)
    トラブル対処の第一はSSLや簡易HTMLでログインしたりキャッシュをクリアする事!
    Gmailの内部更新に起因する場合も多いので臨時メンテナンスと同じ予防策を!

    はてなブックマークに登録
    リンクフリー(更新:2008/2/6)
    エラーコード等 過去に生じた症状と解決法
    007  事例1,事例2,
    主にメール送信やファイル添付で出る。セキュリティソフトの悪影響が大きい。ブラウザのキャ
    ッシュをクリアすると直る場合もある。サーバーの一時的なトラブルもある。SSLリンクでログインすると解決。 公式ヘルプがこちら。
    受信したHTMLメールの容量が多い時にも出る(削除する)。IE7で頻発?
    008  事例1,事例2,事例3,
    基本的に007エラーと同じだが、主にファイル添付(容量関係ない)で出る。
    Gmailの「更新」ボタンで解決する事もあるが、SSLでログインすると解決。
    Adobeソフトをアップグレードしたら出たという話もある。
    IEの場合、ブラウザのセキュリティレベルを下げても直る。Firefoxでも直る。
    102  007の場合のトラブルシュートで解決しない場合は、旧バージョンの Gmail を使用するか、簡易 HTML 形式を使用する。
    404
    405  公式ヘルプがこちらとこちら。ネットワークやセキュリティソフトでブロックされている。Gmailというより、HTTPエラー。
    502  事例1,
    公式ヘルプがこちら。"Server Error(サーバーエラー)"と表示されるBad Gateway(プロキシ)を示すHTTPエラー。しばらく待つ。700系エラーと混在する事がある。同じPCでも別のアカウントでは正常な事例があり、アカウントによって起こりやすいものがあるという話も。サーバー依存?
    "http://b.mail.google.com/mail/channel/bind"系のページがポップアップするものはGmail2.0から1.0バージョンに戻すと直ったという話がある。このURLはGmailをブロックする事なくGoogleトークをブロックする方法で活用されているらしい。
    600  事例1,事例2,
    フィルタ作成時やメッセージを開こうとすると出る。ブラウザのキャッシュをクリアし、SSLでログインすれば解決する。Firefox用Greasemonkeyスクリプト「gmail Unlabelled」を使うと出るという報告もある。
    602  事例1,事例2,事例3,
    ブラウザ(Safariなど)でのメール送信でクラッシュしたり遅くなる。キャッシュのクリアなどは効果なし。メールソフトのファイル添付でエラーが出る場合も。メールソフトの場合、他のプログラムがモデムを使ってる時に出るエラーらしい。他のファックスソフトなどを閉じて解決。
    613  事例1,
    メール送信やファイル添付の際に出る。あまり事例が無いため解決策が分からないが、添付制限に関わっていると言う人がいた。
    700  事例1,事例2,
    Gmail2.0導入直後にトラブル続出。ログイン不良やログイン後の操作の不具合。キャッシュやクッキーのクリアでは解決せず。その間転送は機能する。POPでも接続トラブル。いろんなセキュリティソフトが不具合を起こす例がある。モバイルGmailでも同様の不具合。「設定」をクリックするとエラー502が出る例も。簡易HTMLで解決した(簡易HTMLはこちら)という話がある。
    704  事例1,事例2,
    ログイン時に出る。他のGoogleサービスにはログインできる。Google Talkからならログインできるらしい。メールが遅延したり、メール送信時や読む時にもエラーが出る。POP3/SMTPも反応はあるが働かない。メールを一定量受信するとフリーズする人もいた。ウィルススキャン中に固まる人もいた。IEでもFirefoxでも。同じPCでも別のアカウントでは正常。405や758、717エラーと混在する事がある。
    707  事例1,事例2,
    メール送信時にエラーが出る。ログインできない時も。キャッシュをクリアしても解決しない場合は、セキュリティソフトのidentity protectionが原因なので、そのセキュリティレベルを下げると解決する。
    717  事例1,事例2,事例3,事例4,
    ログインできない。できてもメール送信時や下書き保存時や更新の操作で出る事も。メールが遅延する。OSやプロバイダは関係なくサーバーの問題。704や766、767エラーと混在。
    758  事例1,
    ログインできなかったり、メール送信や受信でエラーが出る。下書き保存できない。キャッシュをクリアしても解決せず。同じPCで別のアカウントは正常に動作。704や766エラーから転移する事がある。
    766  事例1,事例2,事例3,
    数時間、ログインできなかったりメール本文が表示されない。レスポンスが悪くなる。あるスパムメールを削除したら717エラーになった話や、767に変化した話もある。Googleにはログインできる。クッキーをクリアしても解決せず。PCの問題ではなくアカウント(サーバー)の問題。
    一時解決はとりあえずログインURLを変えてみる事。不安定だが。
    767  事例1,事例2,事例3,事例4,事例5,事例6,
    ウェブでも携帯でもGmail ManageやGoogle talkやガジェットなどのツールでもPOPでもアクセスできないが、別のGmailアカウントでは正常だったり、他のGoogleサービスにはログインできる。転送設定している人はメールが届く人もいる。クッキーとキャッシュをクリアしたら直った人や、PCを再起動したら直った人がいるが、解決しない人もいる。IE系でのエラーが目に付く。メール送信時やウイルススキャン時に767エラーが出る人もいる。717や766、777と混在する事がある。
    776  事例1,事例2,事例3,事例4,事例5,事例6,
    アクセスできなかったり、プロフィールの保存や連絡先の追加ができない。Gmailの設定で休暇モードやPOP設定を変更しようとしても出る。休暇モードは空白にする分には問題ない。ラベルが削除できない人も。ブラウザ依存やPC依存ではなく、セキュリティソフトの影響でもない。1ヶ月悩まされた人がいる。766と混在する事がある。
    777  事例1,事例2,
    ログインできない。ログイン中に出ることも。面白い事にSSLでログインする事でエラーが出ることもある。クッキーをクリアしてもだめ。767や766のファーストエラーとして出る。
    Sector 5 policy  複数宛先に一斉送信する場合に、Mail Delivery Subsystemから、「Sector 5 policy」によってメールが配信されない事例がある。スパマーと認識されている可能性が高い。
    Bad Data 3  対処法はこちら。Gmailと通信できていない事を示す。
    読み込み中...  読み込み処理を完了できない場合の対処法。
    Cookie 機能が無効  ブラウザの cookie をオンにするには。
    ActiveX エラー  ActiveX エラーが出る場合はセキュリティレベルの設定を。
    証明書エラー  証明書エラーが出る場合は、日時を正しく設定する。
    メンテナンス  Gmailの臨時メンテナンス対処法。
    「noname」  Gmailで「noname」と出て壊れてしまった添付ファイルを直す変換スクリプト
    外部POP
    エラー  Gmailに外部POPアカウントを登録した時のエラーについて列挙しておきます。
    Authentication failed →アカウント名かパスワードが間違っている
    DNS lookup failed →サーバー名(ドメイン)が間違っている
    Bad port →ポート番号が違う
    Protocol error →SSL未対応なのにSSLを使って取得しようとした場合に出る
    Connection timed out →アカウントがPOPに対応していない
    大量送信エラー  メールを一斉送信する場合に、以下のエラーが出てアカウントがロックされます。
    Gmail(ウェブ)で500件以上:”Gmail Lockdown in Secton 4”
    メールソフトで100件以上:”E550 5.4.5 Daily sending quota exceeded.”
    詳細はこちら。
    エラーコードの実態について
    Gmailは常に、最先端機能の導入やスパム対策などを通じて更新され続けています。そのため、数年間何事もなく利用できていても、ある日突然、エラーコードが出たり、臨時メンテナンスに突入したりする事があります。特に新機能がリリースされた時など。
    Google由来の場合、Gmailは分散システム(Gmailダンス)になっているのか、エラーコードに悩むユーザはごく一部、1%にも届きません。PC依存ではないので別のアカウントでは正常だったりします。ですが、その事は逆に、エラーにハマった人々の叫びが空しく響く状況を生み出し、1ヶ月も遮断されたままだったという人もいます。
    Google由来の場合のエラーコードはバグコードのようなもので、その本当の意味はGoogleにしか分かりません。Googleが修正している間、ユーザーが出来る解決策は少ないので、日々予防する事をオススメします。
    エラーコードはGoogle由来だけでなく、添付ファイル系のエラーは、セキュリティソフトやネットワークが干渉している事が多く、その場合はSSLでログインすれば解決します。ソフトが干渉すると言う事は、それだけセキュリティに弱いという事なので、普段からSSLを使うようにしましょう。
    セキュリティソフトやブラウザが突然更新されてGmailをフリーズさせる事もあります。

    ※解決方法など、追加情報がありましたら是非ご連絡下さい。


    Gmailの使い方!

    2011年11月11日金曜日

    iTunes Wi-Fi 同期トラブルおよび対処方法

    iTunes 10.5 and later:iTunes Wi-Fi 同期 に関する・トラブルシューティング
    (これはsuppurt.applle.comによる記事のバックアップです)

    現象

    iTunes 10.5 には、Wi-Fi 経由で iOS デバイスを同期できる機能が追加されています。Wi-Fi 同期を設定 した後、以下のような問題が起こった場合は、この記事で紹介する手順を参照してください。
    Wi-Fi 経由で iTunes に iOS デバイスが表示されない
    Wi-Fi 同期のパフォーマンスが遅い


    対象製品
    iTunes 10 for Windows, iTunes 10 for Mac


    解決方法

    1. システム条件を確認する

    Wi-Fi 同期に必要な条件は以下の通りです。
    iOS 5 以降を搭載する iOS デバイス、および iTunes 10.5 以降で以下を搭載するコンピュータ
    OS X Lion または Snow Leopard (10.6.8)
    またはWindows XP、Windows Vista、または Windows 7

    お使いの iOS デバイス、iTunes、およびオペレーティングシステムが最新であることを確認してください。
    iOS デバイスをアップデートするには、こちらの記事 の手順を実行してください。
    iTunes と OS X のアップデート方法:Apple メニューの「ソフトウェア・アップデート」を選択します。iTunes または OS X 関連のアップデートをインストールします。
    Windows のアップデート方法:Microsoft の Windows Update ページを参照してください。

    2. Wi-Fi 同期が有効になっていることを確認する

    Wi-Fi 経由でコンテンツを iOS デバイスに同期するには、まず、iTunes で Wi-Fi 同期のオプションを有効にする必要があります。以下の手順を実行します。
    付属の USB ケーブルを使って iOS デバイスをコンピュータに接続します。
    iTunes を起動し、iTunes ウインドウの左側でデバイスを選択します。
    「概要」タブをクリックします。


    「オプション」までスクロールし、「Wi-Fi 経由でこの iOS デバイス と同期」オプションを有効にします。「適用」ボタンをクリックします。



    3. iTunes をいったん終了し、再起動した後、iOS デバイスを再起動する

    接続の問題が解消しない場合、お使いのコンピュータで iTunes をいったん終了してから、再起動します。次に、iOS デバイスを再起動します。

    4. ネットワークルーターを再起動する

    製造元のマニュアルで推奨されている方法で、ホームネットワークルーターを再起動します。このとき、30 秒以上電源コードを抜いたままにする必要がある場合があります。

    注意:この間、VoIP ベースの電話などのインターネットサービスが無効になり、ほかのルーターを順次リセットしなければならない場合があります。

    5. ネットワーク接続を確認する

    Wi-Fi 同期を行うには、インターネットに接続された Wi-Fi ネットワークが必要です。iTunes を使ってワイヤレスで同期するすべてのデバイスが、同じ Wi-Fi ネットワークに接続されていることを確認してください。
    さらに、次の点を確認します。
    複数の Wi-Fi ルーターをお使いの場合は、すべてのデバイスが同じルーターに接続されていること。複数のルーターを使っていると、デバイス間の通信が妨げられることがあります。
    デバイスが VPN を使っていないこと、またはすべてのデバイスが同じ VPN を使っていること。VPN がデバイスを隔離して接続妨害を起こすことがあります。
    ゲストネットワークを使ってルーターを設定している場合は、以下を確認します。
    すべてのデバイスがゲストネットワークに接続されており、互いに通信できるよう設定されていること。
    またはすべてのデバイスがルーターのプライマリネットワークに切り替えられること。
    お使いのコンピュータがスリープまたはシャットダウン状態の場合、または iTunes を閉じている場合、iTunes ライブラリへのアクセスがないこと。コンピュータをスリープ解除または起動し、Wi-Fi 同期を最初に有効にしたコンピュータのユーザアカウントにサインインして、iTunes を開くと、ライブラリへのアクセスが復帰します。
    ルーターを最新の状態にしておくこと。AirMac または Time Capsule をお使いの場合、こちらの記事 を参照してファームウェアアップデートについて確認してください。他社製のルーターをお使いの場合は、各製造元にお問い合わせ ください。

    6. ネットワーク干渉の確認

    Wi-Fi 同期の実行中に接続が途切れる場合や、パフォーマンスが大幅に低下する場合は、以下が原因でワイヤレスネットワークに干渉が起こっていることが考えられます。
    電子レンジコードレス電話ルーターとデバイスの間に金属の障壁があったり、コンピュータ、ベースステーション、iOS デバイスの間の距離が遠すぎる場合ネットワーク干渉を最小限に抑えるには、次の方法を試してください。
    iOS デバイスとコンピュータを Wi-Fi ルーターまたはベースステーションの近くに配置し、Wi-Fi 信号が強くなるかどうか確認します。
    ワイヤレス通信を妨げる要因 がないか確認します。
    iOS デバイスからケース、スタンド、またはその他の付属品を取り外して、Wi-Fi 信号が強くなるかどうか確認します。
    Safari で Web ページを読み込んで、Wi-Fi 信号が強くなるか確認します。

    7. ファイアウォールの設定の確認

    お使いのルーターまたはコンピュータでファイアウォールが有効になっている場合は、ファイアウォールによってコンピュータと iOS デバイスの通信が妨げられていないかどうか確認してください。Mac の iTunes で内蔵ファイアウォールオプションを使うには、こちらの記事 の手順を参照してください。Apple 製以外のファイアウォールとセキュリティソフトウェアを使っている場合は、該当する開発者/製造元にお問い合わせください。

    注意:Mac では、ポート 123 を使って、日付と時刻が自動的に設定されます。コンピュータまたは iOS デバイスの日付/時刻が間違っていると、接続全般のエラーの原因となります。

    お使いのルーターにファイアウォールが設定されているかどうか、必要なポートが開いているかどうがわからない場合は、以下の手順を実行して、問題の原因を判断してください。
    ネットワーク上にある別の iOS デバイスで Wi-Fi 同期を有効にし、同じ問題が起こるかどうか確認します (別のデバイスの Wi-Fi 同期を有効にする方法については、上記の手順 を参照してください)。
    別のネットワークを使ってデバイスをテストします。別のネットワークでデバイスが問題なく動作する場合は、お使いのルーターまたはネットワーク設定に問題があることが考えられます。詳しいトラブルシューティング方法を 製造元またはインターネットサービスプロバイダにお問い合わせ ください。

    コンピュータまたはルーター上でほかのセキュリティ/ファイアウォールソフトウェアをお使いの場合は、こちらの記事 を参照するか、製造元にお問い合わせ ください。または TCP ポート 123 と 3689、UDP ポート 123 と 5353 を開放する方法をマニュアルで確認してください。