Expection handling

PartizaneN

I speak PHP
Expection handling

Привет всем!

Недавно попробовал использовать эксэпшны для реализации алгоритма кэширования результатов выполнения функции (метода).
Задача была следующей: Многие статические методы вызывались по несколько раз для различных вычислений, и с целью оптимизации, когда проект уже подошёл к концу - нужно было соптимизировать.

Пример статического метода:
PHP:
class ShippingCalculator{
	
	/**
	 * Gets shipping costs
	 *
	 * @param SingleParcel $parcel
	 * @return array
	 */
	public static function getCost(SingleParcel $parcel) {
	    //.... 
             $query="SELECT * FROM price_location_bands 
						WHERE pickup_country='".$parcel->get('pickup_country')."'";
            // и тому подобные запросы дальше и вычисления
            
             return array('price_band'=>$priceBand,'delivery_time'=>$deliveryTime,'price'=>$price);

        }
}
Придумалось использовать для этого Эксэпшны, причём так чтобы выглядело следующим образом:

PHP:
class ShippingCalculator{
	
	/**
	 * Gets shipping costs
	 *
	 * @param SingleParcel $parcel
	 * @return array
	 */
	public static function getCost(SingleParcel $parcel) {
            try{
                   return CalculatorsCache::get($parcel);
            }catch(CalculatorsCache $cache){
  	               //.... 
                      $query="SELECT * FROM price_location_bands 
						WHERE pickup_country='".$parcel->get('pickup_country')."'";
                     // и тому подобные запросы дальше и вычисления
            
                     return $cache->set(array('price_band'=>$priceBand,'delivery_time'=>$deliveryTime,'price'=>$price));
             }
        }
}
Что же происходит - вначале пытаемся вернуть закэшированный результат выполнения функции - если не находится кэша - выкидывается эксэпшн и идёт в catch. Дальше $cache->set закэширует результат этого метода. и в следующий раз до кэтча не дойдёт.

Всё было бы хорошо, если бы не существовало анти-паттерна схожего:

http://en.wikipedia.org/wiki/Expection_handling

......

Вопрос заключается в следующем - является ли алгоритм мой анти-паттерном (т.к. не совсем для эррор хэндлинга используются эксэпшны, а для кэширования), либо всё-таки - сойдёт (впринципе пробуется сделать ретурн закэшированного значения и т.к. его нету возникает эррор и выкидывается эксэпшн)?
 

Lews

Новичок
А зачем тут исключения вобще?
Чего-нить в стиле
PHP:
If(!CalculatorsCache::exists()){
   set..
}
return CalculatorsCache::get();
 

PartizaneN

I speak PHP
Lews
Ifы конечно быстрее, но было сделано так вот почему...

Сколько раз нужно передавать параметры при использовании твоей схемы? 3 раза.

При использовании эксэпшнов - получается 1-ин раз.

Как итог - меньше багов. Например, решил параметры поменять - в двух местах проапдэйтил - в третьем - забыл.
 

Black Raven

Новичок
помоему ситуация не является исключением, поэтому я не использовал бы Exception

PHP:
public static function getCost(SingleParcel $parcel)
{
	$cache = CalculatorsCache::getOrCreate($parcel); 

	if($cache->isNew())
	{
		//....  
		$query="SELECT * FROM price_location_bands  
		WHERE pickup_country='".$parcel->get('pickup_country')."'"; 
		// и тому подобные запросы дальше и вычисления 
		
		$cache->set(array('price_band'=>$priceBand,'delivery_time'=>$deliveryTime,'price'=>$price)); 
	} 

	return $cache;
}
 

Lews

Новичок
Автор оригинала: PartizaneN
Lews
Ifы конечно быстрее, но было сделано так вот почему...

Сколько раз нужно передавать параметры при использовании твоей схемы? 3 раза.

При использовании эксэпшнов - получается 1-ин раз.

Как итог - меньше багов. Например, решил параметры поменять - в двух местах проапдэйтил - в третьем - забыл.
Не понял про количество параметров, если честно.
Я вобще о логике, а не конкрентно об ифах. Т.е. согласен с мнением Black Raven
 

whirlwind

TDD infected, paranoid
Black Raven Lews Да лан, ребят. Что вы пытаетесь доказать. Там же сплошная статика и нормальное решение не прикрутишь. Вот и приходится микроскопом...
 

PartizaneN

I speak PHP
Автор оригинала: whirlwind
Black Raven Lews Да лан, ребят. Что вы пытаетесь доказать. Там же сплошная статика и нормальное решение не прикрутишь. Вот и приходится микроскопом...
Вот этого не понял... Хоть и не ко мне обращались :)

Есть куча нормальных решений... 2 уже предложили... И одно "не знаю нормальное ли", т.е. моё. И вот я и пытаюсь вычислить нормальность с помощью других пхпшников (т.е. вас).

Black Raven, понятненько...
 

HraKK

Мудак
Команда форума
Black Raven
Если кешновый то устанавливаем кеш. Это смутило :)
 

Black Raven

Новичок
Автор оригинала: HraKK
Black Raven
Если кешновый то устанавливаем кеш. Это смутило :)
Писал чтобы показать вариант, а так конечно согласен, что isNew звучит не очень. isEmpty лучше? :)
 

PartizaneN

I speak PHP
Глубоких филосовских рассуждений не получилось...

Решил я всё-таки, что мой способ круче, элегантнее...

Было придумано именно так, потому как логически не сильно смотрелось с ифами. К тому же и букав больше получается.

После долгих обдумий стало понятно, что "плохо потому что нестандартно" - это не плохо :)

Ну и конечно же в итоге всё упирается в то, что конструкция просто идеально подходит по своей функциональности именно для этой конкретной нужды...
 

Angerslave

Новичок
PartizaneN
Твой способ хитрее. А хитрее значит хуже. Вообще на первый взгляд прикольно, а вот на второй - как-то не очень. Хотя конечно можно сказать, что отсутствие объекта в кэше - исключительная ситуация...

Кстати, я и сам тянусь к структуре "если есть в кэше - отдать на первых строчках кода", но для этого я юзаю
PHP:
<?php

public function getSomething($param1, $param2)
{
    $cache_key = $param1->prop1.'_'.$param2->prop2;
    if (Cache::exists($cache_key))
        return Cache::get($cache_key);
    // Do something operations
    Cache::set($obj, $cache_key);
    return $obj;
}
 

dr-sm

Новичок
я бы вот так написал
PHP:
if ($o = CalculatorsCache::get($parcel)) {
     return $o;
}
$query="SELECT * FROM price_location_bands 
                        WHERE pickup_country='".$parcel->get('pickup_country')."'";
                     // и тому подобные запросы дальше и вычисления
            
return CalculatorsCache::set(array('price_band'=>$priceBand,'delivery_time'=>$deliveryTime,'price'=>$price));
 

korchasa

LIMB infected
Автор оригинала: PartizaneN
...
Сколько раз нужно передавать параметры при использовании твоей схемы? 3 раза.

При использовании эксэпшнов - получается 1-ин раз.

Как итог - меньше багов. Например, решил параметры поменять - в двух местах проапдэйтил - в третьем - забыл.
Прикольное извращение. А то, что у вас уже два класса знают об интерфейсе SingleParcel это ничего? И то, что сетите вы массив, а забираете объект, и соответственно, мне придется смотреть код кэшэра, чтобы понять что там происходит.

ЗЫ: На вашем месте я бы не парился и сделал у SingleParcel метод getHash(), по которому бы set'ил и get'ил бы в какой-то общий кэш-объект.
 
Сверху