冗长的方法
在某些情况下,PHP 方法可能会过于复杂;例如,在下面的类中,我故意省略了一些有意义的注释,并使构造函数过长:
<?php
class TaxiMeter
{
const MIN_RATE = 2.50;
const secondsInDay = 60 * 60 * 24;
const MILE_RATE = 0.2;
private $timeOfDay;
private $baseRate;
private $miles;
private $dob;
/**
* TaxiMeter constructor.
* @param int $timeOfDay
* @param float $baseRate
* @param string $driverDateOfBirth
* @throws Exception
*/
public function __construct(int $timeOfDay, float $baseRate, string $driverDateOfBirth)
{
if ($timeOfDay > self::SECONDS_IN_DAY) {
throw new Exception('There can only be ' . self::SECONDS_IN_DAY . 'seconds in a day.');
} else if ($timeOfDay < 0) {
throw new Exception('Value cannot be negative.');
} else {
$this->timeOfDay = $timeOfDay;
}
if ($baseRate < self::MIN_RATE) {
throw new Exception('Base rate below minimum.');
} else {
$this->baseRate = $baseRate;
}
$dateArr = explode('/', $driverDateOfBirth);
if (count($dateArr) == 3) {
if ((checkdate($dateArr[0], $dateArr[1], $dateArr[2])) !== true) {
throw new Exception('Invalid date, please use mm/dd/yyyy.');
}
} else {
throw new Exception('Invalid date formatting, please use simple mm/dd/yyyy.');
}
$this->dob = $driverDateOfBirth;
$this->miles = 0;
}
/**
* @param int $miles
* @return bool
*/
public function addMilage(int $miles): bool
{
$this->miles += $miles;
return true;
}
/**
* @return float
* @throws Exception
*/
public function getRate(): float
{
$dynamicRate = $this->miles * self::MILE_RATE;
$totalRate = $dynamicRate + $this->baseRate;
if (is_numeric($totalRate)) {
return $totalRate;
} else {
throw new Exception('Invalid rate output.');
}
}
}
现在,让我们只做两个小改动:将我们的一些方法提取到它们自己的函数中,并添加一些 DocBlock 注释。虽然这还不够完美,但请注意其中的差别:
<?php
class TaxiMeter
{
const MIN_RATE = 2.50;
const SECONDS_IN_DAY = 60 * 60 * 24;
const MILE_RATE = 0.2;
private $timeOfDay;
private $baseRate;
private $miles;
/**
* TaxiMeter constructor.
* @param int $timeOfDay
* @param float $baseRate
* @param string $driverDateOfBirth
* @throws Exception
*/
public function __construct(int $timeOfDay, float $baseRate, string $driverDateOfBirth)
{
$this->setTimeOfDay($timeOfDay);
$this->setBaseRate($baseRate);
$this->validateDriverDateOfBirth($driverDateOfBirth);
$this->miles = 0;
}
/**
* Set timeOfDay class variable.
* Only providing it doesn't exceed the maximum seconds in a day (const secondsInDay) and is greater than 0.
* @param $timeOfDay
* @return bool
* @throws Exception
*/
private function setTimeOfDay($timeOfDay): bool
{
if ($timeOfDay > self::SECONDS_IN_DAY) {
throw new Exception('There can only be ' . self::SECONDS_IN_DAY . 'seconds in a day.');
} else if ($timeOfDay < 0) {
throw new Exception('Value cannot be negative.');
} else {
$this->timeOfDay = $timeOfDay;
return true;
}
}
/**
* Sets the base rate variable providing it's over the MIN_RATE class constant.
* @param $baseRate
* @return bool
* @throws Exception
*/
private function setBaseRate($baseRate): bool
{
if ($baseRate < self::MIN_RATE) {
throw new Exception('Base rate below minimum.');
} else {
$this->baseRate = $baseRate;
return true;
}
}
/**
* Validates
* @param $driverDateOfBirth
* @return bool
* @throws Exception
*/
private function validateDriverDateOfBirth($driverDateOfBirth): bool
{
$dateArr = explode('/', $driverDateOfBirth);
if (count($dateArr) == 3) {
if ((checkdate($dateArr[0], $dateArr[1], $dateArr[2])) !== true) {
throw new Exception('Invalid date, please use mm/dd/yyyy.');
}
} else {
throw new Exception('Invalid date formatting, please use simple mm/dd/yyyy.');
}
return true;
}
/**
* Adds given milage to the milage class variable.
* @param int $miles
* @return bool
*/
public function addMilage(int $miles): bool
{
$this->miles += $miles;
return true;
}
/**
* Calculates rate of trip.
* Times class constant mileRate against the current milage in miles class variables and adds the base rate.
* @return float
* @throws Exception
*/
public function getRate(): float
{
$dynamicRate = $this->miles * self::MILE_RATE;
$totalRate = $dynamicRate + $this->baseRate;
if (is_numeric($totalRate)) {
return $totalRate;
} else {
throw new Exception('Invalid rate output.');
}
}
}
冗长的方法是代码气味的一个指标;它们指的是代码中的一个症状,其根源可能是更深层次的问题。其他例子还包括重复代码和矫揉造作的复杂性(使用高级设计模式,而简单的方法就足够了)。