2013-03-03 2 views
0

나는 몇 가지 코드를 쓰고 있어요 (데이터베이스 추상화 계층, 내 코드 모듈의 기타에 사용되는) 네임 스페이스와 제안 모듈을 포함하여 좋은 디자인 패턴 작곡가와의 프로젝트에서. 작곡가 정의에 내 모듈의 성능을 향상시킬 수있는 몇 가지 제안 된 모듈을 포함하고 싶습니다.하지만 꼭 필요한 것은 아닙니다.PHP 작곡가,

내가 가진 문제는 완전히 끔찍한 메모 인 방법으로이를 수행하는 방법입니다.

따라서이 특정 예에서는 모듈이 namespace Intahwebz\DB;으로 선언 된 다음 선택 모듈 Intahwebz\Log\Log이 포함되도록 시도되고 차례로 선택 모듈 Monolog을 사용하려고 시도합니다. 내가 지금까지 무엇을 가지고

namespace Intahwebz\DB; 

use Intahwebz\Log\Log; 


if(trait_exists("Intahwebz\Log\Log") == false){ 
    require_once("Log.php"); 
} 


class ConnectionWrapper{ 

    use Log; 

    function __construct(){ 
     $this->initLog(); 

     // Rest of constructor code. 

     $this->log->trace("ConnectionWrapper has been constructed."); 
    } 

    // Lots of other functions here. 
} 


?> 

그런 다음 Log.php에서 나는 독백을 사용할 수 등을 포함 할 경우, 그렇지 않으면 정말 가벼운 로거를 정의하면 확인 모듈 코드 ConnectionWrapper.php입니다. 독백을 사용할 수있는 경우

<?php 

namespace Intahwebz\Log; 

if (class_exists('Monolog\Logger') && 
    class_exists('Monolog\Handler\StreamHandler')) { 

require_once "MonologWrapper.php"; 

} 
else{ 

    class Logger{ 
     public function debug($message, array $context = array()){ 
      echo $message."\n"; 
     } 
     public function log($level, $message, array $context = array()){ 
      echo $message."\n"; 
     } 
     public function info($message, array $context = array()){ 
      echo $message."\n"; 
     } 
     public function notice($message, array $context = array()){ 
      echo $message."\n"; 
     } 
     public function warning($message, array $context = array()){ 
      echo $message."\n"; 
     } 
     public function error($message, array $context = array()){ 
      echo $message."\n"; 
     } 
     public function critical($message, array $context = array()){ 
      echo $message."\n"; 
     } 
     public function alert($message, array $context = array()){ 
      echo $message."\n"; 
     } 
     public function emergency($message, array $context = array()){ 
      echo $message."\n"; 
     } 
    } 

    trait Log{ 

     var $log; 
     function initLog(){ 
      $this->log = new Logger(__CLASS__); 
     } 
    } 
} 

, 우리는 MonologWrapper.php

<?php 

namespace Intahwebz\Log; 

use Monolog\Logger; 
use Monolog\Handler\StreamHandler; 

trait Log{ 

    var $log; 

    function initLog(){ 
     $this->log = new Logger(__CLASS__); 
     //Todo - get log handler from config file automagically. 
     $this->log->pushHandler(new StreamHandler(PATH_TO_ROOT.'var/log/Admin.log', Logger::WARNING)); 
    } 
} 


?> 
이 가진 문제

을 포함하여 사용할 수 있습니다 : 그것은 매우 추한, 그리고 별도의 파일이 필요합니다

1) 제안 당 기준 치수.

2) 코드를 다시 작성하지 않고 사람들이 모놀로그 이외의 다른 로거로 전환하는 것을 허용하지 않습니다.

3) 클래스/특성 정의 만에 의해 분리 복제가 완전히 내 IDE 혼란을 문 경우.

Symfony 등이이 문제를 해결하는 방법은 서비스 계층을 확보하는 것임을 알고 있습니다. 그러나 종속성 포함을 강제로하지 않고도 해당 디자인 패턴을 사용하는 방법을 볼 수는 없지만 단지 옵션 모듈을 가져 오는 것보다 훨씬 복잡합니다.

옵션 모듈을 포함하거나 다른 호환 모듈로 교체하는 데 적절한 디자인 패턴을 설명한 사람이 있습니까? 아니면 실제 프레임 워크 내에서만 정의 할 수있는 유형입니까?

답변

3

의존성 삽입 (Dependency Injection) : 예를 들어

대신

function initLog(){ 
    $this->log = new Logger(__CLASS__); 
    // .. 
} 

사용

function setLogger(Logger $logger) { 
    $this->log = $logger; 
    // ... 
} 

등등. 이 하드 코딩 된 종속성이 너무 많아서 모든 사람을 언급하지 않을 것입니다. 누군가가이 클래스를 실체화을 시도하고 뭔가가 누락 된 것을 매우 분명하다 때

class MonologLoggingConnectionWrapperWrapper extends ConnectionWrapper { 
    public function __construct (ConnectionWrapper $wrapper, Logger $logger) { 
     // .. 
    } 
} 

이제 독백은, 필요합니다. 원하는 경우 클래스 정의 이전에 파일에 테스트를 추가 할 수 있습니다 (이 경우) 예외를 throw하거나 오류를 트리거해야합니다.

:

(따라서 깨끗하게 교환입니다, 래퍼 필수은, 랩 된 클래스를 확장하거나 해당 인터페이스를 구현하는 사실에서 클래스 명 결과, 그 ConnectionWrapper 정말 래퍼가 아니라 그 자체의 클래스)

언급 할만한 가치가있는 것 : 조건부 클래스 또는 함수 정의를 피하십시오. 하나의 클래스 이름, 하나의 클래스 (더 이상은 아님), 클래스를 인스턴스화하려고 시도 할 때 존재하거나 존재하지 않지만 "때때로"는 아닙니다.

+0

답변 해 주셔서 감사합니다. Monolog 대신에 자신이 선호하는 logger를 어떻게 사용합니까? 그들 자신의 "OtherLoggingConnectionWrapperWrapper"클래스를 생성해야합니까? – Danack

+0

"언급 할만한 가치가있는 : 조건부 클래스 또는 함수 정의를 피하십시오. :)"예. 나는 이것을 "TODO - refactor"라고 쓰고있다. – Danack

+0

매우 매우 중용 : 내 경험상 "TODO"- 플래그가 읽히지 않았습니다. D – KingCrunch