让我们从一些文本分析开始,我强调:
我经营一个街机网站,在过去的几年里
想想你能应付多少以及你正在处理什么。还要了解,多年来您已经获得了有关运行街机站点的特定知识。你已经获得了你所在地区的专业。永远不要低估自己的职位和资产,这是您运营的基础,您将对其进行更改。这包括您网站的用户群。
它添加了许多功能,程序编程看起来太复杂了,添加新功能或进行简单的设计修改可能非常棘手。
如果系统增长,它们会变得越来越复杂。这不仅仅特定于过程编程,这是一个事实。由于您已经运行该站点多年,因此您知道事情发生了怎样的变化,尤其是在用户如何与您的站点交互方面。
因此,我决定尝试使用相同的功能但以 OOP 格式从头开始重新编码该站点。
据说可以使用 OOP 技术来制作可重用的软件,有(并且不可能)任何证据证明这一点。
但是在商业软件开发中,从头开始重写整个应用程序是成功的例子很少。很少。商业软件开发的规则可能不适用于您的特定情况,所以只是说。
在重新编码网站之前请三思。做很多工作只是为了达到同样的目的是有些徒劳的,而且可能会令人失望。相反,您可能更具体地查看您当前的设计中的哪个引入了您希望改变的最大问题。
PHP 可以混合过程和面向对象的风格,这在你有遗留代码时特别有用(遗留代码的常见定义是没有自动化测试的代码)。
我的问题是选课,
我试着改写一下:为了什么写课程?
我了解 OOP 以及它应该如何工作,但似乎总是难以入门。
开始总是最艰难的一步。您现在可以做出决定,但您无法展望未来。通过消除风险最大的部分来降低风险。您可能已经开始在这里提出问题以获得一些反馈以作为您的决定的依据,但这可能不会减轻负担并可能导致混乱。然而,接受教育通常是一件好事。
我不确定我是否应该尝试为类(例如具有登录用户功能的用户类)创建功能,或者用户类是否应该只是添加/更新/显示用户详细信息并且登录部分在系统中会更好班级?
这在很大程度上取决于您的应用程序的性质和用户的性质。可能您的大部分脚本只需要知道用户是具体的还是匿名的(匿名用户尚未登录),它的 ID、名称或昵称。
应用程序应该将该用户提供给任何消费组件,因此每个命令/脚本不需要处理 a) 获取用户信息和处理用户(如登录),b) 验证组件是否对用户有效(访问控制)。这应该放在其他地方,例如在应用程序控制器PofEAA中。
每个具有应用程序控制器对象的脚本/命令都可以请求用户并与用户交互。
然而,这只是从技术上讲。处理自己不确定的事实,处理这些信息。尝试更好地表述你的具体问题,列出具体解决方法的优缺点,在开始编码之前再次远离具体代码。然后比较优劣。试着让事情变得更简单,更简单。
可能用简单的文字写下应该发生的事情,而不是编写代码。
目前我已经开始使用以下类和函数,但它们是否适合这个类别**?**
你的代码很简单,所以很难说太多 - 特别是因为我不知道你的街机网站是什么(以及你写的类别是什么)。它可能仍然是一个很好的例子。在您的课程中可以看到的是,您将所有内容紧密集成在一起。
例如,您从数据库开始。这很常见,因为数据库是任何应用程序的中心组件。应用程序需要数据库才能运行。但是,您希望保持松散耦合,以便您的所有命令都可以与其他数据库或与其他数据库连接的新用户对象一起运行,而不是应用程序的其余数据对象。
$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 的示例 - 用于 PHPUnit 培训的示例应用程序
现在这下面的所有东西都可以在一个Request
和一个Response
对象上运行——处理输入并将其转换为输出。域命令(执行此操作的脚本/命令)不再需要关心从 HTTP 请求中提取输入,例如使用$_POST
,或者$_GET
他们可以直接从Request
- 或者如果你编写它自己的一类命令 -这可以更加量身定制。有些命令可以对自己的请求和响应进行操作。
下一个重要主题是用户界面。你写你想:
我决定尝试使用相同的功能但以 OOP 格式从头开始重新编码该站点。
我已经写过这样的做法可能是徒劳的。受益于 OOP 代码意味着下次更改代码时,您仍然可以重用组件。随着软件的不断变化,这一次已经是下一次了。因此,您希望已经重用现有代码。我假设您现有代码的一部分是输出逻辑。因此现有的输出逻辑需要与示例Request
及Response
以上接口。
我打赌你喜欢网站。你喜欢让它们正常工作并且看起来很棒。多年来,您已经建立了自己的网站,即使并非一切都像您希望的那样,您也不想放弃它。因此,对于您的重写至关重要的是,您不会破坏所有内容,但您可以从现在到将来保留它的工作形式(另请参阅保留工作应用程序;列表的最后一点)。
在 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 从您的应用程序移到它自己的适配器中。该适配器能够制定可以通过接口传递给任何应用程序的通用命令。
应用程序只会注意执行命令并通过接口输出它的响应。所以你现在有两个域:你的应用程序和网站。
您可以开始创建这两个新域,然后为旧代码和新代码提供一个进出接口。
您还有“两个”应用程序并排放置。它们最终与您的数据库绑定在一起(在他们自己的代码中不可见),该数据库负责您网站的数据是否有序。这就是数据库的用途。将数据与代码分开,这样您就可以随着时间的推移更改代码。
此外,如果您想重新编码,请在现有代码和新代码之间画一个边界。
祝你好运!我希望阅读本文会为您展示一些针对您的具体情况的选项。另请注意,您不会将控制器变成数据库的另一个外观。通过使用轻量级 HTTP 抽象和仅视图层,您可能获得了最大的好处(不知道您的具体最大问题),因为您的应用程序可能仅适用于网站。
因为在 HTTP / PHP 中:
[Interface In] Plain Text HTTP request
[Application] Free to go
[Interface Out] Plain Text HTTP response
您通常只需要一些功能来解析输入并构建输出。
此外,不使用胖模型的好处是您可以快速、按顺序访问数据,例如,如果您不需要一次传递输出(缓冲、一个块),您可以利用将输出流式传输到服务器。
您应该决定哪些部分对您的应用程序重构很重要,而不是 OOP 与否。与程序一样,OOP 也需要做好。如果您今天在编写过程代码时遇到问题,那么 OOP 代码可能无法解决您的问题。可能需要编写更好的程序代码。只是说,重构应用程序并不容易,您应该首先确定实际问题。
- 如果你打破它,你会注意到吗?
- 如果你打破它,你能修复它吗?
关键部分是您可以注意到并且您手头有一切可以进行修复。
让您的网站接受测试,这样您就可以说在这里或那里更改代码是否真的很好。如果发现它不起作用(更好),则能够将任何更改返回。
完成后,您可以轻松决定是否使用新功能。只要您不需要引入新功能,您编写功能的方式就无需更改任何内容。在此之前,您无法计划新功能。
所以最好在重新编写你的应用程序之前三思而后行。正如所写,这可能会杀死项目。
另请参阅: 如何在我的 PHP/SQL/HTML/CSS 代码上实现 MVC 样式?问答