Рефакторинг: введение объясняющих переменных
Иногда в исходном коде выражения бывают настолько сложными, что если даже и мы их написали, то по прошествии какого-то времени не можем понять, что мы имели в виду в том или ином участке кода.
Например, рассмотрим следующее выражение (правда, оно не настолько сложное, но выражения посложнее я покажу далее):
if ((strpos(strtoupper($platform), "MAC") !== false) && (strpos(strtoupper($browser), "IE") !== false) && wasInitialized() && $resize > 0 ) { // что-то делаем ... }
Чтобы нам легче было понять логическое выражение в условии, попробуем упростить его с помощью нашего сегодняшнего приема:
$isMacOs = strpos(strtoupper($platform), "MAC") !== false; $isIEBrowser = strpos(strtoupper($browser), "IE") !== false; $wasResized = $resize > 0; if ($isMacOs && $isIEBrowser && wasInitialized() && $wasResized) { // что-то делаем ... }
Выражение могут быть очень сложными для понимания и чтения. В таких случаях введение локальных переменных может существенно помочь разбить сложное и длинное выражение на ряд более простых. Только тут надо учитывать, что имена переменных должны быть понятны читателю кода, т.е. они должны отражать суть того, что делает выражение, результат которого сохраняется в переменной.
Иногда бывает трудно применить прием группировки кода в отдельную функцию, о котором мы говорили ранее. И наш сегодняшний прием немного может облегчить нам жизнь в этом случае.
Рассмотрим теперь пример посложнее:
function price() { // цена = базовая_цена - скидка + стоимость_доставки return $this->_quantity * $this->_itemPrice - max(0, $this->_quantity - 500) * $this->_itemPrice * 0.05 + min($this->_quantity * $this->_itemPrice * 0.1, 100.0); }
Во-первых, в примере базовая цена вычисляется как цена одной единицы, умноженная на количество товара. Мы можем с легкостью выделить это в отдельную переменную:
function price() { // цена = базовая_цена - скидка + стоимость_доставки $basePrice = $this->_quantity * $this->_itemPrice; return $basePrice - max(0, $this->_quantity - 500) * $this->_itemPrice * 0.05 + min($basePrice * 0.1, 100.0); }
Во-вторых, мы можем выделить вычисление скидки в отдельную переменную:
function price() { // цена = базовая_цена - скидка + стоимость_доставки $basePrice = $this->_quantity * $this->_itemPrice; $qtyDiscount = max(0, $this->_quantity - 500) * $this->_itemPrice * 0.05; return $basePrice - $qtyDiscount + min($basePrice * 0.1, 100.0); }
В конце концов, я могу вынести определение стоимости доставки в третью переменную. При этом я могу удалить комментарий, т.к. он для понимания кода уже не нужен:
function price() { $basePrice = $this->_quantity * $this->_itemPrice; $qtyDiscount = max(0, $this->_quantity - 500) * $this->_itemPrice * 0.05; $shipping = min($basePrice * 0.1, 100.0); return $basePrice - $qtyDiscount + $shipping; }
Но здесь мы могли бы вполне использовать прием группировки кода в отдельную функцию:
function price() { return basePrice() - qtyDiscount() + shipping(); } function quantityDiscount() { return max(0, $this->_quantity - 500) * $this->_itemPrice * 0.05; } function shipping() { return min($this->basePrice() * 0.1, 100.0); } function basePrice() { return $this->_quantity * $this->_itemPrice; }
Я предпочел бы использовать именно группировку кода в отдельную функцию, т.к. в этом случае выделенные методы quantityDiscount, shipping и basePrice доступны любой части объекта, в котором мы их используем. Но если у нас есть довольно сложное выражение, которое не позволит нам просто так применить прием группировки, мы вынуждены будем применить наш сегодняшний прием введения объясняющих переменных.
Хороший прием для качественного кода, но делать руппировку кода в отдельную функцию надо только тогда когда код встречается более двух раз, а если нет то переменные самый раз.
Нашёл ошибку, по крайне мере у меня не воспринимает браузер пока не исправил: #
# function quantityDiscount() {
# return max(0, $this->_quantity - 500) * $this->_itemPrice * 0.06;
Кто нить уже пробовал код?
2 iwan: не воспринимает скорее всего не браузер, а php-интерпретатор ) Тут конечно будет ошибка, если держать этот код не в классе, в котором есть поля _quantity и _itemPrice. А вообще этот код просто для примера приведен, его даже пробовать не стоит Достаточно понять смысл приема.