вопрос по ООП (идеологический)

dub

Новичок
вопрос по ООП (идеологический)

Сорри за возможный ламеризм. Не могу согласится с одним суждением. есть класс в нем функция :
PHP:
function getParent($id)
{      
    $sql = 'SELECT par_id  FROM `table` where id = '.$id;
	$this->db->query($sql);
}
абсолютно однозначно формирующая запрос и испольняющая его вроде все просто, но мой опонент утверждает что нада делать так :
PHP:
function getParent($id)
{      
	$this->db->query($this->sqlGetLevel($id));
}

function sqlGetLevel($id)
{
	 $sql = 'SELECT par_id  FROM `table` where id = '.$id;
         return ($sql);
}
И вот так все время формировать все запросы в отдельных функциях. Ну не могу я с этим согласится. Зачем, если почти все функции возвращающие запрос использоватся будут не больше 1-го раза(те что больше то понятно что можна выделять, но правильно ли все)?
С одной стороны, таким образом у нас запрос формируется в отдельной функции и потом можно менять только ее, добавляя какие нибудь правила, например, с другой, в два раза больше функций. учитывая что все документируется то вместо 1-й строчки 10.
Помогите пожалуйста решить спор :)
 

JamES

Новичок
это какая-то паранойя, чтобы функция возвращала строку, в которую просто подставили переменную и причем без проверки на тип
 

WP

^_^
Я бы не делал функцию которая возращает текст запроса.
 

dub

Новичок
JamES
WP
Спасиба, я начинаю верить что я все таки прав, теперь бы доводов побольше найти :)
 

WP

^_^
А каких доводов? Я просто не понимаю нафиг возвращать строку запроса. Это нужно в редких случаях, и возвращается часть запроса (при работе с деревьями).
 

Crazy

Developer
Re: вопрос по ООП (идеологический)

абсолютно однозначно формирующая запрос и испольняющая его вроде все просто, но мой опонент утверждает что нада делать так :
Так имеет смысл делать, если планируется в потомках класса заменять этот SQL на другой. Если представляется вероятным, что это может потребоваться.

В противном случае это называется "интеллектуальная мастурбация", видов которой в ООП достаточно много.

-~{}~ 22.08.06 07:39:

Спасиба, я начинаю верить что я все таки прав, теперь бы доводов побольше найти :)
Это в корне неверный подход к делу. Если кто-то говорит, что ты должен покрасить яйца в оранжевый цвет -- не нужно искать 47 причин этого не делать. Нужно спросить у доброжелателя, зачем красить и почему именно в оранжевый.
 

StUV

Rotaredom
dub
+ если данный запрос выполняется не только для getParent($id)
 

Crazy

Developer
StUV, это уже воплощение принципе DRY и к ООП отношения не имеет. :)
 

Alexandre

PHPПенсионер
PHP:
function getParent($id) 
{       
    $this->db->query($this->sqlGetLevel($id)); 
} 

function sqlGetLevel($id) 
{ 
     $sql = 'SELECT par_id  FROM `table` where id = '.$id; 
         return ($sql); 
}
Кроме указанных недостатков в данном подходе есть свой плюс - это улучшенная возможность отладки. Если запрос формируется динамически и зависит от нескольких переменных, и на порядок сложнее, то используя его можно протестировать, используя
Код:
print $catalog->sqlGetLevel($id)
, а потом сделав paste/copy просто выполнить в БД.

Но я бы все равно так не делал бы, читая Фаулера, я выработал правило: метод класса должен иметь содержательное имя, быть небольшим (до 15 строк) и выполнять законченное действие. $catalog->sqlGetLevel (я бы придумал имя generateSqlForTableLevelId ) - это как-то не вяжется. Под это правило вариант 1 больше подходит.
 

dub

Новичок
Re: Re: вопрос по ООП (идеологический)

Автор оригинала: Crazy
Так имеет смысл делать, если планируется в потомках класса заменять этот SQL на другой. Если представляется вероятным, что это может потребоваться.

В противном случае это называется "интеллектуальная мастурбация", видов которой в ООП достаточно много.

-~{}~ 22.08.06 07:39:


Это в корне неверный подход к делу. Если кто-то говорит, что ты должен покрасить яйца в оранжевый цвет -- не нужно искать 47 причин этого не делать. Нужно спросить у доброжелателя, зачем красить и почему именно в оранжевый.
Хороший подход, если бы не тот факт что дискуссия у меня с начальством :D
 

Yaponchick

Новичок
а если:
PHP:
function getParent($id, $ret) 
{
       if(!$ret){
              return $this->db->query($this->sqlGetLevel($id)); // ретурн не обязательно, но вдруг захочешь парсить ресурс
       } else {
              return $this->sqlGetLevel($id);
       }
}
/*
Shorten:
*/

return $ret?$this->sqlGetLevel($id):$this->db->query($this->sqlGetLevel($id));
 

dub

Новичок
Alexandre
попробую делать так же .. а по поводу имени - это +1;
 

WP

^_^
Alexandre
:) Улыбнул print. Необходимость работы с запросом в редакторе у меня появляется не так часто, и тем более копирования из PHP-скрипта (только сложные SELECT'ы поиска в пару килобайт). Во-первых есть свойство last_query в драйвере СУБД, во-вторых когда система работает на локальной тачке (где и разрабатывается), все запросы скидываются в q.txt где их легко достать :) Imho, лишних методов делать не нужно, т.к. это неудобно, а логику построения запроса я частично записываю тернарным оператором (стораюсь).
Yaponchick
Меня сейчас вырвет.
 

shark_255

Новичок
почему-то в памяти всплыло "SQL-инъекции" - кто знает
более-менее универсальный способ защиты?
 

WP

^_^
shark_255
1. Оффтопик.
2. Специально защиты никакой не надо. Надо делать так чтобы в запрос попало только что там должно быть по смыслу, и нельзя было специально составленым HTTP-запросом добиться неожиданного SQL-запроса. На практике это достигается приведением целых к типу int, т.е. на данном примере:
PHP:
$sql = 'SELECT par_id  FROM `table` where id = '.intval($id);
А строки нужно экранировать, т.е. добавлять обратный слеш (\) перед служебными символами запросов к используемой СУБД.
Есть функция intval и функция mysql_real_escape_string, но я сделал свои. Одну для приведения к целому (с тем отличием от intval что если скормить ей строку например "100 лет" она в отличие от intval вернет 0, а не 100), и две для экранирования строк - первая экранирует лишь основные служебные символы, а вторая еще % и _ (служебные символы в LIKE).
 

Yaponchick

Новичок
Crazy
Объясни пожайлуста, почему, чтобы не делать в будущем ошибки =)
 

Alexandre

PHPПенсионер
WP ну это маленькие хитрости...
print используется для одних целей, echo для других. это так, чтоб быстрее найти и заэкронитовать отладочный принт.

а что касается
во-вторых когда система работает на локальной тачке (где и разрабатывается),
не разрабатывается, а дорабатывается...и по ряду причин, ну например по специфики данных и размеру БД, не всегда получается на локальной, ну это так - мелочи.
 

Crazy

Developer
Автор оригинала: Yaponchick
Объясни пожайлуста, почему, чтобы не делать в будущем ошибки =)
Объясняю: у метода должно быть одно назначение. Если онгда лезет в базу и возвращает значение, а иногда возвращает SQL и не лезет в базу -- это пример самого кошмарного проектирования, какое я могу представить.

-~{}~ 22.08.06 13:55:

Автор оригинала: Alexandre
print используется для одних целей, echo для других. это так, чтоб быстрее найти и заэкронитовать отладочный принт.
Не проще сделать какое-нибудь debug_print и жить спокойно?
 

Alexandre

PHPПенсионер
Не проще сделать какое-нибудь debug_print и жить спокойно?
не всегда. можно вообще принт не использовать, а использовать к примеру simpletest. Но это просто, дело привычки. Хотя, переход на TDD, считается хорошим тоном. С другой стороны, использование принта - это тотже simpletest, только сбоку.
есть два подхода
PHP:
function getParent($id)  
{        
    $sql = 'SELECT par_id  FROM `table` where id = '.$id; 
    print $sql ; 
    $this->db->query($sql); 
}

// MyClass.test.php
$cat = new  MyClass();
$id=1;
$cat->getParent($id);
и второй
PHP:
function getParent($id) 
{       
    $this->db->query($this->sqlGetLevel($id)); 
} 

function sqlGetLevel($id) 
{ 
     $sql = 'SELECT par_id  FROM `table` where id = '.$id; 
         return ($sql); 
}

// MyClass.test.php
$cat = new  MyClass();
$id=1;
print $cat->sqlGetLeve($id);
для отладки второй вариант предпочтительнее, так как это криво, править существующие классы. Ну как вариант можно предложить такой ход конем (что я и делаю)
PHP:
function getParent($id) 
{       
    $this->sql = 'SELECT par_id  FROM `table` where id = '.$id; 
    $this->db->query($this->sql); 
}
// MyClass.test.php
$cat = new  MyClass();
$id=1;
$cat->getParent($id);  
print $cat->sql;
Но часто бывает, что необходимо посмотреть сам сформировавшийся sql без выполнения, например, когда навешиваем кучу всяцих фильтров или пр... тогда придется код усложнять...
PHP:
function getParent($id, $isExec=true )  
{        
    $this->sql = 'SELECT par_id  FROM `table` where id = '.$id; 
    if  ($isExec)
          $this->db->query($this->sql); 
}

// MyClass.test.php
$cat = new  MyClass();
$id=1;
$cat->getParent($id, false);  
print $cat->sql;
 
Сверху