php - 如何使用 OOP 改进代码
php - how to improve code with OOP
这可能已被讨论过多次,但我想知道 OOP 如何帮助我改进代码。
我曾经以程序方式编码。但是有一个合理的逻辑。整个项目中使用的代码片段都封装在函数中。但是所有函数都放在一个大的 functions.php 文件中(我发现效率不高)。
例如,这是一个检查销售是否过期的函数:
function is_sales_expired($salesId, PDO $conn) {
$now=time();
$sql="SELECT * FROM specialoffers WHERE id=:id";
$st=$conn->prepare($sql);
$st->bindvalue(":id",$salesId,PDO::PARAM_STR);
$st->execute();
$sales_array=$st->fetchAll();
if($now<$sales_array[0]['finishdate'] && $now>$sales_array[0]['startdate']) {
return FALSE;
} else {
return TRUE;
}
}
现在我决定转向 OOP 并将我的代码转换为 OOP。所以我创建了 classes 并将与特定行为相关的功能放入每个 class 中。例如 sales class 有一个 is_sales_expired()
和其他与销售相关的方法。属性和构造函数如下所示:
class Sales
{
private $conn;
private $stockObj;
private $userObj;
private $cartObj;
private $randomObj;
function __construct(PDO $conn)
{
$this->conn = $conn;
$this->stockObj = new Stock($this->conn);
$this->userObj = new User($this->conn);
$this->cartObj = new Cart($this->conn);
$this->randomObj = new Random($this->conn);
}
//methods come here//
}
然后我使用 spl_autoload_register
在我的代码中加载 classes,这样我就不必在每个其他文件中包含所有 class 文件。好吧,使用这种方法,调用方法会更容易一些,我不需要将 PDO $conn
传递给每个方法调用,它已经通过构造函数传递了。
好吧,这些都很好,所有相关代码现在都在一个地方,也许更容易管理一些。但我有一种感觉,OOP 应该提供更多。使用我使用的方法,我不觉得现在我的代码更有效率和可维护性。我觉得我应该在这里错过一些概念。
感谢您的帮助。
您已经开始将代码组织到对象中,这很好,这是向更好的应用程序结构迈出的一步。
一旦你开始深入研究它,你就会找到将当前对象拆分成更小的部分并以更好的方式组织它们的方法,用更少的代码以更灵活的方式解决更多的问题。
例如,在您的代码中,业务逻辑仍然与数据库紧密耦合。如果您决定使用 mysqli
而不是 PDO
怎么办?您必须触摸应用程序中的每个 class。
但是如果数据库交互被提取到您的业务逻辑使用的自己的一组对象中,那么替换数据库访问层会容易得多。事实上,在这种情况下,您可以很容易地将 MySQL 替换为 PostgreSQL 甚至是普通文件。
我可以想到两种方法来进一步了解 OOP 的工作原理:阅读 book 或从现有代码中学习。
我链接的这本书是我最喜欢的 OOP 书,它展示了一些很好的例子,说明如何通过将程序分解为 co-operating 个对象来使用 OOP 解决问题。
而且我还建议开始使用一些 OOP 框架,我过去在 Yii 方面有过一些很好的经验,请查看 guide 以了解它的外观。您会看到大量有用的对象解决了您在开发 Web 应用程序时必须一直解决的各种问题。
尝试使用它构建一些简单的应用程序,然后尝试查看框架代码内部以查看其实际工作原理。
还有一个建议是研究自动测试。这不仅会让您的应用程序保持活力,还会教您如何组合更好的对象。您必须在两种不同的情况下使用您的 classes - 您的实际代码和测试。在内部测试中,您需要将要测试的对象与其余代码隔离开来,例如,在不接触数据库的情况下测试销售统计算法。而且您必须将代码拆分成更小、更灵活的结构才能做到这一点。
您的开端不错,开始思考对象架构需要时间。 OOP 的优势在于它可以模拟您的代码必须交互的事物。所以想想它需要处理的事情和它需要做的动作。因此,在您的示例中,您可以拥有一个新的 class SpecialOffers,它将处理与您的特价商品 table 相关的所有事情。
例如:
class SpecialOffers {
function __construct(PDO $conn)
{
// this is connected to the server table
$this->conn = $conn;
}
// get the details of a special offer
private function get($salesId) {
$sql="SELECT * FROM specialoffers WHERE id=:id LIMIT 1";
$st=$this->conn->prepare($sql);
$st->bindvalue(":id",$salesId,PDO::PARAM_STR);
$st->execute();
$rows = $st->fetchAll();
if (count($rows) > 0) {
return $rows[0];
} else {
return null;
}
}
// answers whether a particular sales is active
public function isActive($salesId) {
$answer = $this->get($salesId);
if (isset($answer['finishdate']) && isset($answer['startdate'])) {
$now=time();
return $now<$answer['finishdate'] && $now>$answer['startdate'];
} else {
return false;
}
}
}
还有很多事情要做,比如错误处理,但你可以看到它是如何随着事情的发展而变得更加明显的,你只想着特价。它们是如何工作的?会出什么问题?
最后,在考虑 class 的范围时,最好的建议来自 SOLID 原则。第一个,S——单一职责原则:
a class should have only a single responsibility (i.e. only one
potential change in the software's specification should be able to
affect the specification of the class)
最好的class可以用一句话来形容。方法也一样,一句话描述它的作用。
这可能已被讨论过多次,但我想知道 OOP 如何帮助我改进代码。 我曾经以程序方式编码。但是有一个合理的逻辑。整个项目中使用的代码片段都封装在函数中。但是所有函数都放在一个大的 functions.php 文件中(我发现效率不高)。 例如,这是一个检查销售是否过期的函数:
function is_sales_expired($salesId, PDO $conn) {
$now=time();
$sql="SELECT * FROM specialoffers WHERE id=:id";
$st=$conn->prepare($sql);
$st->bindvalue(":id",$salesId,PDO::PARAM_STR);
$st->execute();
$sales_array=$st->fetchAll();
if($now<$sales_array[0]['finishdate'] && $now>$sales_array[0]['startdate']) {
return FALSE;
} else {
return TRUE;
}
}
现在我决定转向 OOP 并将我的代码转换为 OOP。所以我创建了 classes 并将与特定行为相关的功能放入每个 class 中。例如 sales class 有一个 is_sales_expired()
和其他与销售相关的方法。属性和构造函数如下所示:
class Sales
{
private $conn;
private $stockObj;
private $userObj;
private $cartObj;
private $randomObj;
function __construct(PDO $conn)
{
$this->conn = $conn;
$this->stockObj = new Stock($this->conn);
$this->userObj = new User($this->conn);
$this->cartObj = new Cart($this->conn);
$this->randomObj = new Random($this->conn);
}
//methods come here//
}
然后我使用 spl_autoload_register
在我的代码中加载 classes,这样我就不必在每个其他文件中包含所有 class 文件。好吧,使用这种方法,调用方法会更容易一些,我不需要将 PDO $conn
传递给每个方法调用,它已经通过构造函数传递了。
好吧,这些都很好,所有相关代码现在都在一个地方,也许更容易管理一些。但我有一种感觉,OOP 应该提供更多。使用我使用的方法,我不觉得现在我的代码更有效率和可维护性。我觉得我应该在这里错过一些概念。 感谢您的帮助。
您已经开始将代码组织到对象中,这很好,这是向更好的应用程序结构迈出的一步。 一旦你开始深入研究它,你就会找到将当前对象拆分成更小的部分并以更好的方式组织它们的方法,用更少的代码以更灵活的方式解决更多的问题。
例如,在您的代码中,业务逻辑仍然与数据库紧密耦合。如果您决定使用 mysqli
而不是 PDO
怎么办?您必须触摸应用程序中的每个 class。
但是如果数据库交互被提取到您的业务逻辑使用的自己的一组对象中,那么替换数据库访问层会容易得多。事实上,在这种情况下,您可以很容易地将 MySQL 替换为 PostgreSQL 甚至是普通文件。
我可以想到两种方法来进一步了解 OOP 的工作原理:阅读 book 或从现有代码中学习。
我链接的这本书是我最喜欢的 OOP 书,它展示了一些很好的例子,说明如何通过将程序分解为 co-operating 个对象来使用 OOP 解决问题。
而且我还建议开始使用一些 OOP 框架,我过去在 Yii 方面有过一些很好的经验,请查看 guide 以了解它的外观。您会看到大量有用的对象解决了您在开发 Web 应用程序时必须一直解决的各种问题。 尝试使用它构建一些简单的应用程序,然后尝试查看框架代码内部以查看其实际工作原理。
还有一个建议是研究自动测试。这不仅会让您的应用程序保持活力,还会教您如何组合更好的对象。您必须在两种不同的情况下使用您的 classes - 您的实际代码和测试。在内部测试中,您需要将要测试的对象与其余代码隔离开来,例如,在不接触数据库的情况下测试销售统计算法。而且您必须将代码拆分成更小、更灵活的结构才能做到这一点。
您的开端不错,开始思考对象架构需要时间。 OOP 的优势在于它可以模拟您的代码必须交互的事物。所以想想它需要处理的事情和它需要做的动作。因此,在您的示例中,您可以拥有一个新的 class SpecialOffers,它将处理与您的特价商品 table 相关的所有事情。
例如:
class SpecialOffers {
function __construct(PDO $conn)
{
// this is connected to the server table
$this->conn = $conn;
}
// get the details of a special offer
private function get($salesId) {
$sql="SELECT * FROM specialoffers WHERE id=:id LIMIT 1";
$st=$this->conn->prepare($sql);
$st->bindvalue(":id",$salesId,PDO::PARAM_STR);
$st->execute();
$rows = $st->fetchAll();
if (count($rows) > 0) {
return $rows[0];
} else {
return null;
}
}
// answers whether a particular sales is active
public function isActive($salesId) {
$answer = $this->get($salesId);
if (isset($answer['finishdate']) && isset($answer['startdate'])) {
$now=time();
return $now<$answer['finishdate'] && $now>$answer['startdate'];
} else {
return false;
}
}
}
还有很多事情要做,比如错误处理,但你可以看到它是如何随着事情的发展而变得更加明显的,你只想着特价。它们是如何工作的?会出什么问题?
最后,在考虑 class 的范围时,最好的建议来自 SOLID 原则。第一个,S——单一职责原则:
a class should have only a single responsibility (i.e. only one potential change in the software's specification should be able to affect the specification of the class)
最好的class可以用一句话来形容。方法也一样,一句话描述它的作用。