의미있는 일을하려고하지 않는 한 예외를 포착해서는 안됩니다 .
"의미있는 것"은 다음 중 하나 일 수 있습니다.
예외 처리
가장 명백한 의미있는 조치는 예를 들어 오류 메시지를 표시하고 작업을 중단하여 예외를 처리하는 것입니다.
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
echo "Error while connecting to database!";
die;
}
로깅 또는 부분 정리
때로는 특정 컨텍스트 내에서 예외를 올바르게 처리하는 방법을 모릅니다. 아마도 "큰 그림"에 대한 정보가 부족하지만 가능한 한 실패한 지점까지 실패를 기록하려고합니다. 이 경우 다음을 포착, 기록 및 다시 던지기를 원할 수 있습니다.
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
logException($e); // does something
throw $e;
}
관련 시나리오는 실패한 작업에 대한 정리를 수행 할 수있는 적절한 위치에 있지만 실패를 최상위 수준에서 처리하는 방법을 결정하지는 않는 것입니다. 이전 PHP 버전에서는 다음과 같이 구현되었습니다.
$connect = new CONNECT($db, $user, $password, $driver, $host);
try {
$connect->insertSomeRecord();
}
catch (Exception $e) {
$connect->disconnect(); // we don't want to keep the connection open anymore
throw $e; // but we also don't know how to respond to the failure
}
PHP 5.5에는 finally
키워드 가 도입 되었으므로 정리 시나리오의 경우 다른 접근 방법이 있습니다. 어떤 일이 발생했는지 (예 : 오류와 성공 여부에 관계없이) 정리 코드를 실행해야하는 경우 이제 예외를 전달하면서 투명하게 허용하면서이를 수행 할 수 있습니다.
$connect = new CONNECT($db, $user, $password, $driver, $host);
try {
$connect->insertSomeRecord();
}
finally {
$connect->disconnect(); // no matter what
}
오류 추상화 (예외 체인 포함)
세 번째 경우는 가능한 많은 실패를 논리적으로 더 큰 그룹으로 그룹화하려는 경우입니다. 논리 그룹화의 예 :
class ComponentInitException extends Exception {
// public constructors etc as in Exception
}
class Component {
public function __construct() {
try {
$connect = new CONNECT($db, $user, $password, $driver, $host);
}
catch (Exception $e) {
throw new ComponentInitException($e->getMessage(), $e->getCode(), $e);
}
}
}
이 경우 Component
데이터베이스 연결을 사용하여 구현되었음을 사용자 가 알지 못하게 할 수 있습니다 (향후 옵션을 열어두고 파일 기반 스토리지를 사용하려고 할 수도 있음). 따라서 귀하의 사양은 Component
"초기화 실패의 경우 ComponentInitException
발생합니다"라고 말합니다. 이를 통해 소비자는 Component
예상되는 유형의 예외를 포착 하는 동시에 디버깅 코드가 모든 (구현 종속) 세부 정보에 액세스 할 수 있습니다 .
보다 풍부한 컨텍스트 제공 (예외 연결)
마지막으로 예외에 대한 더 많은 컨텍스트를 제공하려는 경우가 있습니다. 이 경우 오류가 발생했을 때 수행하려는 작업에 대한 자세한 정보가 포함 된 다른 예외로 예외를 래핑하는 것이 좋습니다. 예를 들면 다음과 같습니다.
class FileOperation {
public static function copyFiles() {
try {
$copier = new FileCopier(); // the constructor may throw
// this may throw if the files do no not exist
$copier->ensureSourceFilesExist();
// this may throw if the directory cannot be created
$copier->createTargetDirectory();
// this may throw if copying a file fails
$copier->performCopy();
}
catch (Exception $e) {
throw new Exception("Could not perform copy operation.", 0, $e);
}
}
}
이 경우는 위와 비슷하지만 (예제로는 아마도 가장 좋은 것은 아닙니다) 더 많은 컨텍스트를 제공하는 요점을 보여줍니다. 예외가 발생하면 파일 복사가 실패했음을 알려줍니다. 그러나 왜 실패 했습니까? 이 정보는 랩핑 된 예외에서 제공됩니다 (이 예제가 훨씬 복잡한 경우 둘 이상의 레벨이있을 수 있음).
예를 들어 UserProfile
, 사용자 프로파일이 파일에 저장되고 트랜잭션 시맨틱을 지원하기 때문에 오브젝트 작성으로 인해 파일이 복사 되는 시나리오를 생각하면이 값을 보여줍니다 . 커밋 할 때까지 프로필 사본.
이 경우에
try {
$profile = UserProfile::getInstance();
}
결과적으로 "대상 디렉토리를 만들 수 없습니다"예외 오류가 발생하면 혼란 스러울 수 있습니다. 컨텍스트를 제공하는 다른 예외 계층으로이 "핵심"예외를 랩하면 오류를 훨씬 쉽게 처리 할 수 있습니다 ( "프로파일 복사 작성 실패"-> "파일 복사 조작 실패"-> "대상 디렉토리를 작성할 수 없음").