19

私は PHP ライブラリを書いていますが、懸念があります。インターフェイスに次のようなものがあります。

<?php
/**
 * My interface
 *
 * ...
 */
interface MyInterface
{
    /**
     * This method does foo.
     *
     * @throws \RuntimeException If foo can't be done.
     */
    public function fooAndBar();
}
?>

@throwsインターフェイスは実際には何もせず、純粋に実装の詳細を抽象化するために使用されるため、このエントリは完全に正しいとは言えません。ただし、インターフェイスのすべての実装が何か問題が発生したときに例外をスローしたため、私は常にそれを使用してきました。

しかし、別の開発者が、失敗しない (例外をスローできない) 実装を作成したり、別の例外クラスを使用したりする場合があります。

@throwsこの状況では、インターフェース宣言でどのように文書化すればよいですか? それも文書化する必要がありますか?

4

2 に答える 2

13

インターフェイスはコントラクトを定義します。throws実装クラスが Exception をスローするかどうかは、PHP では実装の詳細です。これは、(Java のように) メソッド シグネチャにキーワードがないためです。注釈を追加して@throwsも、技術的に契約を強制することはできませんが、規則を示すことができます (戻り値についても同じです)。それが十分かどうかは、あなたが決めることです。

補足として、開発者がスローしない実装を思いついた場合、スローする実装にはいずれにしても try/catch ブロックを追加する必要があるため、問題はありません (慣例により)。実装が DocBlock に示されているものとは異なる Exception をスローし始めた場合、それはキャッチされないため、問題になります。

于 2012-05-27T20:38:30.443 に答える
12

インターフェイスを使用するコードを検討してください。

public function doSomething(MyInterface $my) { ... }

実装の 1 つでも例外をスローできる場合は、例外の可能性を確実に処理する必要があります。

ですから、はい、文書化する必要があります。

例外をスローする実装が 1 つだけの場合でも、例外処理を適切に行う必要があります。もちろん、これはすべてのメソッドに @throws を適用する必要があるという意味ではありません。適切な場合にのみ使用する必要があります (実装が正当に例外をスローする必要があると予想される場合)。

より具体的な例として、次のことを検討してください。

interface LogWriter
{

    /**
     * @throws LogWriterException
     */
    public function write($entry);

}


class DbLogWriter
{

    public function __construct(PDO $db)
    {
        //store $db somewhere
    }

    public function write($entry)
    {
        try {
            //store $entry in the database
        } catch (PDOException $e) {
            throw new LogWriterException(...);
        }
    }

}

class NullLogWriter
{
    public function write($entry) { }
}

データベースへの書き込み時に例外が発生する可能性を下げるために、特定のことを行うことができますが、結局のところ、それは例外に対して安全な操作ではありません。したがって、DbLogWriter::write例外がスローされることが予想されます。

ただし、エントリを破棄するだけの null ライターを考えてみましょう。そこでは間違いが起こる可能性はまったくないので、例外は必要ありません。

$logしかし、それが の実装であるということだけを知っている場合はどうなるでしょうかLogWriter。例外がスローされず、誤って 1 つのバブルが発生する可能性があると思いますか、それとも をスローできると思いますLogWriterExceptionか? 私は安全側にとどまり、LogWriterException をスローできると想定します。

ユーザーが知っているの$logは LogWriter であるということだけで、DbLogWriter だけが例外をスローすると文書化されている場合、ユーザーはそれが例外をスローできることに気付かない$log->write(...) 可能性があります。また、後で FileLogWriter が作成されたときに、その実装がスローできる例外とスローする可能性のある例外の期待値が既に設定されていることを意味します ( が をスローするとは誰も期待しませんFileLogWriter) RandomNewException

于 2012-05-27T20:25:37.923 に答える