どちらも、システム間の境界のみをチェックする必要があります。
システム間の境界とは?
- ユーザーからの入力を受け取ると、
- ファイル、ネットワーク、またはソケットを読み取るとき、
- システムコールやプロセス間通信を行う場合、
- ライブラリ コード内、すべての公開 API 内。
- 等
ライブラリ コードでは、パブリック API が外部コードから呼び出される可能性があるため、外部コードから呼び出せるものはすべて常にチェックインする必要があります。内部専用メソッドをチェックする必要はありません (アクセス修飾子が public であっても)。引数エラーは、個人的な好みに応じて、例外またはリターン コードによって通知される場合がありますが、チェック例外は無視できないため、通常、エラーを外部コードに通知する方法として推奨されます。
アプリケーション コードでは (ライブラリとは対照的に)、ユーザーからの入力を受け取るとき、URL をロードするとき、ファイルを読み取るときなどにのみチェックを行う必要があります。パブリック メソッドでは入力チェックを行う必要はありません。独自のアプリケーション コードによって呼び出されることはありません。
Within your own code, you should avoid the situation where you need to check in the first place. For example, instead of checking for null
, you can use "null object pattern". If you still need to do a check though, do it as early as possible, this usually means doing it outside but try to find even earlier points.
Even if not written down formally and even if it's not enforced, all methods whether its internal or public-facing should have a contract. The difference is that in external-facing code, you should enforce the contract as part of your error checking, while in internal-only code you can and should rely on the caller knowing what to and not to pass.
In short, since checking is only done on system boundaries, if you actually have a choice of whether to check inside or outside a method, then you probably should not be checking there since that is not a system boundary.
In a system boundary, both sides always have to check. The caller had to check that the external call succeeds and the callee had to check that the caller gives a sane input/argument. Ignoring an error in the caller is almost always a bug. Robustness principle applies, always check everything you receive from external system, but only send what you know that the external system can accept for sure.
In very big projects though, it's often necessary to compartmentalize the project into small modules. In this case, the other modules in the project can be treated as external systems and you should therefore do the checks in the APIs that are exposed to the other modules in the project.
TLDR; checking is hard.