上帝对象
上帝对象是糟糕的软件设计和糟糕的面向对象实现的诱人后果。
从本质上讲,上帝对象 是一个拥有太多方法或太多属性的对象;从本质上讲,它是一个知道太多或做了太多事情的类。上帝对象很快就会与应用程序中的大量其他代码紧密耦合(被引用)。
那么,这究竟有什么问题呢?简而言之,当你将一段代码与其他所有代码捆绑在一起时,你很快就会发现维护方面的灾难。如果你为一个用例调整了上帝对象中一个方法的逻辑,你可能会发现这会给另一个元素带来意想不到的后果。
在计算机科学中,采取分而治之的策略通常是个好主意。通常,大问题只是一系列小问题。解决了这一系列小问题,就能迅速解决整个问题。对象通常应该是自足的;它们应该只知道关于自身的问题,也应该只解决一组问题,即自身的问题。任何与这一目标无关的东西都不属于这一类。
可以说,与物理对象有关的对象应该是实例化的,而与之无关的对象应该是抽象类。
在开发嵌入式系统时,上帝对象反其道而行之。嵌入式系统用于处理从计算器到 LED 标牌等任何设备上的数据;它们是小型芯片,本质上是独立的计算机,而且成本相当低。在这种使用情况下,由于计算能力有限,你经常会发现编程的优雅性和可维护性成了无关紧要的问题。性能的轻微提高和控制的集中化可能更为重要,这意味着使用上帝对象可能是明智之举。幸运的是,PHP 很少用于嵌入式系统的编程,所以你不太可能遇到这种特殊情况。
处理这些类的最有效方法是手动将它们拆分成独立的类。
另一种名为 "害怕添加类" 的反模式也会造成这种情况,同时也会导致无法缓解这种情况。这就是开发人员不愿创建必要类的原因。
下面是一个上帝类的例子:
<?php
class God
{
public function getTime(): int
{
return time();
}
public function getYesterdayDate(): string
{
return date("F j, Y", time() - 60 * 60 * 24);
}
public function getDaysInMonth(): int
{
return cal_days_in_month(CAL_GREGORIAN, date('m'), date('Y'));
}
public function isCacheWritable(): bool
{
return is_writable(CACHE_FILE);
}
public function writeToCache($data): bool
{
return (file_put_contents(CACHE_FILE, $data) !== false);
}
public function whatIsThisClass(): string
{
return "Pure technical debt in the form of a God Class.";
}
}
因此,正如你所看到的,在这个类中,我们基本上合并了很多无关的方法。为了解决这个问题,我们可以把这个类分成两个子类,一个是 Watch
类,另一个是 CacheManager
类。
下面是 Watch
类;该类的目的只是向我们显示各种格式的时间:
<?php
class Watch
{
public function getTime(): int
{
return time();
}
public function getYesterdayDate(): string
{
return date("F j, Y", time() - 60 * 60 * 24);
}
public function getDaysInMonth(): int
{
return cal_days_in_month(CAL_GREGORIAN, date('m'), date('Y'));
}
}
这是 CacheManager
类;这个类将所有缓存的功能分开,因此它与 Watch
类完全分开:
<?php
class CacheManager
{
public function isCacheWritable(): bool
{
return is_writable(CACHE_FILE);
}
public function writeToCache($data): bool
{
return (file_put_contents(CACHE_FILE, $data) !== false);
}
}