- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
请诚实一点,必要时拆开我的作品。
所以我正在重新编写我最近制作的一个小型网络应用程序。原因很简单,代码变得非常困惑,我想学习和应用更好的 OO 设计。这个应用程序应该做的只是简单的 CRUD。我有一个包含 3 个表的数据库,companies
和 partners
彼此没有关系,city
与公司和合作伙伴。很简单,真的。现在,我有几个问题将在帖子末尾说明。在这里,我将尝试解释一下:
我的第一种方法是创建公司、合作伙伴和城市类,从数据库中获取所有数据集并从中创建对象:
class company {
private $id = null;
private $name = null;
private $city = null;
//many more attributes
function __construct( $id, $name, $city, [...] ) {
$this->id = $id;
$this->name = $name;
$this->city = $city;
//huge constructor
}
/*
* getters + setters here
*
* no need to paste the partner class as it looks just like this one
*
*/
}
这就是所有这些类所做的。我从数据库中获取每个数据集并构建公司、合作伙伴和城市对象(这些类中的属性城市是一个本身具有多个属性的对象)并将它们保存到两个数组 arr_companies
和 arr_partners
,然后保存这些对象......并且它像那样工作得很好。
现在,我想要的是更新、插入、删除数据库,所有 3 个类(城市、公司、合作伙伴)都需要这个功能。我的方法是创建一个带有构造函数的新类,该构造函数基本上采用 2 个字符串命令和对象,例如('update', 'company')
然后它将直接在数据库中更新公司,而我的对象保持不变。这让我非常难过,因为我拥有如此精美的构造对象,但我不知道如何使用它们。
问题:
拥有如此庞大的构造函数是不是很糟糕(我最大的构造函数需要28个参数)?
你是否应该为数据库创建一个单独的类操作还是最好有一个抽象类或接口(interface)并让子类自己处理更新、删除、插入?
无论何时都只写入、从数据库中删除是否很常见,或者我应该只将这些更改应用到我的对象并且只在以后执行对数据库的命令,例如当 session 结束时?
我想像这样的应用程序以前一定已经完成过很多次了。这里的正确方法是什么?创建对象、使用对象、将它们保存到数据库?
我有很多问题,但我想其中很多我只是不知道如何提出。
请注意,如果可能的话,我现在不想使用 ORM。
非常感谢您的宝贵时间。
最佳答案
OP 中提出的问题:
“拥有如此庞大的构造函数(我最大的构造函数需要 28 个参数)是不是很糟糕”?
“您应该为数据库操作创建一个单独的类,还是为其创建一个抽象类或接口(interface)并让子类自己处理更新、删除、插入更好?”
一般来说,在创建类时,您想尝试找出最能代表您的业务需求的名词。在您的特定情况下,您可能有三个类(class);公司、合作伙伴和城市。
现在在每个类(名词)中,您的方法将采用动词的形式,因此从语义上讲您的调用代码是有意义的:if ($company->getName() === 'forbes' )
正如您提到的,每个类都需要一个数据库对象 (dbo) 才能使用,因此您可以实现任意数量的模式来向您的类公开数据集连接;单例、带工厂的单例或依赖注入(inject)等。
抽象(父)类非常适合在子类之间共享通用算法,应该在您处于设计的伪代码阶段时加以识别。父类还允许您通过在父类中声明抽象方法来强制子类拥有方法。
接口(interface)在某些情况下是一个有用的工具,但我发现它们不如在父类中声明抽象方法灵活。但在类不共享父类的情况下效果很好。
“无论何时都只写入、从数据库中删除是很常见的,还是我应该将这些更改应用到我的对象,并且只在以后执行对数据库的命令,例如在 session 结束时”?
CRUD 事件应该在执行操作时发生。例如,如果您等待 session 结束,您可能会遇到 session 因用户关闭浏览器而提前结束的情况。为了更好地保护您的数据,您可以将 CRUD 事件包装在事务中。
如果您正在运行一个高流量应用程序,您可以实现一个排队系统并将要完成的工作排队。
“我想像这样的应用程序以前肯定已经完成了很多次。这里正确的方法是什么?创建对象,使用对象,将它们保存到数据库中”?
你是对的,这在以前就已经完成了,通常被称为 ORM(对象关系映射器)。基本上,ORM 将自省(introspection)您的数据库模式,并创建代表您的模式的对象(和关系)。因此,您不是在使用 native SQL,而是在使用对象。虽然您可以使用 SQL 来满足自定义业务需求,但在 Doctrine 的情况下,您将使用 Doctrine 查询语言 (DQL) 而不是原生 SQL。
我强烈推荐的 ORM 是 Doctrine .
如果您不想使用 ORM,您可以将 CRUD 方法添加到您的主要类中。我选择了一个接口(interface),这样您的类就不必从由数据库操作组成的父类扩展。另外,查看 this post关于使用单例/工厂来公开您的类数据库对象。
考虑以下几点:
// Company.php
class Company implements iDatabaseOperation
public function delete()
{
// Lets use a DBO singleton/factory for DB access
// Uses PDO, which is strongly recommended
$dbo = Database::factory(Database::DATABASE_NAME);
$dbo->beginTransaction();
try {
$sql =
"DELETE FROM " .
" company " .
"WHERE " .
" id = :companyId " .
"LIMIT 1";
$stmt = $dbo->prepare($sql);
$stmt->bindValue(':companyId', $this->getId());
$stmt->execute();
$dbo->commit();
} catch (Exception $e) {
$dbo->rollback();
error_log($e->getMessage();
$e = null; // Php's garbage collection sucks
}
}
}
// iDatabaseOperation.php
interface iDatabaseOperation
{
public function delete();
public function update();
public function insert();
}
关于php - CRUD 和 OOD。如何解决这个问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8825622/
关闭。这个问题是off-topic .它目前不接受答案。 想要改进这个问题? Update the question所以它是on-topic用于堆栈溢出。 关闭 12 年前。 Improve thi
我有一个动态网格,其中的数据功能需要正常工作,这样我才能逐步复制网格中的数据。假设在第 5 行中,我输入 10,则从第 6 行开始的后续行应从 11 开始读取,依此类推。 如果我转到空白的第一行并输入
我有一个关于我的按钮消失的问题 我已经把一个图像作为我的按钮 用这个函数动画 function example_animate(px) { $('#cont
我有一个具有 Facebook 连接和经典用户名/密码登录的网站。目前,如果用户单击 facebook_connect 按钮,系统即可运行。但是,我想将现有帐户链接到 facebook,因为用户可以选
我有一个正在为 iOS 开发的应用程序,该应用程序执行以下操作 加载和设置注释并启动核心定位和缩放到位置。 map 上有很多注释,从数据加载不会花很长时间,但将它们实际渲染到 map 上需要一段时间。
我被推荐使用 Heroku for Ruby on Rails 托管,到目前为止,我认为我真的会喜欢它。只是想知道是否有人可以帮助我找出问题所在。 我按照那里的说明在该网站上创建应用程序,创建并提交
我看过很多关于 SSL 错误的帖子和信息,我自己也偶然发现了一个。 我正在尝试使用 GlobalSign CA BE 证书通过 Android WebView 访问网页,但出现了不可信错误。 对于大多
我想开始使用 OpenGL 3+ 和 4,但我在使用 Glew 时遇到了问题。我试图将 glew32.lib 包含在附加依赖项中,并且我已将库和 .dll 移动到主文件夹中,因此不应该有任何路径问题。
我已经盯着这两个下载页面的源代码看了一段时间,但我似乎找不到问题。 我有两个下载页面,一个 javascript 可以工作,一个没有。 工作:http://justupload.it/v/lfd7不是
我一直在使用 jQuery,只是尝试在单击链接时替换文本字段以及隐藏/显示内容项。它似乎在 IE 中工作得很好,但我似乎无法让它在 FF 中工作。 我的 jQuery: $(function() {
我正在尝试为 NDK 编译套接字库,但出现以下两个错误: error: 'close' was not declared in this scope 和 error: 'min' is not a m
我正在使用 Selenium 浏览器自动化框架测试网站。在测试过程中,我切换到特定的框架,我们将其称为“frame_1”。后来,我在 Select 类中使用了 deselectAll() 方法。不久之
我正在尝试通过 Python 创建到 Heroku PostgreSQL 数据库的连接。我将 Windows10 与 Python 3.6.8 和 PostgreSQL 9.6 一起使用。 我从“ht
我有一个包含 2 列的数据框,我想根据两列之间的比较创建第三列。 所以逻辑是:第 1 列 val = 3,第 2 列 val = 4,因此新列值什么都没有 第 1 列 val = 3,第 2 列 va
我想知道如何调试 iphone 5 中的 css 问题。 我尝试使用 firelite 插件。但是从纵向旋转到横向时,火石占据了整个屏幕。 有没有其他方法可以调试 iphone 5 中的 css 问题
所以我有点难以理解为什么这不起作用。我正在尝试替换我正在处理的示例站点上的类别复选框。我试图让它做以下事情:未选中时以一种方式出现,悬停时以另一种方式出现(选中或未选中)选中时以第三种方式出现(而不是
Javascript CSS 问题: 我正在使用一个文本框来写入一个 div。我使用以下 javascript 获取文本框来执行此操作: function process_input(){
你好,我很难理解 P、NP 和多项式时间缩减的主题。我试过在网上搜索它并问过我的一些 friend ,但我没有得到任何好的答案。 我想问一个关于这个话题的一般性问题: 设 A,B 为 P 中的语言(或
你好,我一直在研究 https://leetcode.com/problems/2-keys-keyboard/并想到了这个动态规划问题。 您从空白页上的“A”开始,完成后得到一个数字 n,页面上应该
我正在使用 Cocoapods 和 KIF 在 Xcode 服务器上运行持续集成。我已经成功地为一个项目设置了它来报告每次提交。我现在正在使用第二个项目并收到错误: Bot Issue: warnin
我是一名优秀的程序员,十分优秀!