我是PHP OOP的新手(现在用程序风格编写PHP一段时间了)我认为我理解了SOLID原则,并且我理解一个对象并非必然等同于关系数据库中的实体。无论如何,我在将这些知识应用于这种实际情况时遇到了一些小问题:
我想写一个服务/处理产品数据的类,这是产品的属性(如产品名称,重量等),但也包括库存数量,未结订单,下一批货物(已交付日期和数量)和等等。
这就引发了一些问题:
创建一个服务于所有这些数据的类的计划是否会干扰单一责任原则(因此,提供库存数量的另一个责任是服务产品的重量)?换句话说:我是否应该为服务产品属性写一个额外的类,而另一个类用于提供库存数量,另一个类用于服务此产品的传入货物?解释:可能是,访问此类对象数据的外部代码不需要所有这些信息,只需要它的一部分(例如产品的属性或下一个传入的货物,但也许外部代码也需要两者)。
如果我要写两个不同的课程,他们是完全分开还是应该扩展另一个?我个人不明白为什么要扩展另一个,因为它总是只需要这两个中的一个,那么我为什么要将它们连接在一起呢。
我从过去的经验中知道,PHP应用程序的瓶颈通常是您发送到数据库接口的查询数。如果我将所有内容划分为不同的类,我有几个数据库查询,而如果我在一个类中有它,我只需要两个。
无论如何,如果我在一个类中编写它,我仍然有两个查询,而外部代码可能只需要可以从这两个查询之一中检索的数据。我应该将两个查询放在两个不同的方法中,让类外的代码决定应该执行哪些方法,从而决定对象中哪些部分的产品数据可用? (这将节省资源和执行时间。)
如果我想防止外部代码必须决定调用哪些方法以获得正确的数据,我应该更好地将属性声明为私有并使用magic __get函数执行必要的查询?我自己相信这是一个肮脏的工作,我在某处读到,如果外部代码想要访问私有属性,那么magic __get函数就是一种错误处理。
我是否还应该为此类添加数据操作方法?我可以添加一个用于更改产品的静态属性,但是在此类中使用方法来更改订单中的数量是否有意义?我认为这相当于一个“订单”类而不是一类产品数据,对吗?
这里有一些代码片段来说明,我打算做什么(在这种情况下,我写的是通过一个类提供所有数据,并让外部代码决定调用哪个方法以获得正确的数据:
<?php
class productdata {
public $productID;
public $productname;
public $weight;
public $deliverytime;
public $deprecated;
public $openorderquantity;
public $stock;
public $opensupplierorders;
public function readproductdatafromDB() {
$db = new Db();
$safe_productID = $db->quote($this->productID);
$rows_get_productdata = $db->select("SELECT ...");
$error = $db -> error();
foreach ($rows_get_productdata as $row_get_productdata) {
$this -> productname = $row_get_productdata["productname"];
$this -> weight = $row_get_productdata["weight"];
$this -> deliverytime = $row_get_productdata["deliverytime"];
$this -> deprecated = $row_get_productdata["deprecated"];
$this -> openorderquantity = $row_get_productdata["openorderquantity"];
$this -> stock = $row_get_productdata["stock"];
}
}
public function readopensupplierordersfromDB () {
$db = new Db();
$safe_productID = $db->quote($this->productID);
$this->opensupplierorders = $db->select("SELECT ...");
$error = $db -> error();
}
} ?>
请不要关心数据库调用我认为我有一个很好的数据库包装类。
在打电话给我时,我会这样做:
<?php
$productdata = new productdata();
$productdata->productID = '123';
$productdata->readproductdatafromDB();
echo "The weight of the product is: " . $productdata->weight;
?>
我希望我能提出正确的问题。非常感谢您提前帮助我。
最诚挚的问候, 本尼迪克特。
答案 0 :(得分:1)
第一原则:正确设计并在遇到问题时担心性能/优化。
因此,产品属性与股票属性分开,股票属性是单独的但与订单属性相关,它们是独立的但与供应商属性相关,等等。因此,每种类型的信息都应该封装到自己的类中:是的,这将是在很大程度上反映了正常化的数据库模式。
答案 1 :(得分:1)
在您的代码中,您主要是打破Single Responsibility
原则。您的课程做了两件事:管理产品信息和管理数据库连接/查询。这是错误的做法。
这样你会有很多重复的代码。现在您只有一个Product实体。如果你有50个怎么办?你将在所有50个类中拥有相同的代码,而不是你想要做的事情。查看Repository
模式,它可以帮助您进行数据库交互。
正确的方法是分开这些。创建一个用于管理连接和检索数据的类,以及一个类Product
,而不是ProductData
,可以使用从数据库接收的数据创建哪些对象。
我建议你先看看一些OOP框架。与他们合作,尝试并理解他们,你会更好地理解这些概念,以便你可以在自己的项目中使用它们。
除此之外,看看设计模式。本书Head First Design Patterns
是了解设计原则和模式的绝佳介绍。