2007년 7월 29일 일요일

6. Object-oriented pinciples

1. The open-closed principle(OCP)
확장에는 열려있고, 수정에는 닫쳐있어야 한다.(open to extension, closed to modification)
// 수정전
function hello() {
   echo "Hello, Dolly!\n";
}

// 수정 후, 변경 가능한 요소인 이름을 인자로 받아 출력, 코드 수정없이 출력 범위를 확장함
function hello($name) {
   echo "Hello, ".$name."!";
}
2. The single-responsibility principle(SRP)
하나의 클래스에는 하나의 책임만을 져야한다. (변화 가능한 요소가 하나만 있어야 한다. -A class should have only one reason to change)

템플릿 엔진(Template engine)의 기본적인 특징은 다음과 같습니다.
  • 변수들의 집합을 저장할 수 있어야 합니다. (Storing a set of variables)
  • 템플릿 파일을 읽을 수 있어야 합니다. (Reading a template file)
  • 템플릿 파일과 변수 집합을 통하여 출력물을 생성할 수 있어야 합니다. (Combining the first two to generate output)
이러한 특징을 바탕으로 Template을 생성하면 다음과 같은 클래스를 만들 수 있을 것입니다.
class Template {
   private $vars;
   private $file;

   // 생성자에서 파일을 인자로 받아서 템플릿 파일에 사용될 파일을 저장합니다.
   public function __construct($file) {
     $this->$file = $file;
   }

   // 이름과 값 쌍으로 받아서 변수를 저장합니다.
   public function set($var, $value) {
     $this->vars[$var] = $value;
   }
  
   /* HTML로 출력합니다.
    * 1. 설정된 변수들의 집합을 현재의 심볼로 임포트합니다.
    * 2. 출력 버퍼에 템플릿 파일을 출력합니다.
    * 3. 출력 버퍼의 내용을 $string으로 리턴한 다음에 버퍼를 끕니다.
    * 4. 출력 버퍼를 클리어한다음 $string을 리턴합니다.
    */
   public function asHtml() {
     extract($this->vars);
     ob_start();
     include $this->file;
     $string = ob_get_contents();
     ob_end_clean();
     return $string;
   }
}
(관점에 따라 다를 수 있습니다만,) SRP의 원칙에서 봤을 때는 변수를 저장하는 부분과 템플릿 파일을 읽어들이는 부분과 템플릿으로 생성하는 부분 세 개의 책임을 가지는 클래스로 볼 수 있습니다. 따라서 이들을 분리할 수도 있겠죠.
// File을 읽어들이고 처리하는 클래스입니다.
class File {
   public function __construct($name) {
     $this->name = $name;
   }
   // File의 내용을 스트링으로 리턴합니다.
   function getContents() {
     return file_get_contents($this->name);
   }
}

// Template에서 사용하기 위한 변수들을 설정합니다.
// 디폴트 값을 설정하는 기능을 여기에서 할 수 있겠죠.
class TemplateData {
   private $vars;
   public function set($var, $value) {
     $this->vars[$var] = $value;
   }
   public function getArray() {
     return $this->vars;
   }
}

// TemplateData와 File에 템플릿 변수/파일을 처리하는 기능을 위임한 클래스입니다.
class Template {
   private $data;
   private $file;

   public function __construct($file) {
     $this->file = new File($file);
     $this->data = new TemplateData;
   }

   public function set($var, $value) {
     $this->data->set($var, $value);
   }

   private function processTemplate() {
     extract($this->data->getArray());
     $string = $this->file->getContents();
    // 파일처리와 템플릿 생성을 분리하여 include를 사용할  수 없어서 eval을 사용
     eval('?>'.$string);
   }

   public function asHtml() {
     ob_start();
     $this->processTemplate();
     $string = ob_get_contents();
     ob_end_clean();
     return $string;
   }
}
※ 그 외에도 The Dependency-inversion principle(DIP)와 Layered designs가 소개되어있는데 생략합니다~
※※ 4,5 장도 읽어봤는데.. 아는 내용이라 생략합니다~ ^^;;;

출처: Manning, PHP in Action(Objects, Design, Agility) 보면서 요약한 내용입니다.

댓글 없음:

댓글 쓰기