Xin chào mọi người, đây sẽ là bài viết cuối cùng trong các bài viết về Lập trình hướng đối tượng trong PHP. Ở 2 phần trước mình đã nói tổng quan về lập trình hướng đối tượng trong PHP. Bài viết này mình sẽ nói đến chuẩn PSR và SOLID. Đây là những chuẩn về coding convention trong lập trình PHP. Mong rằng mọi người có thể hiểu và áp dụng chúng vào những dòng code của mình. PSR - PHP Standard RecommendationPSR là 1 đặc tả PHP được xuất bản bởi PHP Framework Interop Group. Nó đưa ra các tiêu chuẩn để chuẩn hóa các khái niệm trong lập trình PHP. Tiêu chuẩn này được các lập trình viên, tổ chức chấp nhận sử dụng. Lý do bạn nên viết code theo chuẩn PSR:- Là tiêu chuẩn được áp dụng vào các dự án lớn hoặc framework PHP
- Việc viết code chuẩn giúp không chỉ có bạn mà người đọc code, hay người sẽ tiếp tục tham gia vào dự án, bảo trì có thể hiểu code hơn
- Có sự thống nhất trong cách thức viết code, tổ chức các class...
- Dễ dàng trong đọc, hiểu code
PSR-2: Coding Style GuideTiêu chuẩn này thừa kế và mở rộng của tiêu chuẩn PSR-1. Tiêu chuẩn này là về 1 số quy tắc cú pháp trong code. - Code PHẢI tuân thủ PSR-1
- Code PHẢI sử dụng 4 khoảng trắng thay vì tab để lùi vào
- Không có giới hạn cứng về độ dài của dòng, giới hạn mềm PHẢI là 120 ký tự, dòng NÊN có 80 ký tự trở xuống
- PHẢI có 1 dòng trống sau khai báo
$shapes = array(
new Circle(2),
new Square(5),
new Square(6)
);
$areas = new AreaCalculator($shapes);
$output = new SumCalculatorOutputter($areas);
echo $output->JSON();
echo $output->HAML();
echo $output->HTML();
echo $output->JADE();
8, và PHẢI có 1 dòng trống sau khổi khai báo $shapes = array(
new Circle(2),
new Square(5),
new Square(6)
);
$areas = new AreaCalculator($shapes);
$output = new SumCalculatorOutputter($areas);
echo $output->JSON();
echo $output->HAML();
echo $output->HTML();
echo $output->JADE();
9 - Ký tự
public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
0 mở 1 class PHẢI ở dòng tiếp theo và public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
1 đóng class PHẢI ở dòng tiếp theo sau phần nội dung class - Ký tự
public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
0 cho phương thức PHẢI ở dòng tiếp theo và public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
1 PHẢI ở dòng tiếp theo sau phần nội dung - Các visibility PHẢI được khai báo trên tất cả các thuộc tính và phương thức.
public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
4 và public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
5 phải được khai báo trước visibility, public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
6 PHẢI được khai báo sau visibility - Các từ khóa của cấu trúc điểu khiển PHẢI có 1 khoảng trắng sau chúng, việc gọi phương thức và hàm thì không phải
- Ký tự
public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
0 của các cấu trúc điều khiển PHẢI ở cùng hàng và ký tự public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
1 PHẢI ở hàng tiếp theo sau phần nội dung - Ký tự
public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
9 cho các cấu trúc điểu khiển KHÔNG PHẢI có khoảng trắng sau chúng, và ký tự class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
0 KHÔNG PHẢI có khoảng trắng trước nó
PSR-0 và PSR-4: Autoloading StandardPSR-0Tiêu chuẩn này đã không còn được chấp nhận từ 21/10/2014 và được chấp nhận thay thế bằng chuẩn PSR-4. PSR-4Tiêu chuẩn PSR-4 mô tả các đặc điểm kỹ thuật cho việc tự động tải các class từ đường dẫn tập tin. Nó hoàn toàn tương thích và có thể được sử dụng ngoài bất kỳ mục nào khác của đặc tả tự động tải, bao gồm PSR-0. PSR này cũng mô tả nơi để đặt các tệp sẽ được tự động tri theo đặc điểm kỹ thuật. Thuật ngữ "class" đề cập đến các class, interface, trait và các loại cấu trúc tương tự khác Tên class tiêu chuẩn theo mẫu: class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
2- Tên class tiêu chuẩn PHẢI có namspace cấp cao nhất, có thể hiểu là vendor namespace
- Tên class tiêu chuẩn CÓ THỂ có 1 hoặc nhiều namespace con
- Tên class tiêu chuẩn PHẢI có 1 tên class kết thúc
- Dấu gạch dưới không có ý nghĩa đặc biệt trong bất kỳ phần nào của tên class tiêu chuẩn
- Ký tự trong tên class tiêu chuẩn CÓ THỂ kết hợp của ký tự thường và ký tự hoa
- Tất cả các tên class PHẢI được tham chiếu trong trường hợp phù hợp
Khi tải 1 tệp tương ứng với tên đẩy đủ của class Việc triển khai trình tự động tải KHÔNG ĐƯỢC ném (throw) các ngoại lệ, KHÔNG ĐƯỢC sinh thêm lỗi ở bất kỳ cấp độ nào và KHÔNG NÊN trả về giá trị Nguyên tắc thiết kế hướng đối tượng S.O.L.I.DS.O.L.I.D là 1 từ viết tắt cho 5 nguyên tắc thiết kế hướng đối tượng đầu tiên (OOD) của Robert C. Martin. Những nguyên tắc này khi kết hợp với nhau giúp cho người lập trình dễ dàng phát triển phần mềm cũng như dễ cho việc bảo trì và mở rộng. Vì mình cũng mới tìm hiểu phẩn này nên kiến thức có thể không chắc chắn ở 1 số phần. Nội dung sau đây mình lấy từ đây. Các bạn có thể tham khảo kỹ hơn. S - Single reponsibity principle: Nguyên tắc đơn nhiệm1 lớp nên có 1 và chỉ 1 lý do để thay đổi, có nghĩa là 1 lớp chỉ nên có 1 công việc.
Ví dụ, chúng ta có 1 vài hình và cần tính tổng diện tích các hình. class Circle {
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
}
class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
}
Đầu tiên, chúng ta tạo các class hình và có các class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
4 thiết lập các thông số cần thiết. Tiếp theo, chúng ta tạo class class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
5 và viết logic để tính tổng diện tích các hình.class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
Để sử dụng lớp AreaCalculator, chúng ta chỉ đơn giản là khởi tạo lớp và truyền vào 1 mảng các hình và hiển thị đầu ra. $shapes = array(
new Circle(2),
new Square(5),
new Square(6)
);
$areas = new AreaCalculator($shapes);
echo $areas->output();
Vấn đề với phương thức class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
6 là lớp AreaCalculator xử lý logic để xuất dữ liệu. Vì vậy, nếu người dùng muốn xuất dữ liệu như JSON hay 1 dạng gì khác thì sao?Tất cả các logic đó sẽ được xử lý bởi lớp Tất cả các logic đó sẽ được xử lý bởi lớp AreaCalculator, đây là không phù hợp với nguyên tắc đơn nhiệm. Lớp AreaCalculator nên chỉ tính tổng diện tích được cung cấp bởi các hình. Nó không nên quan tâm đến việc người dùng muốn trả về JSON hay HTML. Vì vậy để giải quyết vấn đề chúng ta có thể taọ lớp SumCalculatorOutputter và sử dụng nó để giải quyết bất kỳ vấn để gì về logic mà bạn bạn cần để xử lý cách tính tổng diện tích của tất cả các hình được cung cấp. Lớp SumCalculatorOutputter sẽ làm việc như sau: $shapes = array(
new Circle(2),
new Square(5),
new Square(6)
);
$areas = new AreaCalculator($shapes);
$output = new SumCalculatorOutputter($areas);
echo $output->JSON();
echo $output->HAML();
echo $output->HTML();
echo $output->JADE();
O - Open - closed principle: Nguyên tắc mở - đóngCác đối tượng hoặc thực thể nên được mở để mở rộng, nhưng đóng để sửa đổi.
Điều này đơn giản có nghĩa là 1 lớp nên dễ dàng để được mở rộng mà không sửa đổi chính lớp đó. Chúng ta xem xét phương thức class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
7 của lớp AreaCalculator.public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'Square')) {
$area[] = pow($shape->length, 2);
} else if(is_a($shape, 'Circle')) {
$area[] = pi() * pow($shape->radius, 2);
}
}
return array_sum($area);
}
Nếu chúng ta muốn phương thức class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
7 có thể tính tổng diện tích của 1 vài hình nữa thì chúng ta cần thêm các khối class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
9 và nó đi ngược lại nguyên tắc đóng - mở.1 cách mà chúng ta có thể làm cho phương thức class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
7 tốt hơn là loại bỏ phần logic tính diện tích của mỗi hình ra khỏi phương thức class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
7 và đính kém nó vào lơp của hình.class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
Bây giờ, để tính tổng của bất kỳ hình nào chúng ta có thể đơn giản phương thức class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
7 như sau:public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
Bây giờ, chúng ta có thể tạo 1 lớp đại diện cho hình khác và chuyển nó vào khi tính tổng mà không ảnh hưởng đến code. Tuy nhiên, bây giờ có 1 vấn đề khác nảy sinh, làm thế nào mà chúng ta biết rằng đối tượng được truyền vào trong AreaCalculator thực sự là 1 hình hoặc nếu hình có 1 phương thức tên là public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
3?Việc sử dụng public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
4 là 1 phần không thể thiếu của S.O.L.I.D, chúng ta tạo 1 public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
4 để mọi hình có thể public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
6:interface ShapeInterface
{
public function area();
}
class Circle implements ShapeInterface
{
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
public function area()
{
return pi() * pow($this->radius, 2);
}
}
Phương thức class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
7 của class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
5 có thể kiểm tra xem các hình được cung cấp có thực sự là trường hợp của public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
9 hay không, nếu không thì chúng ta có thể ném 1 ngoại lệ:public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'ShapeInterface')) {
$area[] = $shape->area();
continue;
}
throw new AreaCalculatorInvalidShapeException;
}
return array_sum($area);
}
L: Liskov substitution principle - Nguyên tắc thay thế LiskovGọi interface ShapeInterface
{
public function area();
}
class Circle implements ShapeInterface
{
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
public function area()
{
return pi() * pow($this->radius, 2);
}
}
0 là 1 thuộc tính có thể chứng minh được về các đối tượng của x của kiểu T. Sau đó, interface ShapeInterface
{
public function area();
}
class Circle implements ShapeInterface
{
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
public function area()
{
return pi() * pow($this->radius, 2);
}
}
1 phải được chứng minh cho các đối tượng y kiểu S, trong đó S là 1 kiểu con của T.
Tất cả những điểu trên có nghĩa là tất cả các lơp con / lớp dẫn xuất nên được thay thế cho các lớp cơ sở / lớp cha của chúng. Vẫn với việc sử dụng lớp class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
5, chúng ta có 1 lớp interface ShapeInterface
{
public function area();
}
class Circle implements ShapeInterface
{
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
public function area()
{
return pi() * pow($this->radius, 2);
}
}
3 thừa kế lớp class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
5:class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
Lớp interface ShapeInterface
{
public function area();
}
class Circle implements ShapeInterface
{
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
public function area()
{
return pi() * pow($this->radius, 2);
}
}
5:class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
0Nếu chúng ta thử chạy ví dụ trên như sau: class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
1Khi chúng ta gọi phương thức interface ShapeInterface
{
public function area();
}
class Circle implements ShapeInterface
{
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
public function area()
{
return pi() * pow($this->radius, 2);
}
}
6 trên đối tượng interface ShapeInterface
{
public function area();
}
class Circle implements ShapeInterface
{
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
public function area()
{
return pi() * pow($this->radius, 2);
}
}
7 thì sẽ trả về lỗi E_NOTICE thông báo chuyển đổi mảng sang chuỗi.Để giải quyết nó, thay vì trả về mảng từ phương thức class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
7 của lớp interface ShapeInterface
{
public function area();
}
class Circle implements ShapeInterface
{
public $radius;
public function __construct($radius)
{
$this->radius = $radius;
}
public function area()
{
return pi() * pow($this->radius, 2);
}
}
3, bạn nên đơn giản nó:class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
2I: Interface segregation principle - Nguyên tắc giao diện phân biệt1 khách hàng không bao giờ bị buộc phải public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
6 1 public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
4 mà nó không sử dụng hoắc các khách hàng không nên bị phụ thuộc vào các phương thức mà họ không sử dụng.
Vẫn với ví dụ trên, chúng ta biết rằng chúng ta cũng có hình dạng rắn nên chúng ta có thể muốn tính toán khối lượng của hình khối, chúng ta có thể thêm 1 "hợp đồng - contract" vào public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
9:class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
3Bất kỳ hình nào chúng ta tạo bắt buộc phải public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
6 phương thức public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'ShapeInterface')) {
$area[] = $shape->area();
continue;
}
throw new AreaCalculatorInvalidShapeException;
}
return array_sum($area);
}
4, nhưng chúng ta biết rằng hình vuông là hình phẳng và không có khối lượng, vì vậy public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
4 này sẽ bắt buộc lớp public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'ShapeInterface')) {
$area[] = $shape->area();
continue;
}
throw new AreaCalculatorInvalidShapeException;
}
return array_sum($area);
}
6 thực hiện 1 phương thức mà nó không sử dụng.Nguyên tắc này không cho phép thực hiện như vậy, thay vào đó bạn có thể tạo 1 giao diện khác gọi là public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'ShapeInterface')) {
$area[] = $shape->area();
continue;
}
throw new AreaCalculatorInvalidShapeException;
}
return array_sum($area);
}
7 có hợp đồng là public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'ShapeInterface')) {
$area[] = $shape->area();
continue;
}
throw new AreaCalculatorInvalidShapeException;
}
return array_sum($area);
}
4 và các hình dạng rắn như hình khối có thể triển khai giao diện này:class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
4Đây là 1 cách giải quyết tương đối tốt, nhưng đáng buồn là để xem khi loại gợi ý các giao diện này, thay vì sử dụng 1 public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
9 hoặc 1 public function sum()
{
foreach($this->shapes as $shape) {
if(is_a($shape, 'ShapeInterface')) {
$area[] = $shape->area();
continue;
}
throw new AreaCalculatorInvalidShapeException;
}
return array_sum($area);
}
7.Bạn có thể tạo 1 giao diện khác, ví dụ là class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
1 và public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
6 nó trong cả các lớp hình phẳng và hình khối rắn. Đây là cách mà bạn có thể dễ dàng thấy rằng nó có 1 API duy nhất để quản lý các hình.class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
5Bây giờ, trong lớp class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
5, chúng ta có thể dễ dàng thay thế việc gọi đến phương thức public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
3 với class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
5 và cũng kiểm tra nếu đối tượng là 1 thể hiện của class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
1 và không phải là public function sum()
{
foreach($this->shapes as $shape) {
$area[] = $shape->area();
}
return array_sum($area);
}
9.D: Dependency inversion principle - Nguyên tắc nghịch đảo phụ thuộcCác thực thể phải phụ thuộc vào sự trừu tượng hóa không phải là các concretion. Nó nói rằng mô-đun mức cao không được phụ thuộc vào mô-đun mức thấp, nhưng chúng phải phụ thuộc vào sự trừu tượng hóa.
Điều này có vẻ cồng kềnh, nhưng nó thực sự rất dễ hiểu. Nguyên tắc này cho phép tách rời. class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
6Đầu tiên, class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
8 là mô-đun cấp thấp trong khi class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
9 là mô-đun cấp cao, nhưng theo định nghĩa của D trong S.O.L.I.D nói rằng phụ thuộc vào trừu tượng hóa không trên concretion, đoạn mã trên vi phạm nguyên tắc này đối với lớp class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
9 bị buộc phụ thuộc vào lớp class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
8.Sau này, nếu bạn muốn thay đổi cơ sở dữ liệu, bạn cũng sẽ phải chỉnh sửa lớp class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
9 và vi phạm nguyên tắc O.Lớp class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
9 không nên quan tâm đến cơ sở dữ liệu mà ứng dụng đang sử dụng, để giải quyết vấn đề chúng ta "code vào 1 giao diện", vì các mô-đun mức cap và mức thấp nên phụ thuộc vào sự trừu tượng, chúng ta có thể tạo ra 1 giao diện như sau:class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
7Giao diện này có phương thức class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
04 và lớp class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
8 thực thi giao diện này. Cũng thay vì trực tiếp lớp class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
8 trong class Square {
public $length;
public function __construct($length)
{
$this->length = $length;
}
public function area()
{
return pow($this->length, 2);
}
}
4 của class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
9. Thay vào đó, chúng ta gợi ý giao diện và bất kể loại cơ sở dữ liệu nào mà ứng dụng của bạn đang sử dụng, lớp class VolumeCalculator extends AreaCalulator
{
public function __construct($shapes = array())
{
parent::__construct($shapes);
}
public function sum()
{
// logic to calculate the volumes and then return and array of output
return array($summedData);
}
}
9 có thể dễ dàng kết nối đến cơ sở dữ liệu mà không gặp bất kỳ vấn đề nào và nguyên lý O không bị vi phạm.class AreaCalculator {
protected $shapes;
public function __construct($shapes = array())
{
$this->shapes = $shapes;
}
public function sum()
{
// logic to sum the areas
}
public function output()
{
return implode('', array(
"",
"Sum of the areas of provided shapes: ",
$this->sum(),
""
));
}
}
8Thông qua đoạn mã ở trên, bây giờ bạn có thể thấy rằng cả mô-đun cấp cao và cấp thấp để phụ thuộc vào sự trừu tượng. Kết luậnPhần cuối này, bản thân mình tìm hiểu về nguyên tắc SOLID cũng đang vẫn tương đối mơ hồ. Mong rằng, chúng ta có thêm nhiều thời gian để cọ xát với các dự án thực tế để nắm bắt cũng như hiểu rõ thêm. Mình cũng xin cảm ơn nếu bạn nào cũng có lỡ đọc cả 3 bài về Lập trình hướng đối tượng trong PHP của mình. Bài viết còn tương đối thiếu sót do kiến thức của bản thân. Mong rằng những góp ý của các bạn giúp mình có thể tiến bộ hơn (bowbowbow). |