让我们从一些文本分析开始,我强调:
我经营一个街机网站和过去几年
想想你能应付多少以及你正在处理什么。还要了解,多年来您已经获得了关于运行街机网站的特定知识。你已经获得了你所在地区的专业。永远不要低估自己的职位和资产,这是您运营的基础,您将对其进行更改。这包括您网站的用户群。
它添加了许多功能,它已经到了程序编程看起来太复杂并且添加新功能或进行简单的设计修改可能非常棘手的地步。
如果系统增长,它们会变得越来越复杂。这不仅特定于过程编程,这是事实。由于您已经运营该网站多年,因此您知道事情发生了怎样的变化,尤其是在用户与您的网站的交互方式方面。
因此,我决定尝试并从头开始重新编码网站,使用相同的功能,但采用 OOP 格式。
据说可以使用 OOP 技术来制作可重用的软件,有(而且不可能)任何证据。
但在商业软件开发中,从头开始重新编写整个应用程序取得成功的例子很少。 很少。商业软件开发的规则可能不适用于您的具体情况,所以就这么说吧。
重新编码网站之前请三思。做很多工作只是为了达到同样的目的是有些徒劳的,而且可能会令人失望。相反,您可能更具体地查看您当前的设计中的哪个引入了您希望改变的最大问题。
PHP 可以混合使用过程式和面向对象的风格,当您有遗留代码(遗留代码的常见定义是代码没有自动化测试)。
我的问题是选课,
我试着换个说法:写课程是为了什么?
我了解 OOP 及其工作原理,但似乎总是难以入门。
开始总是最艰难的一步。您现在可以做出决定,但您无法展望未来。通过消除风险最大的部分来降低风险。您可能已经开始在这里提出问题以获得一些反馈以作为您的决定的依据,但这可能不会减轻负担并可能导致混乱。然而,接受教育通常是一件好事。
我不确定我是否应该尝试为具有登录用户功能的用户类等类创建函数,或者用户类是否应该只是添加/update/show 用户详细信息和部分登录在系统类中会更好吗?
这在很大程度上取决于您的应用程序的性质和用户的性质。可能您的大部分脚本只需要知道用户是具体用户还是匿名用户(匿名用户尚未登录),它是 ID、姓名或昵称。
应用程序应该向该用户提供任何消费组件,因此每个命令/脚本都不需要处理 a) 获取用户信息和处理用户(如登录),b) 验证组件是否对用户有效(访问控制)。那应该放在其他地方,例如在application controllerPofEAA。
每个具有应用程序控制器对象的脚本/命令都可以请求用户并与用户交互。
但这只是技术上的说法。处理自己不确定的事实,处理这些信息。尝试更好地表述你的具体问题,列出解决问题的具体方法的优缺点,在开始编码之前再次远离具体代码。然后比较优劣。尽量让事情变得更简单,不那么复杂。
可能用简单的文字写下应该发生的事情,而不是编写代码。
目前我已经开始使用以下类和函数但它们是否适合这个类别**?**
您的代码非常简单,因此很难说太多 - 特别是因为我不知道您的街机网站是什么(以及您所写的类别是什么)。它可能仍然是一个很好的例子。从您的课程中可以看出,您将所有内容紧密集成在一起。
例如,您从数据库开始。这很常见,因为数据库是任何应用程序的中心组件。应用程序需要数据库才能运行。但是,您希望保持松散耦合,以便您的所有命令都可以与其他数据库或与其他数据库连接的新用户对象一起运行,而不是应用程序的其余数据对象。
$application->getDB();
由于用户是每个应用程序的中心主体,它应该有一个非常简单的界面。所有关于身份验证、检索用户属性等的荣耀细节都应该委托给另一个类/组件,以便您可以更改存储用户的实现以及他们如何进行身份验证:
/**
* @package command.modules.games
*/
function ListGamesCommand(Request $request, Response $response)
{
$application = $request->getApplication();
$user = $application->getSession()->getUser();
$games = $application->getModels()->build('games');
$games = $games->findByUser($user);
$response->setProp('games', $games);
}
如本示例所示,您可以在需要时添加该功能。例如。只要您的应用程序不需要实际登录用户,为什么要关心它现在是如何编写的?
创建一个为应用程序对象生成用户的工厂——无论它现在或将来需要什么(参见The Clean Code Talks — Inheritance, Polymorphism, & Testing 中的两堆对象)。如果您随后需要身份验证,请将其添加到会话对象或用户对象接口。
无论如何,身份验证本身将在它自己的一个类中实现,Authenticator。因此,您也可以稍后通过将身份验证调用从会话转移到用户或其他方式来查看您的界面。只有一小部分命令需要处理这些特定任务,并且由于所有新代码都在自动测试中,因为您希望重写并从 OOP 中受益,因此您已确保所有地方都被覆盖并正确重构。
访问请求变量也是如此。如果你想利用 OOP 的好处——它与间接高度相关(并且每一层间接都有代价)——你首先应该让你的基类对特定数据而不是任何数据进行操作(比如全局变量和超全局变量,我在您的示例代码中看到了$_POST)。
因此,让您的新代码能够对请求进行操作并传递响应(输入 - 处理 - 输出):
$request = new Request($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES, $_ENV);
$response = new Response;
示例取自BankAccount - Sample application used for PHPUnit training
现在下面的一切都可以在Request 和Response 对象上运行 - 处理输入并将其转换为输出。 域命令(执行此操作的脚本/命令)不再需要像使用 $_POST 或 $_GET 那样从 HTTP 请求中提取输入,他们可以直接从Request - 或者如果您编写了自己的一类命令 - 这可以更加量身定制。有些命令可以对自己的请求和响应进行操作。
下一个重要主题是用户界面。你写你想:
我决定尝试从头开始重新编码网站,使用相同的功能但采用 OOP 格式。
我已经写过这样的做法可能是徒劳的。受益于 OOP 代码意味着下次更改代码时,您仍然可以重用组件。随着软件不断变化,这一次现在已经是下一次了。因此,您希望已经重用现有代码。我假设您现有代码的一部分是输出逻辑。所以现有的输出逻辑需要与上面的示例Request和Response接口。
我打赌你喜欢网站。你喜欢让它们正常工作并且看起来很棒。多年来,您已经建立了自己的网站,即使并非一切都像您希望的那样,您也不想放弃它。因此,对于您的重写至关重要的是,您不会破坏所有内容,但您可以保留它从现在到未来的工作形式(参见 Preserve a Working Application; last point of the list)。
在 webapps 中,视图是至关重要的部分。如果您失去视图,您的网站将失去它的身份。如果您对其进行过多更改,您的网站将会失去现在习惯使用它的用户。
如果你打破它,
- 你会注意到吗?
- 你能解决它吗?
另一方面,您希望您的应用程序代码(特性、功能)不再与它紧密绑定以便在重写代码时受益。既然你想重写你的应用程序,我们来看看:
.---------. .-------------.
| website | ---> [interface in ] ---> | application |
| user | <--- [interface out] <--- | |
`---------´ `-------------´
正如此架构所示,为了使您的应用程序更独立于交互的外观(可以是网站、(智能手机)GUI 或票务系统),应用程序代码应该是可替换的。您不想在新应用程序代码中编写逻辑来获取用户游戏,例如针对每种类型的用户界面,但您在旧应用程序代码中这样做了。
这里以User 对象为例。它的身份验证方式和存储位置不应该是您的新应用程序命令代码关心的问题。如果命令需要它,它就在那里。不是全局的,而是具体的,如果命令要求的话。
因为注册和丢失密码程序是您现有应用程序的一部分并继续存在。
现在您需要将旧代码和新代码放在一起。
因此,您可能会从 HTTP 请求和 HTTP 响应的接口开始。视图从 Interface Out 开始。您通过该接口为视图分配/传递所有需要的数据,您的应用程序不再知道该视图。您无需处理新应用程序代码中的任何 CSS、Javascript 或 HTML 代码。这只是输出的糖。您的应用程序也应该通过控制台/telnet 以纯文本形式或作为远程 XMLRPC 服务、AJAX 端点进行接口 - 随便什么。
因此,您可能只是概括您的视图代码并向其注入变量。编写一个视图层可以像包含一个 PHP 文件一样简单。它对在其范围内可用的变量进行操作。它可以利用其范围内可用的“帮助”函数(模板宏)。它可以利用视图模型对象。甚至可以为视图编写自己的语言(模板语言,一种领域特定语言 (DSL))。
但这只有在您创建一个允许应用程序代码执行此操作的接口时才有可能。
因此,您现在要做的就是将 HTTP/HTML/CSS/JS 从您的应用程序移到它自己的适配器中。该适配器能够制定通用命令,可以通过 interface in 传递给 any 应用程序。
应用程序只会注意执行命令并通过接口输出传递它的响应。所以你现在有两个域:你的应用程序和网站。
您可以开始创建这两个新域,然后为旧代码和新代码提供一个进出接口。
您还有“两个”应用程序并排放置。它们最终与您的数据库绑定在一起(在他们自己的代码中不可见),该数据库负责您网站的数据是否有序。这就是数据库的用途。将数据与您的代码分开,这样您就可以随时更改您的代码。
另外,如果你想重新编码,在现有代码和新代码之间画一个边框。
祝你好运!我希望阅读本文会为您展示一些针对您的具体情况的选项。另请注意,您不会将控制器变成数据库的另一个外观。通过使用轻量级 HTTP 抽象和仅视图层,您可能获得了最大的好处(不知道您的具体最大问题),因为您的应用程序可能仅适用于网站。
因为在 HTTP/PHP 中:
[Interface In] Plain Text HTTP request
[Application] Free to go
[Interface Out] Plain Text HTTP response
您通常只需要一些功能来解析输入并构建输出。
此外,不使用胖模型还有一个好处是您可以快速按顺序访问数据,例如如果您不需要一次传递输出(缓冲,一个块),您可以利用将输出流式传输到服务器的好处。
您应该决定哪些部分对您的应用程序是重要的重构,而不是 OOP 与否。与程序一样,OOP 也需要做好。如果您今天在编写过程代码时遇到问题,那么 OOP 代码可能无法解决您的问题。可能需要编写更好的程序代码。只是说,重构一个应用程序并不容易,你应该先找出实际问题。
- 如果你打破它,你会注意到吗?
- 如果你把它弄坏了,你能修复它吗?
关键部分是您可以注意到并且您手头有一切可以进行修复。
让您的网站处于测试状态,这样您就可以判断是否在此处或那里更改代码实际上做得很好。如果发现它不起作用(更好),则能够将任何更改返回。
完成后,您可以轻松决定是否使用新功能。只要您不需要引入新功能,您编写功能的方式就无需更改任何内容。在此之前,您无法计划新功能。
所以最好在重新编写应用程序之前三思而后行。正如所写,这可能会杀死项目。
另请参阅: How to implement MVC style on my PHP/SQL/HTML/CSS code?SO Q&A