From 9c19de690fee2cf6a37df0955f60fa9ef2e2796b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EB=8C=80=EC=8A=B9?= Date: Fri, 22 Oct 2021 13:42:58 +0900 Subject: [PATCH 1/6] =?UTF-8?q?tutorial=20=EA=B0=9C=ED=8E=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Views/tutorial/page/home.php | 79 ++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 app/Views/tutorial/page/home.php diff --git a/app/Views/tutorial/page/home.php b/app/Views/tutorial/page/home.php new file mode 100644 index 0000000..0ab2c0c --- /dev/null +++ b/app/Views/tutorial/page/home.php @@ -0,0 +1,79 @@ +extend('sample/layout') ?> + +section('content') ?> +
+ + + +
+ + +

첫 번째 컨트롤러 만들기

+ +

+ `app/Controllers/Tutorial/Pages1.php` 파일을 만들고 다음 코드를 입력합니다. +

+

+ 우리는 `$Page`라는 하나의 인수(argument)를 허용하는 view() 메소드가 있는 Pages1 클래스를 작성했습니다.
+ 그리고 기본 컨트롤러인 `app/Controllers/Home.php`와 동일한 index() 메소드(method)를 가지고 있습니다.
+ 이 메소드는 CodeIgniter의 welcome 페이지를 보여줍니다. +

+

+ Pages1 클래스는 CodeIgniter\Controller 클래스를 확장하고 있습니다.
+ 이는 새 Pages1 클래스가 CodeIgniter\Controller 클래스에 정의된 메소드와 변수를 이용할 수 있다는 것을 의미합니다.
+ 컨트롤러는 웹 어플리케이션에 대한 모든 요청의 중심이 되며, 여느 php 클래스와 마찬가지로 컨트롤러내에서 `$this`로 지칭합니다. +

+ + 'tabsPages1Source', + 'title' => '컨트롤러', + 'href' => '/sample/home/view/Controllers/Tutorial/Pages1', + ], + [ + 'id' => 'tabsPages1', + 'title' => '실행결과', + 'href' => '/tutorial/pages1', + ], + [ + 'id' => 'tabsPages1ViewSource', + 'title' => '뷰', + 'href' => '/sample/home/view/Views/welcome_message', + ], + [ + 'id' => 'tabsPages1Guide', + 'title' => '메뉴얼', + 'href' => 'http://ci4doc.cikorea.net/tutorial/static_pages.html#id1', + ], + ]) ?> + + +

첫 번째 메소드를 만들었으니, 이제 몇 가지 기본적인 페이지 템플릿을 만들어 봅시다.

+

우리는 페이지 푸터(footer)와 헤더(header) 역할을 하는 두 개의 “뷰(view)”를 만들겁니다.

+

`app/Views/tutorial/templates/header.php` 파일을 만들고 다음 코드를 추가하십시오.

+

+

헤더에는 머리글과 함께 기본 보기를 로드하기 전에 표시할 기본 HTML 코드가 포함되어 있습니다.

+

그리고 우리가 나중에 컨트롤러에서 정의할 `$title` 변수를 출력합니다.

+

이제, 다음 코드를 포함하는 `app/Views/tutorial/templates/footer.php`로 푸터(footer)를 작성하십시오.

+ +

컨트롤러에 로직 추가

+ +

앞서 우리는 view() 메소드를 컨트롤러에 추가했습니다.

+

이 메소드는 `$Page`라는 하나의 파라미터를 허용합니다.

+

정적(static) 페이지 본문은 `app/Views/tutorial/pages/` 디렉터리에 위치합니다.

+

그 디렉터리에 `home.php`과 `about.php`이라는 이름의 파일을 두 개를 만드십시오.

+

그 파일들 안에, 텍스트 − 당신이 원하는 어떤것 −를 입력하고 저장합니다.

+

만약 여러분이 특별히 독창적이지 않은 사람이 되고 싶다면, “Hello World!”를 입력해도 됩니다.

+

이 페이지를 로드하려면 요청된 페이지가 실제로 존재하는지 확인해야 합니다.

+

+

요청된 페이지가 존재하면 헤더와 푸터를 포함하여 본문이 로드되어 사용자에게 표시됩니다. 요청된 페이지가 존재하지 않을 경우, “404 Page not found” 오류가 표시됩니다.

+

이 메소드의 첫 번째 줄은 페이지가 실제로 존재하는지 여부를 확인합니다. PHP의 네이티브 함수 `is_file()`는 파일이 예상되는 위치에 있는지 확인하는 데 사용되었습니다. `PageNotFoundException`은 기본 오류 페이지를 표시하는 CodeIgniter 예외입니다.

+

헤더 템플릿에서는 페이지 제목을 출력하기 위해 “$title” 변수가 사용되었습니다. $title의 값은 메소드에서 정의되지만, 변수에 직접 값을 할당하는 대신 $data 배열의 title 요소에 할당합니다.

+

마지막으로 해야 할 일은 뷰(view)를 표시되는 순서대로 로드하는 것입니다. 이를 위해 CodeIgniter에 내장된 view() 함수를 사용합니다. view() 함수의 두 번째 매개변수는 뷰에 값을 전달하는 데 사용됩니다.

+

$data 배열의 값은 변수명을 키(key)로하여 할당됩니다. 컨트롤러의 $data['title'] 값은 뷰의 $title과 동일합니다.

+ + + +
+
+endSection() ?> \ No newline at end of file From fb01a55ff1efbbec05ec23ac4acb5554465713e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EB=8C=80=EC=8A=B9?= Date: Fri, 22 Oct 2021 13:50:30 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=EB=A6=AC=ED=8E=99=ED=84=B0=EB=A7=81=20?= =?UTF-8?q?=EC=83=98=ED=94=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Controllers/Refactoring/Basic/Home.php | 23 ++++++++++++++++++++++ app/Views/refactoring/basic/home.php | 11 +++++++++++ 2 files changed, 34 insertions(+) create mode 100644 app/Controllers/Refactoring/Basic/Home.php create mode 100644 app/Views/refactoring/basic/home.php diff --git a/app/Controllers/Refactoring/Basic/Home.php b/app/Controllers/Refactoring/Basic/Home.php new file mode 100644 index 0000000..6504dd9 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Home.php @@ -0,0 +1,23 @@ + '기본적인 리팩터링', + 'location' => 'refactoring', + 'menu' => 'basic', + ]; + + public function index() + { + return view('refactoring/basic/home', $this->menuInfo); + } +} \ No newline at end of file diff --git a/app/Views/refactoring/basic/home.php b/app/Views/refactoring/basic/home.php new file mode 100644 index 0000000..6c55015 --- /dev/null +++ b/app/Views/refactoring/basic/home.php @@ -0,0 +1,11 @@ +extend('sample/layout_example') ?> + +section('content') ?> +
+ + + +
+
+
+endSection() ?> \ No newline at end of file From e7a21257fa326ddc90e7fa2d94394fb98389cc22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EB=8C=80=EC=8A=B9?= Date: Fri, 22 Oct 2021 18:19:14 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=EB=A6=AC=ED=8E=99=ED=84=B0=EB=A7=81=20?= =?UTF-8?q?=EA=B8=B0=EC=B4=88=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Controllers/Refactoring/Basic/Exam1.php | 53 ++++ app/Controllers/Refactoring/Basic/Exam2.php | 65 +++++ app/Controllers/Refactoring/Basic/Exam3.php | 34 +++ app/Controllers/Refactoring/Basic/Exam4.php | 26 ++ .../Refactoring/Basic/Refactoring/Exam1.php | 73 ++++++ .../Refactoring/Basic/Refactoring/Exam2.php | 50 ++++ .../Refactoring/Basic/Refactoring/Exam3.php | 34 +++ .../Refactoring/Basic/Refactoring/Exam4.php | 37 +++ app/Views/refactoring/basic/home.php | 243 +++++++++++++++++- 9 files changed, 613 insertions(+), 2 deletions(-) create mode 100644 app/Controllers/Refactoring/Basic/Exam1.php create mode 100644 app/Controllers/Refactoring/Basic/Exam2.php create mode 100644 app/Controllers/Refactoring/Basic/Exam3.php create mode 100644 app/Controllers/Refactoring/Basic/Exam4.php create mode 100644 app/Controllers/Refactoring/Basic/Refactoring/Exam1.php create mode 100644 app/Controllers/Refactoring/Basic/Refactoring/Exam2.php create mode 100644 app/Controllers/Refactoring/Basic/Refactoring/Exam3.php create mode 100644 app/Controllers/Refactoring/Basic/Refactoring/Exam4.php diff --git a/app/Controllers/Refactoring/Basic/Exam1.php b/app/Controllers/Refactoring/Basic/Exam1.php new file mode 100644 index 0000000..15a6dd3 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Exam1.php @@ -0,0 +1,53 @@ +addDays(30); + + echo "고객명 : {$invoice['customer']}\n"; + echo "채무액 : {$outstanding}\n"; + echo "마감일 : {$invoice['dueDate']}\n"; + } + + public function index() + { + $invoice = [ + 'customer' => 'customer', + 'orders' => [ + ['amount' => 100], + ['amount' => 110], + ['amount' => 120], + ['amount' => 130], + ['amount' => 140], + ], + 'dueDate' => '', + ]; + + echo '
';
+        $this->printOwing($invoice);
+        echo '
'; + } + +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Exam2.php b/app/Controllers/Refactoring/Basic/Exam2.php new file mode 100644 index 0000000..6e92da7 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Exam2.php @@ -0,0 +1,65 @@ +moreThanFiveLateDeliveries($aDriver) ? 2 : 1); + } + + protected function moreThanFiveLateDeliveries($aDriver) + { + return $aDriver['numberOfLateDeliveries'] > 5; + } + + protected function rating2($aDriver) + { + return ($this->lessThanFiveLateDeliveries($aDriver) ? 2 : 1); + } + + protected function lessThanFiveLateDeliveries($drv) + { + return $drv['numberOfLateDeliveries'] < 5; + } + + protected function reportLines($aCustomer) + { + $lines = []; + $lines = $this->getherCustomerData($lines, $aCustomer); + return $lines; + } + + protected function getherCustomerData($out, $aCustomer) + { + $out['name'] = $aCustomer['name']; + $out['location'] = $aCustomer['location']; + + return $out; + } + + public function index() + { + $aDriver = [ + 'numberOfLateDeliveries' => 3 + ]; + + $aCustomer = [ + 'name' => 'Name', + 'location' => 'Location', + ]; + + echo '
';
+        echo "rating1 = {$this->rating1($aDriver)}\n";
+        echo "rating2 = {$this->rating2($aDriver)}\n";
+        echo "reportLines = " . print_r($this->reportLines($aCustomer), true);
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Exam3.php b/app/Controllers/Refactoring/Basic/Exam3.php new file mode 100644 index 0000000..45f57f2 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Exam3.php @@ -0,0 +1,34 @@ + 5, + 'itemPrice' => 1000 + ]; + + echo '
';
+        echo "price = {$this->price($order)}";
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Exam4.php b/app/Controllers/Refactoring/Basic/Exam4.php new file mode 100644 index 0000000..86cca75 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Exam4.php @@ -0,0 +1,26 @@ + 'mr', 'lastName' => 'he']; + + public function index() + { + $spaceship['owner'] = $this->defaultOwner; + $this->defaultOwner = ['firstName' => 'mrs', 'lastName' => 'her']; + + echo '
';
+        echo 'spaceship = ' . print_r($spaceship, true) . "\n";
+        echo 'defaultOwner = ' . print_r($this->defaultOwner, true);
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Refactoring/Exam1.php b/app/Controllers/Refactoring/Basic/Refactoring/Exam1.php new file mode 100644 index 0000000..6661daa --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Refactoring/Exam1.php @@ -0,0 +1,73 @@ +printBanner(); + $outstanding = $this->calculateOutstanding($invoice); + $invoice = $this->recordDueData($invoice); + $this->printDetail($invoice, $outstanding); + } + + protected function printBanner() + { + echo "*****************\n"; + echo "*** 고객 채무 ***\n"; + echo "*****************\n"; + } + + protected function printDetail($invoice, $outstanding) + { + echo "고객명 : {$invoice['customer']}\n"; + echo "채무액 : {$outstanding}\n"; + echo "마감일 : {$invoice['dueDate']}\n"; + } + + protected function recordDueData($invoice) + { + $time = Time::now(); + $invoice['dueDate'] = $time->addDays(30); + + return $invoice; + } + + protected function calculateOutstanding($invoice) + { + $outstanding = 0; + foreach($invoice['orders'] as $o) { + $outstanding += $o['amount']; + } + + return $outstanding; + } + + public function index() + { + $invoice = [ + 'customer' => 'customer', + 'orders' => [ + ['amount' => 100], + ['amount' => 110], + ['amount' => 120], + ['amount' => 130], + ['amount' => 140], + ], + 'dueDate' => '', + ]; + + echo '
';
+        $this->printOwing($invoice);
+        echo '
'; + } + +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Refactoring/Exam2.php b/app/Controllers/Refactoring/Basic/Refactoring/Exam2.php new file mode 100644 index 0000000..93be0d5 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Refactoring/Exam2.php @@ -0,0 +1,50 @@ + 5 ? 2 : 1); + } + + protected function rating2($aDriver) + { + // 인라인시 $drv를 $aDriver로 리펙토링 + return ($aDriver['numberOfLateDeliveries'] < 5 ? 2 : 1); + } + + protected function reportLines($aCustomer) + { + $lines = []; + // 인라인시 $out을 $lines로 리펙토링 + $lines['name'] = $aCustomer['name']; + $lines['location'] = $aCustomer['location']; + return $lines; + } + + public function index() + { + $aDriver = [ + 'numberOfLateDeliveries' => 3 + ]; + + $aCustomer = [ + 'name' => 'Name', + 'location' => 'Location', + ]; + + echo '
';
+        echo "rating1 = {$this->rating1($aDriver)}\n";
+        echo "rating2 = {$this->rating2($aDriver)}\n";
+        echo "reportLines = " . print_r($this->reportLines($aCustomer), true);
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Refactoring/Exam3.php b/app/Controllers/Refactoring/Basic/Refactoring/Exam3.php new file mode 100644 index 0000000..49a009d --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Refactoring/Exam3.php @@ -0,0 +1,34 @@ + 5, + 'itemPrice' => 1000 + ]; + + echo '
';
+        echo "price = {$this->price($order)}";
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Refactoring/Exam4.php b/app/Controllers/Refactoring/Basic/Refactoring/Exam4.php new file mode 100644 index 0000000..89593e1 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Refactoring/Exam4.php @@ -0,0 +1,37 @@ + 'mr', 'lastName' => 'he']; + + public function getDefaultOwner() + { + return $this->defaultOwner; + } + + public function setDefaultOwner($arg) + { + $this->defaultOwner = $arg; + return $this; + } + + public function index() + { + $spaceship['owner'] = $this->getDefaultOwner(); + $this->setDefaultOwner(['firstName' => 'mrs', 'lastName' => 'her']); + + echo '
';
+        echo 'spaceship = ' . print_r($spaceship, true) . "\n";
+        echo 'defaultOwner = ' . print_r($this->getDefaultOwner(), true);
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Views/refactoring/basic/home.php b/app/Views/refactoring/basic/home.php index 6c55015..3a2109e 100644 --- a/app/Views/refactoring/basic/home.php +++ b/app/Views/refactoring/basic/home.php @@ -1,11 +1,250 @@ -extend('sample/layout_example') ?> +extend('sample/layout') ?> section('content') ?>
- +
+ +

함수 추출하기

+ +

+ 코드 조각을 찾아 무슨일을 하는지 파악한 다음, 독립된 함수로 추출하고 목적에 맞는 이름을 붙인다.
+ 코드가 무슨 일을 하는지 파악하는 데 한참이 걸리다면 그 부분을 함수로 추출한 뒤 `무슨 일`에 걸맞는 이름을 짓는다. +

+ +
    +
  1. 함수를 새로 만들고 목적을 잘 드러내는 이름을 붙인다.(어떻게가 아닌 무엇을 기준으로)
  2. +
  3. 추출할 코드를 원본 함수에서 복사하여 새 함수에 붙여넣는다.
  4. +
  5. 추출한 코드 중 원본 함수의 지역 변수를 참조하거나 추출한 함수의 유효범위를 벗어나는 변수는 없는지 검사한다.
    있다면 매개변수로 전달한다.
  6. +
  7. 원본 함수에서 추출한 코드 부분을 새로 만든 함수를 호출하는 문장으로 바꾼다.
  8. +
  9. 테스트한다.
  10. +
  11. 다른 코드에 방금 추출한 것과 같거나 비슷한 코드가 없는지 살핀다.
    있다면 방금 추출한 새 함수를 호출하도록 바꿀지 검토한다.
  12. +
+ + 'Exam1Show', + 'title' => '/refactoring/basic/exam1', + 'href' => '/refactoring/basic/exam1', + ], + [ + 'id' => 'Exam1', + 'title' => 'Exam1.php', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Exam1', + ], + [ + 'id' => 'ReftExam1Show', + 'title' => '/refactoring/basic/refactoring/exam1', + 'href' => '/refactoring/basic/refactoring/exam1', + ], + [ + 'id' => 'ReftExam1', + 'title' => 'Exam1.php(Refactoring)', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Refactoring/Exam1', + ], + ]) ?> + + + +

함수 인라인하기

+ +

+ `함수 추출하기`에서는 코드가 명료해지고 이해하기 쉽도록 코드의 일부를 목적이 분명히 들어나는 이름의 함수로 사용하기를 권장한다.
+ 하지만 때로는 함수 본문이 이름만큼 명확하거나 이름만큼 깔끔하게 리펙터링될 때도 있다. 이럴때는 함수를 과감히 제거하고 인라인한다.
+

+ +
    +
  1. 다형 메서드인지 확인한다.
  2. +
  3. 인라인할 함수를 호출하는 곳을 모두 찾는다.
  4. +
  5. 각 호출문을 함수 본문으로 교체한다.
  6. +
  7. 하나씩 교체할 때마다 테스트한다.
  8. +
  9. 함수를 삭제한다.
  10. +
+ + 'Exam2Show', + 'title' => '/refactoring/basic/exam2', + 'href' => '/refactoring/basic/exam2', + ], + [ + 'id' => 'Exam2', + 'title' => 'Exam2.php', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Exam2', + ], + [ + 'id' => 'ReftExam2Show', + 'title' => '/refactoring/basic/refactoring/exam2', + 'href' => '/refactoring/basic/refactoring/exam2', + ], + [ + 'id' => 'ReftExam2', + 'title' => 'Exam2.php(Refactoring)', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Refactoring/Exam2', + ], + ]) ?> + + + +

변수 추출하기

+ +

+ 표현식이 너무 복잡하여 이해하기 어려울 때 지역 변수를 활용하여 표현식을 쪼개 관리하기 쉽게 만듭니다.
+ 추가한 변수는 복잡한 로직을 쉽게 만들기도 하지만 디버깅에도 도움이 됩니다. +

+ +
    +
  1. 추출하려는 표현식에 부작용(Side effect)이 없는지 확인하다.
  2. +
  3. 지역 변수를 하나 선언하고 이름을 붙일 표현식의 복제본을 대입한다.
  4. +
  5. 원본 표현식을 새로 만든 변수로 교체한다.
  6. +
  7. 테스트한다.
  8. +
  9. 표현식을 여러 곳에서 사용한다면 각각을 새로 만든 변수로 교체한다.
    하나 교체할 때마다 테스트한다.
  10. +
+ + 'Exam3Show', + 'title' => '/refactoring/basic/exam3', + 'href' => '/refactoring/basic/exam3', + ], + [ + 'id' => 'Exam3', + 'title' => 'Exam3.php', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Exam3', + ], + [ + 'id' => 'ReftExam3Show', + 'title' => '/refactoring/basic/refactoring/exam3', + 'href' => '/refactoring/basic/refactoring/exam3', + ], + [ + 'id' => 'ReftExam3', + 'title' => 'Exam3.php(Refactoring)', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Refactoring/Exam3', + ], + ]) ?> + + + +

변수 인라인하기

+ +

+ 변수 이름이 표현식과 다를 바 없다면 그 변수는 인라인하는 것이 좋습니다. +

+ +
    +
  1. 대입문의 우변(표현식)에서 부작용(Side effect)이 없는지 확인하다.
  2. +
  3. 이 변수를 가장 처음 사용하는 코드를 찾아서 대입문 우변의 코드로 바꾼다.
  4. +
  5. 테스트한다.
  6. +
  7. 변수를 사용하는 부분을 모두 교체할 때까지 이 과정을 반복한다.
  8. +
  9. 변수와 대입문을 삭제한다.
  10. +
  11. 테스트한다.
  12. +
+ + + + + + + +
function moreThan100($anOrder)
+{
+    $basePrice = $anOrder['basePrice'];
+    return ($basePrice > 100);
+}
+
=>
+function moreThan100($anOrder)
+{
+    return ($anOrder['basePrice'] > 100);
+
+}
+
+ + + +

함수 이름 바꾸기

+ +

+ 함수 이름이 좋으면 함수 호출문만 보고도 무슨 일을 하는지 파악할 수 있습니다.
+ 잘못된 함수 이름을 발견하고 그보다 더 이해하기 쉬운 이름이 떠오르면 즉시 바꿉니다. +

+ + + + + + + +
+function circum($radius)
+{
+    return 2 * pi() * $radius;
+}
+
=>
+function circumference($radius)
+{
+    return 2 * pi() * $radius;
+}
+
+ + + +

변수 캡슐화하기

+ +

+ 유효 범위가 넓은 전역 변수는 함수로 캡슐화 하십시오.
+ 전역 변수 접근을 함수로 캡슐화하여 독점하면 데이터의 변경 및 사용하는 코드를 감시할 수 있으며, 데이터 변경 전 검증이나 변경 후 추가 로직을 쉽게 넣을 수 있습니다. +

+ +
    +
  1. 변수로의 접근과 갱신을 전담하는 캡슐화 함수들을 만든다.
  2. +
  3. 변수를 직접 참조하던 부분을 모두 적절한 캡슐화 함수 호출로 바군다. 하나씩 바꿀 때마다 테스트한다.
  4. +
  5. 변수의 접근 범위를 제한한다.
  6. +
  7. 테스트한다.
  8. +
  9. 변수 값이 레코드라면 `레코드 캡슐화하기`를 적용할 지 고려해본다.
  10. +
+ + 'Exam4Show', + 'title' => '/refactoring/basic/exam4', + 'href' => '/refactoring/basic/exam4', + ], + [ + 'id' => 'Exam4', + 'title' => 'Exam4.php', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Exam4', + ], + [ + 'id' => 'ReftExam4Show', + 'title' => '/refactoring/basic/refactoring/exam4', + 'href' => '/refactoring/basic/refactoring/exam4', + ], + [ + 'id' => 'ReftExam4', + 'title' => 'Exam4.php(Refactoring)', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Refactoring/Exam4', + ], + ]) ?> + + + +

변수 이름 바꾸기

+ +

+ 함수 이름과 마찬가지로 변수 이름도 많은 것을 설명해줍니다.
+ 개발을 진행하다 잘못 지어진 변수 이름을 발견한다면 그 목적에 맞는 이름으로 변수명을 바꿔줍니다. +

+ +
    +
  1. 폭넓게 쓰이는 변수라면 변수 캡슐화하기를 고려한다.
  2. +
  3. 이름을 바꿀 변수를 참조하는 곳을 모두 찾아서, 하나씩 변경한다.
  4. +
  5. 테스트한다.
  6. +
+ +
endSection() ?> \ No newline at end of file From 91e63afd320da8ffe5d15576ad9a8993fed0ab63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EB=8C=80=EC=8A=B9?= Date: Wed, 27 Oct 2021 10:20:55 +0900 Subject: [PATCH 4/6] =?UTF-8?q?=EB=B7=B0=EC=99=80=20=ED=8C=8C=EC=84=9C=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99=20=EC=83=98=ED=94=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Controllers/Refactoring/Basic/Exam5.php | 39 ++++ app/Controllers/Refactoring/Basic/Exam6.php | 73 +++++++ app/Controllers/Refactoring/Basic/Exam7.php | 73 +++++++ app/Controllers/Refactoring/Basic/Exam8.php | 33 +++ .../Refactoring/Basic/Refactoring/Exam5.php | 60 ++++++ .../Refactoring/Basic/Refactoring/Exam6.php | 116 +++++++++++ .../Refactoring/Basic/Refactoring/Exam7.php | 83 ++++++++ .../Refactoring/Basic/Refactoring/Exam8.php | 43 ++++ .../Refactoring/Capsulation/Exam1.php | 24 +++ .../Refactoring/Capsulation/Home.php | 23 +++ .../Capsulation/Refactoring/Exam1.php | 29 +++ app/Controllers/Response/Parser/Exam4.php | 31 +++ app/Helpers/parser_helper.php | 15 ++ app/Views/refactoring/basic/home.php | 167 ++++++++++++++- app/Views/refactoring/capsulation/home.php | 58 ++++++ app/Views/response/parser/exam4.php | 13 ++ app/Views/response/parser/home.php | 191 +++++++++++------- 17 files changed, 997 insertions(+), 74 deletions(-) create mode 100644 app/Controllers/Refactoring/Basic/Exam5.php create mode 100644 app/Controllers/Refactoring/Basic/Exam6.php create mode 100644 app/Controllers/Refactoring/Basic/Exam7.php create mode 100644 app/Controllers/Refactoring/Basic/Exam8.php create mode 100644 app/Controllers/Refactoring/Basic/Refactoring/Exam5.php create mode 100644 app/Controllers/Refactoring/Basic/Refactoring/Exam6.php create mode 100644 app/Controllers/Refactoring/Basic/Refactoring/Exam7.php create mode 100644 app/Controllers/Refactoring/Basic/Refactoring/Exam8.php create mode 100644 app/Controllers/Refactoring/Capsulation/Exam1.php create mode 100644 app/Controllers/Refactoring/Capsulation/Home.php create mode 100644 app/Controllers/Refactoring/Capsulation/Refactoring/Exam1.php create mode 100644 app/Controllers/Response/Parser/Exam4.php create mode 100644 app/Helpers/parser_helper.php create mode 100644 app/Views/refactoring/capsulation/home.php create mode 100644 app/Views/response/parser/exam4.php diff --git a/app/Controllers/Refactoring/Basic/Exam5.php b/app/Controllers/Refactoring/Basic/Exam5.php new file mode 100644 index 0000000..f2810db --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Exam5.php @@ -0,0 +1,39 @@ + $max); + }); + + } + + public function index() + { + $station = [ + 'name' => 'ZB!', + 'readings' => [ + ['temp' => 47, 'time' => '2016-11-10 09:10'], + ['temp' => 53, 'time' => '2016-11-10 09:20'], + ['temp' => 58, 'time' => '2016-11-10 09:30'], + ['temp' => 53, 'time' => '2016-11-10 09:40'], + ['temp' => 51, 'time' => '2016-11-10 09:50'], + ], + ]; + + echo '
';
+        print_r($this->readingsOutsideRange($station, 50, 55));
+        echo '
'; + + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Exam6.php b/app/Controllers/Refactoring/Basic/Exam6.php new file mode 100644 index 0000000..e63f608 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Exam6.php @@ -0,0 +1,73 @@ + 'ivan', + 'quantity' => 10, + 'month' => 5, + 'year' => 2017, + ]; + + return $reading; +} + +function taxThreshold($year) +{ + return $year > 2015 ? 0 : 0.5; +} + +function baseRate($month, $year) +{ + return $year / $month; +} + +function calculateBaseCharge($aReading) +{ + return baseRate($aReading['month'], $aReading['year']) * $aReading['quantity']; +} + +/** + * Description of Exam6 + * + * @author hoksi + */ +class Exam6 extends BaseController +{ + protected function client1() + { + $aReading = acquireReading(); + $baseCharge = baseRate($aReading['month'], $aReading['year']) * $aReading['quantity']; + + return $baseCharge; + } + + protected function client2() + { + $aReading = acquireReading(); + $base = (baseRate($aReading['month'], $aReading['year']) * $aReading['quantity']); + $taxableCharge = max(0, $base - taxThreshold($aReading['year'])); + + return $taxableCharge; + } + + protected function client3() + { + $aReading = acquireReading(); + $baseCharge = calculateBaseCharge($aReading); + + return $baseCharge; + } + + public function index() + { + echo '
';
+        echo "client1 : {$this->client1()}\n";
+        echo "client2 : {$this->client2()}\n";
+        echo "client3 : {$this->client3()}\n";
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Exam7.php b/app/Controllers/Refactoring/Basic/Exam7.php new file mode 100644 index 0000000..c2a78bb --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Exam7.php @@ -0,0 +1,73 @@ + 'ivan', + 'quantity' => 10, + 'month' => 5, + 'year' => 2017, + ]; + + return $reading; +} + +function taxThreshold($year) +{ + return $year > 2015 ? 0 : 0.5; +} + +function baseRate($month, $year) +{ + return $year / $month; +} + +function calculateBaseCharge($aReading) +{ + return baseRate($aReading['month'], $aReading['year']) * $aReading['quantity']; +} + +/** + * Description of Exam7 + * + * @author hoksi + */ +class Exam7 extends BaseController +{ + protected function client1() + { + $aReading = acquireReading(); + $baseCharge = baseRate($aReading['month'], $aReading['year']) * $aReading['quantity']; + + return $baseCharge; + } + + protected function client2() + { + $aReading = acquireReading(); + $base = (baseRate($aReading['month'], $aReading['year']) * $aReading['quantity']); + $taxableCharge = max(0, $base - taxThreshold($aReading['year'])); + + return $taxableCharge; + } + + protected function client3() + { + $aReading = acquireReading(); + $baseCharge = calculateBaseCharge($aReading); + + return $baseCharge; + } + + public function index() + { + echo '
';
+        echo "client1 : {$this->client1()}\n";
+        echo "client2 : {$this->client2()}\n";
+        echo "client3 : {$this->client3()}\n";
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Exam8.php b/app/Controllers/Refactoring/Basic/Exam8.php new file mode 100644 index 0000000..dd46978 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Exam8.php @@ -0,0 +1,33 @@ + $shippingMethod['discountThreshold']) ? $shippingMethod['discountedFee'] : $shippingMethod['feePerCase']; + $shippingCost = $quantity * $shippingPerCase; + $price = $basePrice - $discount + $shippingCost; + + return $price; +} + +/** + * Description of Exam8 + * + * @author hoksi + */ +class Exam8 extends BaseController +{ + public function index() + { + $product = ['basePrice' => 10000, 'discountThreshold' => 8000, 'discountRate' => 0.1]; + $shippingMethod = ['discountThreshold' => 8000, 'discountedFee' => 500, 'feePerCase' => 3500]; + + echo '
';
+        echo "priceOrder : " . priceOrder($product, 5, $shippingMethod) . "\n";
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Refactoring/Exam5.php b/app/Controllers/Refactoring/Basic/Refactoring/Exam5.php new file mode 100644 index 0000000..a9e1d7a --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Refactoring/Exam5.php @@ -0,0 +1,60 @@ +getMin() || $r['temp'] > $range->getMax()); + }); + + } + + public function index() + { + $range = new NumberRange(50, 55); + + $station = [ + 'name' => 'ZB!', + 'readings' => [ + ['temp' => 47, 'time' => '2016-11-10 09:10'], + ['temp' => 53, 'time' => '2016-11-10 09:20'], + ['temp' => 58, 'time' => '2016-11-10 09:30'], + ['temp' => 53, 'time' => '2016-11-10 09:40'], + ['temp' => 51, 'time' => '2016-11-10 09:50'], + ], + ]; + + echo '
';
+        print_r($this->readingsOutsideRange($station, $range));
+        echo '
'; + + } +} + +class NumberRange { + protected $data; + + public function __construct($min, $max) + { + $this->data = ['min' => $min, 'max' => $max]; + } + + public function getMin() + { + return $this->data['min']; + } + + public function getMax() + { + return $this->data['max']; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Refactoring/Exam6.php b/app/Controllers/Refactoring/Basic/Refactoring/Exam6.php new file mode 100644 index 0000000..a40fa46 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Refactoring/Exam6.php @@ -0,0 +1,116 @@ + 'ivan', + 'quantity' => 10, + 'month' => 5, + 'year' => 2017, + ]; + + return $reading; +} + +function taxThreshold($year) +{ + return $year > 2015 ? 0 : 0.5; +} + +/** + * Description of Exam6 + * + * @author hoksi + */ +class Exam6 extends BaseController +{ + protected function client1() + { + $rawReading = acquireReading(); + $aReading = new Reading($rawReading); + $baseCharge = $aReading->getBaseCharge(); + + return $baseCharge; + } + + protected function client2() + { + $rawReading = acquireReading(); + $aReading = new Reading($rawReading); + $taxableCharge = $aReading->taxableChargeFn(); + + return $taxableCharge; + } + + protected function client3() + { + $rawReading = acquireReading(); + $aReading = new Reading($rawReading); + $baseCharge = $aReading->getBaseCharge(); + + return $baseCharge; + } + + public function index() + { + echo '
';
+        echo "client1 : {$this->client1()}\n";
+        echo "client2 : {$this->client2()}\n";
+        echo "client3 : {$this->client3()}\n";
+        echo '
'; + } +} + +class Reading { + protected $customer; + protected $quantity; + protected $month; + protected $year; + + public function __construct($data) + { + $this->customer = $data['customer']; + $this->quantity = $data['quantity']; + $this->month = $data['month']; + $this->year = $data['year']; + } + + public function getCustomer() + { + return $this->customer; + } + + public function getQuantity() + { + return $this->quantity; + } + + public function getMonth() + { + return $this->month; + } + + public function getYear() + { + return $this->year; + } + + public function baseRate($month, $year) + { + return $year / $month; + } + + public function getBaseCharge() + { + return $this->baseRate($this->month, $this->year) * $this->quantity; + } + + public function taxableChargeFn() + { + return max(0, $this->getBaseCharge() - taxThreshold($this->getYear())); + } + +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Refactoring/Exam7.php b/app/Controllers/Refactoring/Basic/Refactoring/Exam7.php new file mode 100644 index 0000000..77750e3 --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Refactoring/Exam7.php @@ -0,0 +1,83 @@ + 'ivan', + 'quantity' => 10, + 'month' => 5, + 'year' => 2017, + ]; + + return $reading; +} + +function taxThreshold($year) +{ + return $year > 2015 ? 0 : 0.5; +} + +function baseRate($month, $year) +{ + return $year / $month; +} + +function calculateBaseCharge($aReading) +{ + return baseRate($aReading['month'], $aReading['year']) * $aReading['quantity']; +} + +function enrichReading($original) +{ + $result = $original; + $result['baseChage'] = calculateBaseCharge($result); + $result['taxableCharge'] = max(0, $result['baseChage'] - taxThreshold($result['year'])); + return $result; +} + +/** + * Description of Exam7 + * + * @author hoksi + */ +class Exam7 extends BaseController +{ + protected function client1() + { + $rawReading = acquireReading(); + $aReading = enrichReading($rawReading); + $baseCharge = $aReading['baseChage']; + + return $baseCharge; + } + + protected function client2() + { + $rawReading = acquireReading(); + $aReading = enrichReading($rawReading); + $taxableCharge =$aReading['taxableCharge']; + + return $taxableCharge; + } + + protected function client3() + { + $rawReading = acquireReading(); + $aReading = enrichReading($rawReading); + $baseCharge = $aReading['baseChage']; + + return $baseCharge; + } + + public function index() + { + echo '
';
+        echo "client1 : {$this->client1()}\n";
+        echo "client2 : {$this->client2()}\n";
+        echo "client3 : {$this->client3()}\n";
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Basic/Refactoring/Exam8.php b/app/Controllers/Refactoring/Basic/Refactoring/Exam8.php new file mode 100644 index 0000000..eb4d26b --- /dev/null +++ b/app/Controllers/Refactoring/Basic/Refactoring/Exam8.php @@ -0,0 +1,43 @@ + $basePrice, 'quantity' => $quantity, 'discount' => $discount]; +} + +function applyShipping($priceData, $shippingMethod) +{ + $shippingPerCase = ($priceData['basePrice'] > $shippingMethod['discountThreshold']) ? $shippingMethod['discountedFee'] : $shippingMethod['feePerCase']; + $shippingCost = $priceData['quantity'] * $shippingPerCase; + return $priceData['basePrice'] - $priceData['discount'] + $shippingCost; +} + +/** + * Description of Exam8 + * + * @author hoksi + */ +class Exam8 extends BaseController +{ + public function index() + { + $product = ['basePrice' => 10000, 'discountThreshold' => 8000, 'discountRate' => 0.1]; + $shippingMethod = ['discountThreshold' => 8000, 'discountedFee' => 500, 'feePerCase' => 3500]; + + echo '
';
+        echo "priceOrder : " . priceOrder($product, 5, $shippingMethod) . "\n";
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Capsulation/Exam1.php b/app/Controllers/Refactoring/Capsulation/Exam1.php new file mode 100644 index 0000000..e44dd09 --- /dev/null +++ b/app/Controllers/Refactoring/Capsulation/Exam1.php @@ -0,0 +1,24 @@ + '홍길동', 'country' => 'KR']; + $result = "[h1]{$organization['name']}[/h1]"; + $organization['name'] = '김삿갓'; + + echo '
';
+        echo "result : {$result}\n";
+        echo "organization : " . print_r($organization, true) . "\n";
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Capsulation/Home.php b/app/Controllers/Refactoring/Capsulation/Home.php new file mode 100644 index 0000000..320329e --- /dev/null +++ b/app/Controllers/Refactoring/Capsulation/Home.php @@ -0,0 +1,23 @@ + '캡슐화', + 'location' => 'refactoring', + 'menu' => 'capsulation', + ]; + + public function index() + { + return view('refactoring/capsulation/home', $this->menuInfo); + } +} \ No newline at end of file diff --git a/app/Controllers/Refactoring/Capsulation/Refactoring/Exam1.php b/app/Controllers/Refactoring/Capsulation/Refactoring/Exam1.php new file mode 100644 index 0000000..7a61b1e --- /dev/null +++ b/app/Controllers/Refactoring/Capsulation/Refactoring/Exam1.php @@ -0,0 +1,29 @@ + '홍길동', 'country' => 'KR']; +} + +/** + * Description of Exam1 + * + * @author hoksi + */ +class Exam1 extends BaseController +{ + public function index() + { + $organization = getRawDataOfOrganization(); + $result = "[h1]{$organization['name']}[/h1]"; + $organization['name'] = '김삿갓'; + + echo '
';
+        echo "result : {$result}\n";
+        echo "organization : " . print_r($organization, true) . "\n";
+        echo '
'; + } +} \ No newline at end of file diff --git a/app/Controllers/Response/Parser/Exam4.php b/app/Controllers/Response/Parser/Exam4.php new file mode 100644 index 0000000..725fbcd --- /dev/null +++ b/app/Controllers/Response/Parser/Exam4.php @@ -0,0 +1,31 @@ + 'My Blog Title', + 'blog_heading' => 'My Blog Heading', + 'blog_entries' => [ + ['title' => 'Title 1', 'body' => 'Body 1'], + ['title' => 'Title 2', 'body' => 'Body 2'], + ['title' => 'Title 3', 'body' => 'Body 3'], + ['title' => 'Title 4', 'body' => 'Body 4'], + ['title' => 'Title 5', 'body' => 'Body 5'], + ], + ]; + + return parser('response/parser/exam4', $data); + } +} \ No newline at end of file diff --git a/app/Helpers/parser_helper.php b/app/Helpers/parser_helper.php new file mode 100644 index 0000000..b2be09b --- /dev/null +++ b/app/Helpers/parser_helper.php @@ -0,0 +1,15 @@ +setData($data) + ->renderString(\Config\Services::renderer()->setData($data, 'raw')->render($name, $options, $saveData), $options, $saveData); +} diff --git a/app/Views/refactoring/basic/home.php b/app/Views/refactoring/basic/home.php index 3a2109e..f4c0cca 100644 --- a/app/Views/refactoring/basic/home.php +++ b/app/Views/refactoring/basic/home.php @@ -164,7 +164,7 @@ function moreThan100($anOrder) -

함수 이름 바꾸기

+

함수 선언 바꾸기

함수 이름이 좋으면 함수 호출문만 보고도 무슨 일을 하는지 파악할 수 있습니다.
@@ -245,6 +245,171 @@ function circumference($radius) + +

매개변수 객체 만들기

+ +

+ 함수의 데이터 항목이 여러개인 경우 데이터 구조 하나로 모아줍니다.
+ 데이터 구조로 묶으면 데이터 사이의 관계가 명확해지고 매개변수 수가 줄어듭니다. +

+ +
    +
  1. 적당한 데이터 구조가 아직 마련되어 있지 않다면 새로 만든다.
  2. +
  3. 테스트한다.
  4. +
  5. 함수 선언 바꾸기로 새 데이터 구조를 매개변수로 추가한다.
  6. +
  7. 테스트한다.
  8. +
  9. 함수 호출 시 새로운 데이터 구조 인스턴스를 넘기도록 수정한다. 하나씩 수정할 때 마다 테스트한다.
  10. +
  11. 기존 매개변수를 사용하던 코드를 새 데이터 구조의 원소를 사용하도록 바군다.
  12. +
  13. 다 바꿨다면 기존 매개변수를 제거하고 테스트한다.
  14. +
+ + 'Exam5Show', + 'title' => '/refactoring/basic/exam5', + 'href' => '/refactoring/basic/exam5', + ], + [ + 'id' => 'Exam5', + 'title' => 'Exam5.php', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Exam5', + ], + [ + 'id' => 'ReftExam5Show', + 'title' => '/refactoring/basic/refactoring/exam5', + 'href' => '/refactoring/basic/refactoring/exam5', + ], + [ + 'id' => 'ReftExam5', + 'title' => 'Exam5.php(Refactoring)', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Refactoring/Exam5', + ], + ]) ?> + + + +

여러 함수를 클래스로 묶기

+ +

+ 공통의 데이터를 중심으로 긴밀하게 엮여 작동하는 함수들을 클래스 하나로 묶어줍니다.
+ 클래스로 묶으면 이 함수들이 공유하는 공통 환경을 더 명확하게 표현할 수 있고, 각 함수에 전달되는 인수를 줄여서 객체 안세서의 + 함수 호출을 간결하게 만들 수 있습니다. +

+ +
    +
  1. 함수들이 공유하는 공통 데이터 레코드를 캡슐화한다.
  2. +
  3. 공통 레코드를 사용하는 함수 각각을 새 클래스로 옮긴다.
  4. +
  5. 데이터를 조작하는 로직들은 함수로 추출해서 새 클래스로 옮긴다.
  6. +
+ + 'Exam6Show', + 'title' => '/refactoring/basic/exam6', + 'href' => '/refactoring/basic/exam6', + ], + [ + 'id' => 'Exam6', + 'title' => 'Exam6.php', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Exam6', + ], + [ + 'id' => 'ReftExam6Show', + 'title' => '/refactoring/basic/refactoring/exam6', + 'href' => '/refactoring/basic/refactoring/exam6', + ], + [ + 'id' => 'ReftExam6', + 'title' => 'Exam6.php(Refactoring)', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Refactoring/Exam6', + ], + ]) ?> + + + +

여러 함수를 변환 함수로 묶기

+ +

+ 여러 함수에서 도출 로직이 반복되어 사용되다면 변환 함수로 묶어준다.
+ 변환 함수는 원본 데이터를 입력받아서 피룡한 정보를 모두 도출한 뒤, 각각을 출력 데이터의 필드에 넣어 반환한다.
+ 이렇게 해두면 도출 과정을 검토할 일이 생겼을 대 변환 함수만 살펴보면 된다. +

+ +
    +
  1. 변환할 레코드를 입력받아서 값을 그대로 반환하는 변환 함수를 만든다.
  2. +
  3. 묶을 함수중 하나를 골라서 본문 코드를 변환 함수로 옮기고, 처리 결과를 레코드에 새 필드로 기록한다.
  4. +
  5. 클라이언트 코드가 이 필드를 사용하도록 수정한다.
  6. +
  7. 테스트한다.
  8. +
  9. 나머지 관련 함수도 위 과정에 따라 처리한다.
  10. +
+ + 'Exam7Show', + 'title' => '/refactoring/basic/exam7', + 'href' => '/refactoring/basic/exam7', + ], + [ + 'id' => 'Exam7', + 'title' => 'Exam7.php', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Exam7', + ], + [ + 'id' => 'ReftExam7Show', + 'title' => '/refactoring/basic/refactoring/exam7', + 'href' => '/refactoring/basic/refactoring/exam7', + ], + [ + 'id' => 'ReftExam7', + 'title' => 'Exam7.php(Refactoring)', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Refactoring/Exam7', + ], + ]) ?> + + + +

단계 쪼개기

+ +

+ 서로 다른 두 대상을 한꺼번에 다루는 코드를 발견하면 각각을 별개 모듈로 나누는 방법을 모색한다.
+ 모듈이 잘 분리되어 있다면 다른 모듈의 상세 내용은 기억하지 못해도 원하는 대로 수정을 끝마칠 수도 있다. +

+ +
    +
  1. 두 번째 단계에 해당하는 코드를 독립 함수로 추출한다.
  2. +
  3. 테스트한다.
  4. +
  5. 중간 데이터 구조를 만들어서 앞에서 추출한 함수의 인수로 추가한다.
  6. +
  7. 테스트한다.
  8. +
  9. 추출한 두 번째 단계 함수의 매개변수를 하나씩 검토한다.
  10. +
  11. 그중 첫 번째 단계에서 사용되는 것은 중간 데이터 구조로 옮긴다.
  12. +
  13. 하나씩 옮길 때마다 테스트한다.
  14. +
  15. 첫 번째 단계 코드를 함수로 추출하면서 중간 데이터 구조를 반환하도록 만든다.
  16. +
+ + 'Exam8Show', + 'title' => '/refactoring/basic/exam8', + 'href' => '/refactoring/basic/exam8', + ], + [ + 'id' => 'Exam8', + 'title' => 'Exam8.php', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Exam8', + ], + [ + 'id' => 'ReftExam8Show', + 'title' => '/refactoring/basic/refactoring/exam8', + 'href' => '/refactoring/basic/refactoring/exam8', + ], + [ + 'id' => 'ReftExam8', + 'title' => 'Exam8.php(Refactoring)', + 'href' => '/sample/home/view/Controllers/Refactoring/Basic/Refactoring/Exam8', + ], + ]) ?> + + endSection() ?> \ No newline at end of file diff --git a/app/Views/refactoring/capsulation/home.php b/app/Views/refactoring/capsulation/home.php new file mode 100644 index 0000000..188a0ea --- /dev/null +++ b/app/Views/refactoring/capsulation/home.php @@ -0,0 +1,58 @@ +extend('sample/layout') ?> + +section('content') ?> +
+ + + +
+ +

레코드 캡슐화하기

+ +

+ 데이터 레코드와 같은 가변 데이타를 저장할 때 객체를 사용합니다.
+ 객체를 사용하면 저장된 값에 대해 무엇을 어떻게 저장했는지 숨길수 있으며(캐슐화), 필드의 이름이 바뀌어도 동일한 메서드를 통해 제공 받을수 있습니다. +

+ +
    +
  1. 레코드를 담은 변수를 캡슐화한다.
  2. +
  3. 레코드를 감싼 단순한 클래스로 해당 변수의 내용을 교체한다.
  4. +
  5. 이 클레스에 원본 레코드를 반환하는 접근자도 정의하고, 변수를 캡슐화하는 함수들이 이 접근자를 사용하도록 수정한다.
  6. +
  7. 테스트한다.
  8. +
  9. 원본 레코드 대신 새로 정의한 클래스 타입의 객체를 반환하는 함수들을 새로 만든다.
  10. +
  11. 레코드를 반환하는 예전 함수를 사용하는 코드를 5에서 만든 새 함수를 사용하도록 바꾼다.
  12. +
  13. 필드에 접근할 때는 객체의 접근자를 사용한다.
  14. +
  15. 적절한 접근자가 없다면 추가한다.
  16. +
  17. 한 부분을 바꿀 때마다 테스트한다.
  18. +
  19. 클래스에서 원본 데이터를 반환하는 접근자와 3에서 검색하기 쉬운 이름을 붙여둔 원본 레코드를 반환하는 함수들을 제거한다.
  20. +
  21. 테스트한다.
  22. +
  23. 레코드의 필드도 데이터 구조인 중첩 구조라면 레코드 캡슐화하기와 컬렉션 캡슐화하기를 재귀적으로 적용한다.
  24. +
+ + 'Exam1Show', + 'title' => '/refactoring/capsulation/exam1', + 'href' => '/refactoring/capsulation/exam1', + ], + [ + 'id' => 'Exam1', + 'title' => 'Exam1.php', + 'href' => '/sample/home/view/Controllers/Refactoring/Capsulation/Exam1', + ], + [ + 'id' => 'ReftExam1Show', + 'title' => '/refactoring/capsulation/refactoring/exam1', + 'href' => '/refactoring/capsulation/refactoring/exam1', + ], + [ + 'id' => 'ReftExam1', + 'title' => 'Exam1.php(Refactoring)', + 'href' => '/sample/home/view/Controllers/Refactoring/Capsulation/Refactoring/Exam1', + ], + ]) ?> + + +
+
+endSection() ?> \ No newline at end of file diff --git a/app/Views/response/parser/exam4.php b/app/Views/response/parser/exam4.php new file mode 100644 index 0000000..d8acdc7 --- /dev/null +++ b/app/Views/response/parser/exam4.php @@ -0,0 +1,13 @@ + + + <?= $blog_title ?> + + +

{blog_heading}

+ + {blog_entries} +
{title}
+

{body}

+ {/blog_entries} + + \ No newline at end of file diff --git a/app/Views/response/parser/home.php b/app/Views/response/parser/home.php index 6c7a0ad..7f3932d 100644 --- a/app/Views/response/parser/home.php +++ b/app/Views/response/parser/home.php @@ -8,17 +8,20 @@
-

뷰 파서는 뷰 파일에 포함된 유사 변수에 대한 간단한 텍스트 대체를 수행합니다. 간단한 변수 또는 변수 태그 쌍을 구문 분석할 수 있습니다.

-

유사 변수 또는 제어 구문은 중괄호({})로 묶습니다

-

이러한 유사변수는 실제 PHP 변수가 아니며 템플릿(뷰 파일)에서 PHP 코드를 제거할 수 있는 일반 텍스트 표현입니다.

+

+ 뷰 파서는 뷰 파일에 포함된 유사 변수에 대한 간단한 텍스트 대체를 수행합니다. 간단한 변수 또는 변수 태그 쌍을 구문 분석할 수 있습니다.
+ 유사 변수 또는 제어 구문은 중괄호({})로 묶습니다
+ 이러한 유사변수는 실제 PHP 변수가 아니며 템플릿(뷰 파일)에서 PHP 코드를 제거할 수 있는 일반 텍스트 표현입니다. +

+ + 'blog_templateView', + 'title' => 'blog_template.php', + 'href' => '/sample/home/view/Views/response/parser/blog_template', + ], + ]) ?> - 'blog_templateView', - 'title' => 'blog_template.php', - 'href' => '/sample/home/view/Views/response/parser/blog_template', - ], - ]) ?>

뷰 파서 클래스 사용하기

@@ -33,82 +36,124 @@

파서가 하는 일

-

`Parser` 클래스는 어플리케이션의 뷰 경로에 저장된 “PHP/HTML 스크립트”를 처리합니다. 이 스크립트는 PHP 코드를 포함할 수 없습니다.

-

각 뷰의 매개 변수(의사 변수라고 함)는 사용자가 제공한 값의 유형에 따라 대체를 유발합니다. 유사 변수는 PHP 변수로 추출되지 않습니다. 그 대신 값은 유사 변수 구문을 통해 액세스되며 이름은 중괄호 안에서 참조됩니다.

-

`Parser` 클래스는 내부적으로 연관 배열을 사용하여 `render()`를 호출할 때까지 의사 변수 설정을 누적합니다. 이는 의사 변수 이름이 고유해야 하거나, 나중에 설정된 매개 변수가 같은 이름의 이전 매개 변수보다 우선함을 의미합니다.

-

또한 스크립트 내부의 다른 컨텍스트에 대한 이스케이프 매개 변수 값에 영향을 줍니다. 이스케이프된 각 값에 고유한 매개 변수 이름을 지정해야 합니다.

+

+ `Parser` 클래스는 어플리케이션의 뷰 경로에 저장된 “PHP/HTML 스크립트”를 처리합니다. 이 스크립트는 PHP 코드를 포함할 수 없습니다.
+ 각 뷰의 매개 변수(의사 변수라고 함)는 사용자가 제공한 값의 유형에 따라 대체를 유발합니다. 유사 변수는 PHP 변수로 추출되지 않습니다. 그 대신 값은 유사 변수 구문을 통해 액세스되며 이름은 중괄호 안에서 참조됩니다.
+ `Parser` 클래스는 내부적으로 연관 배열을 사용하여 `render()`를 호출할 때까지 의사 변수 설정을 누적합니다. 이는 의사 변수 이름이 고유해야 하거나, 나중에 설정된 매개 변수가 같은 이름의 이전 매개 변수보다 우선함을 의미합니다.
+ 또한 스크립트 내부의 다른 컨텍스트에 대한 이스케이프 매개 변수 값에 영향을 줍니다. 이스케이프된 각 값에 고유한 매개 변수 이름을 지정해야 합니다. +

파서 템플릿

-

`render()` 메소드를 사용하여 다음과 같이 간단한 템플릿을 구문 분석(또는 렌더링)할 수 있습니다.

-

뷰 파라미터는 템플릿에서 교체할 데이터의 연관 배열로 setData()에 전달됩니다. 다음 예제에서 템플릿은 두 개의 변수 `{blog_title}`과 `{blog_heading}`를 포함합니다.

-

`render()`의 첫 번째 매개 변수는 뷰 파일의 이름입니다. 여기서 `blog_template`가 뷰 파일의 이름입니다.

+

+ `render()` 메소드를 사용하여 다음과 같이 간단한 템플릿을 구문 분석(또는 렌더링)할 수 있습니다.
+ 뷰 파라미터는 템플릿에서 교체할 데이터의 연관 배열로 setData()에 전달됩니다. 다음 예제에서 템플릿은 두 개의 변수 `{blog_title}`과 `{blog_heading}`를 포함합니다.
+ `render()`의 첫 번째 매개 변수는 뷰 파일의 이름입니다. 여기서 `blog_template`가 뷰 파일의 이름입니다. +

+ + 'RenderShow', + 'title' => '/response/parser/render', + 'href' => '/response/parser/render', + ], + [ + 'id' => 'Render', + 'title' => 'Render.php', + 'href' => '/sample/home/view/Controllers/Response/Parser/Render', + ], + [ + 'id' => 'RenderView', + 'title' => 'blog_template.php', + 'href' => '/sample/home/view/Views/response/parser/blog_template', + ], + ]) ?> - 'Render', - 'title' => 'Render.php', - 'href' => '/sample/home/view/Controllers/Response/Parser/Render', - ], - [ - 'id' => 'RenderView', - 'title' => 'blog_template.php', - 'href' => '/sample/home/view/Views/response/parser/blog_template', - ], - [ - 'id' => 'RenderShow', - 'title' => '/response/parser/render', - 'href' => '/response/parser/render', - ], - ]) ?>

대체 변형

-

대체 유형은 `simple, looping, nested` 세 가지가 지원됩니다. 유사 변수가 추가된 것과 동일한 순서로 대체가 수행됩니다.

-

파서가 수행하는 단순 치환은 아래 예에서와 같이 해당 데이터 매개 변수에 스칼라 또는 문자열 값이 있는 의사 변수의 일대일 대체입니다.

+

+ 대체 유형은 `simple`, `looping`, `nested` 세 가지가 지원되며 유사 변수는 추가된 순서로 대체가 수행됩니다.
+ 파서가 수행하는 단순 치환은 아래 예와 같이 해당 데이터 매개 변수에 의사 변수(스칼라 또는 문자열 값이 있는)의 일대일 대체입니다. +

+ + 'SimpleShow', + 'title' => '/response/parser/simple', + 'href' => '/response/parser/simple', + ], + [ + 'id' => 'Simple', + 'title' => 'Simple.php', + 'href' => '/sample/home/view/Controllers/Response/Parser/Simple', + ], + ]) ?> - 'Simple', - 'title' => 'Simple.php', - 'href' => '/sample/home/view/Controllers/Response/Parser/Simple', - ], - [ - 'id' => 'SimpleShow', - 'title' => '/response/parser/simple', - 'href' => '/response/parser/simple', - ], - ]) ?> - +

루프 대체

-

의사 변수의 값이 배열인 경우 루프 대체가 발생합니다.

-

다음 코드에서 한 쌍의 변수 `{blog_entries} data… {/blog_entries}`를 볼 수 있습니다.

-

이와 같은 경우 이들 쌍들 사이의 전체 데이터 청크는 파라미터 배열의 “blog_entries” 요소의 행 수에 대응하여 여러 번 반복 됩니다.

-

변수 쌍 구문 분석은 단일 변수를 구문 분석하기 위해 위에 표시된 동일한 코드를 사용하지만 데이터에 다차원 배열을 추가합니다.

-

반복하려는 배열이 배열 대신 객체라면 파서는 먼저 객체에서 `asArray` 메소드를 찾습니다.

-

`asArray` 메소드가 존재한다면 해당 메소드를 호출하여 얻은 결과 배열을 위에서 설명한대로 반복합니다.

-

`asArray` 메소드가 없으면 객체가 배열로 캐스트(cast)되고 해당 퍼블릭 속성이 파서에 제공됩니다.

+

+ 의사 변수의 값이 배열인 경우 루프 대체가 발생합니다.
+ 다음 코드에서 한 쌍의 변수 `{blog_entries} data… {/blog_entries}`를 볼 수 있습니다.
+ 이와 같은 경우 이들 쌍들 사이의 전체 데이터 청크는 파라미터 배열의 “blog_entries” 요소의 행 수에 대응하여 여러 번 반복 됩니다.
+ 변수 쌍 구문 분석은 단일 변수를 구문 분석하기 위해 위에 표시된 동일한 코드를 사용하지만 데이터에 다차원 배열을 추가합니다.
+ 반복하려는 배열이 배열 대신 객체라면 파서는 먼저 객체에서 `asArray` 메소드를 찾습니다.
+ `asArray` 메소드가 존재한다면 해당 메소드를 호출하여 얻은 결과 배열을 위에서 설명한대로 반복합니다.
+ `asArray` 메소드가 없으면 객체가 배열로 캐스트(cast)되고 해당 퍼블릭 속성이 파서에 제공됩니다. +

+ + 'LoopShow', + 'title' => '/response/parser/loop', + 'href' => '/response/parser/loop', + ], + [ + 'id' => 'LoopView', + 'title' => 'blog_template.php', + 'href' => '/sample/home/view/Views/response/parser/blog_template', + ], + [ + 'id' => 'Loop', + 'title' => 'Loop.php', + 'href' => '/sample/home/view/Controllers/Response/Parser/Loop', + ], + ]) ?> + + + +

뷰와 파서 연동

+ +

+ 간단한 사용자 헬퍼를 만들어 뷰와 파서를 연동하여 함께 사용할 수 있습니다. +

+ + 'Exam4Show', + 'title' => '/response/parser/exam4', + 'href' => '/response/parser/exam4', + ], + [ + 'id' => 'Exam4View', + 'title' => 'exam4.php', + 'href' => '/sample/home/view/Views/response/parser/exam4', + ], + [ + 'id' => 'Exam4', + 'title' => 'Exam4.php', + 'href' => '/sample/home/view/Controllers/Response/Parser/Exam4', + ], + [ + 'id' => 'parserHelper', + 'title' => 'parser_helper.php', + 'href' => '/sample/home/view/Helpers/parser_helper', + ], + ]) ?> - 'LoopView', - 'title' => 'blog_template.php', - 'href' => '/sample/home/view/Views/response/parser/blog_template', - ], - [ - 'id' => 'Loop', - 'title' => 'Loop.php', - 'href' => '/sample/home/view/Controllers/Response/Parser/Loop', - ], - [ - 'id' => 'LoopShow', - 'title' => '/response/parser/loop', - 'href' => '/response/parser/loop', - ], - ]) ?>
endSection() ?> \ No newline at end of file From 3d42ea75df591323590c36208fb5b4b9f5114114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=95=9C=EB=8C=80=EC=8A=B9?= Date: Wed, 27 Oct 2021 10:45:55 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=EB=A9=94=EC=9D=B8=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Controllers/Home.php | 6 +++++- app/Views/sample/layout.php | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/Controllers/Home.php b/app/Controllers/Home.php index 43707c4..948b140 100644 --- a/app/Controllers/Home.php +++ b/app/Controllers/Home.php @@ -6,6 +6,10 @@ class Home extends BaseController { public function index() { - return $this->response->redirect('/sample'); + return view('sample/sample', [ + 'title' => 'ci4Sample', + 'location' => 'home', + 'menu' => '', + ]); } } diff --git a/app/Views/sample/layout.php b/app/Views/sample/layout.php index 921655c..498fb09 100644 --- a/app/Views/sample/layout.php +++ b/app/Views/sample/layout.php @@ -73,7 +73,7 @@ function gtag(){dataLayer.push(arguments);}