Универсальная функция или много конкретных?

O
На сайте с 29.05.2008
Offline
195
708

Здравствуйте.

Пишу движoк под свои нужды. Столкнулся следующей проблемой архитектуры ООП.

Есть, к примеру, класс Error. Который может отображать 4 типа ошибок: фатальная, ошибка, предупреждение, информация. Сейчас это все дело вызывается через конструктор. В параметры метода, отсылаю следующую информацию: type ошибки, status code HTTP, code, name. В середине метода с помощью select case определяю уровень ошибки и уже выполняю определенные действия. В данном случае, есть только 4 итерации цикла, но у меня есть методы, в которых таких циклов в 5 раз больше, а количество входящих флагов до 20.

Есть ли смысл создавать отдельные методы для каждого из типа ошибки? Как по мне, это вариант действительно логичнее и удобнее, но? Как насчет производительности? Окупается ли меньшее количество циклов большим потреблением ОЗУ (ибо регистрируется больше методов)?

_vb_
На сайте с 25.07.2009
Offline
104
#1
ortegas:

Есть, к примеру, класс Error. Который может отображать 4 типа ошибок: фатальная, ошибка, предупреждение, информация.
...
Есть ли смысл создавать отдельные методы для каждого из типа ошибки? Как по мне, это вариант действительно логичнее и удобнее, но? Как насчет производительности? Окупается ли меньшее количество циклов большим потреблением ОЗУ (ибо регистрируется больше методов)?

Окупается. Не парьте себе мозг проблемами расхода памяти. ООП - это не о рациональном расходе памяти, а о рациональном коде. Проблемами рационального использования памяти занимаются конкретные языки/среды исполнения/фреймворки.

Сделайте базовый класс Event, куда вынесите весь общий код. И наследуйте от Event классы Fatal, Warning, Information, которые содержат только специфический для каждой ситуации код. В идеале в этих классах у вас не должно быть ни одной строчки повторяющегося кода.

Саратовская фракция серча (). Давайте посчитаемся.
edogs software
На сайте с 15.12.2005
Offline
775
#2
ortegas:
Здравствуйте.

Пишу движoк под свои нужды. Столкнулся следующей проблемой архитектуры ООП.

Есть, к примеру, класс Error. Который может отображать 4 типа ошибок: фатальная, ошибка, предупреждение, информация. Сейчас это все дело вызывается через конструктор. В параметры метода, отсылаю следующую информацию: type ошибки, status code HTTP, code, name. В середине метода с помощью select case определяю уровень ошибки и уже выполняю определенные действия. В данном случае, есть только 4 итерации цикла, но у меня есть методы, в которых таких циклов в 5 раз больше, а количество входящих флагов до 20.

Есть ли смысл создавать отдельные методы для каждого из типа ошибки? Как по мне, это вариант действительно логичнее и удобнее, но? Как насчет производительности? Окупается ли меньшее количество циклов большим потреблением ОЗУ (ибо регистрируется больше методов)?

"Потерявши голову по волосам не плачут"©

Если Вы используете ООП и сделали класс, то от пары лишних методов трагедии не случится точно.

Так что если куча методов оправданна с точки зрения ООП, то делайте кучу.

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

Если код в большинстве случаев у Вас будет вырождаться во что-то вида

function doSomethingWithErrorType1($status_code,$code,$name) {
$this->error_type=1;
return $this->doSomethingWithError($status_code,$code,$name);
}

то по большому счету куча методов будет являться тут ООП ради ООП.

Если же ситуации в большинстве случаев реально уникальны, то почему вполне можно и бить на отдельные методы.

Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход. Продаем lenovo legion в спб, дешевле магазинов, новые, запечатанные. Есть разные. skype: edogssoft
Оптимизайка
На сайте с 11.03.2012
Offline
396
#3

постройте иерархию классов - ошибок с помощью наследования. Используйте Exception'ы. Потом можно как-то так:


try {
// do something useful; throw exceptions when needed
} catch (UnknownContentProducerException $ex) {
header('HTTP/1.0 404 Not Found');
echo $ex->getMessage();
} catch (UnknownHTTPMethodException $ex) {
header('HTTP/1.0 405 Method Not Allowed');
echo $ex->getMessage();
} catch (AccessDeniedException $ex) {
header('WWW-Authenticate: Basic realm=""');
header('HTTP/1.0 401 Unauthorized');
echo $ex->getMessage();
} catch (Exception $ex) {
header('HTTP/1.0 500 Internal Server Error');
echo $ex->getMessage();
}

Т.е. вы сможете обработать нужный вам тип ошибок в соотв. catch (), если спец. обработки не требуется, то catch (Exception $ex), если все наследуются от него, будут пойманы тут.

⭐ BotGuard (https://botguard.net) ⭐ — защита вашего сайта от вредоносных ботов, воровства контента, клонирования, спама и хакерских атак!
O
На сайте с 29.05.2008
Offline
195
#4
_vb_:
Проблемами рационального использования памяти занимаются конкретные языки/среды исполнения/фреймворки.

Да проблема как раз в том, что с каждым днем это стает похожим на фреймворк.

Может кто-то может посмотреть участки кода, и дать хотя бы пару поверхностных советов по архитектуре. Хочется использовать ООП, но что-то вместо этого выходит не легкий и читабельный код, а комбайн-фреймворк.

N
На сайте с 06.05.2007
Offline
419
#5
ortegas:
Хочется использовать ООП, но что-то вместо этого выходит не легкий и читабельный код, а комбайн-фреймворк.

Все нормально. Так и должно быть. Теперь вы действительно знаете что такое ООП.

Можно все удалить и приступать непосредственно к написанию сайтов решающих практические задачи.

Кнопка вызова админа ()
IL
На сайте с 20.04.2007
Offline
435
#6
ortegas:
Есть ли смысл создавать отдельные методы для каждого из типа ошибки? Как по мне, это вариант действительно логичнее и удобнее, но? Как насчет производительности? Окупается ли меньшее количество циклов большим потреблением ОЗУ (ибо регистрируется больше методов)?

Откройте для себя Exception-ы. Посмотрите, как сделано в уже имеющихся фреймворках.

ИМХО, следует различать ООП ради ООП и ООП (а также паттерны/архитектуры: MVC, синглтоны итд) для удобства разработчика.

Говоря про производительность, не забывайте про ЛИЧНУЮ производительность - про производительность разработчика.. Это не скорость выполнения программы, а скорость решения поставленной задачи (величина, обратная времени написания нужного кода, а также времени дальнейшей его доработки/поддержки/сопровождения при необходимости). Если речь о разовом коде, разовой задаче - естественно проще "написать как есть" и забыть.. Если речь о более-менее универсальном движке/классе/наборе функций - о повторно используемом коде.. то подход должен учитывать дальнейшую возможность лёгкого "конфигурирования" и "красивого" кода.. В этом плане ИМХО у ООП больше возможностей.

В качестве примера могу привести часть метода контроллера Yii. Проверка наличия в базе опубликованной записи с нужным id и 404 ошибка (в нужном шаблоне - это может быть и основной шаблон сайта и отдельный шаблон для ошибок... и на белом экране с одной строчкой)


class ShopController extends Controller
{
public function actionCategory($id=0) {
if (!$category = Category::model()->published()->findByPk($id))
throw new CHttpException(404,'Страница не найдена');
// дальше работаем с $category
}

При этом, этот участок кода не изменится, если потребуется добавить ограничения просмотра для различных ролей пользователя/конкретных пользователей, т.к. есть accessRules и accessControlFilter (и ещё классы.. в которых код.. код..)

Про потребление памяти, количество циклов и прочее.. - см про преждевременную оптимизацию.

1. Мерять. Ещё раз мерять.

2. Выявлять узкие места.

3. Оптимизировать их (вплоть до написания отдельных компилируемых модулей/демонов и тд)

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

Конечно, всё что можно сделать при помощи ООП (в смысле, решить задачу из "реального" мира), можно реализовать и без него.. Однако, использование ООП имеет свои плюсы (равно как и минусы). Главное - не переусердствовать...

http://habrahabr.ru/post/172119/

http://habrahabr.ru/post/153225/

http://habrahabr.ru/post/23619/

http://habrahabr.ru/post/169601/

и много других статей в поиске по ООП

... :) Облачные серверы от RegRu - промокод 3F85-3D10-806D-7224 ( http://levik.info/regru )
O
На сайте с 29.05.2008
Offline
195
#7

Метод ошибки выглядит так:

//Вивід критичної помилки
static function displayCritical(array $flags = ['code' => 'UNKNOWN', 'name' => false, 'description' => false, 'status' => 503]) {
//Перевіряємо вхідні параметри
if (!isset($flags['code']))
$flags['code'] = 'UNKNOWN';
if (!isset($flags['status']))
$flags['status'] = 503;
if (!isset($flags['name']))
$flags['name'] = false;
if (!isset($flags['description']))
$flags['description'] = false;

//Завантажуємо мовні константи опису помилок
if (!defined('LANG_ERROR_DEFINED')) {
if (!defined('DIR_LANG'))
Processor_::getLanguage();

File_::parseJson([ 'file' => DIR_LANG.'error.json',
'prefix' => 'LANG_ERROR',
'error_reporting' => 1
]);

//Також завантажуємо родові константи
if (DIR_ROOT !== '')
File_::parseJson([ 'file' => DIR_ROOT.DIR_LANG.'error.json',
'prefix' => 'LANG_ERROR',
'error_reporting' => 1
]);
}

//Встановлюємо статус код HTTP
if ($flags['status'] !== 200)
Processor_::setHttpStatus(['code' => $flags['status']]);

//Перериваємо роботу скрипту та виводимо помилку
$render = new Render_();

die($render->display([ 'page' => 'error',
'title' => ((defined('LANG_ERROR_'.$flags['code'].'_TITLE')) ? constant('LANG_ERROR_'.$flags['code'].'_TITLE') : LANG_ERROR_TITLE),
'css' => ['error'],
'js' => false,
'error' => [ 'code' => $flags['code'],
'type' => 'ERROR',
'name' => $flags['name'],
'description' => $flags['description']
]
]));
}

А вот фатальная ошибка вызывается уже процедурой, ибо в этом случае, может быть ошибка связанная и с подключением класса Error.

function throw_fatal_error($code = 'UNKNOWN', $name = false) {

//Встановлюємо заголовки
header('HTTP/1.1 503 Service Temporarily Unavailable');
header('Status: 503 Service Temporarily Unavailable');
header('Retry-After: 20160');
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
header('Pragma: no-cache');
header('Connection: close');

//Робимо код придатним до читання людиною
if (strpos($code, '_'))
$code = str_replace('_', ' ', $code);

$code = convert_case($code, 'MB_FIRST_WORD', 'utf-8');

//Виводимо сторінку
echo '<!DOCTYPE html>',
'<html id="error">',
'<head>',
'<meta charset="',((defined('CONF_CHARSET')) ? CONF_CHARSET : 'utf-8'),'">',
'<title>',
'Fatal Error!',
'</title>',
//@ Регулярно оновлювати альтернативний CSS
((defined('DIR_TEMPLATE') and defined('CONF_CSS')) ? '<link rel="stylesheet" href="'.DIR_TEMPLATE.DIR_CSS.'error.css">' : '<style>*{margin:0;padding:0;border:none;outline:none}header,nav,section,aside,article,footer,mark{display:block}body{font:15px Tahoma;width:80%;margin:15px auto 10px}h1{font:400 22px Georgia,\'Times New Roman\';color:#B00}p{margin:5px 0}</style>'),
'</head>',
'<body id="fatal">',
'<h1>',
'Fatal error! ',$code,
'</h1>',
(($name !== false) ? '<p>'.$name.'</p>' : ''),
'</body>',
'</html>';
die;
}

Будет еще контроль по группам и связь с автодебагером. Пока что похоже на ООП ради ООП. Могли бы вы хотя бы описать как бы лично реализовали данный участок кода?

Я то сам легко могу править свой код и думаю как раз об общей производительности, а не о производительности разработки, да вот только, не планирую работать всегда над данным проектом сам и хотелось бы логичнее. :( В команде не работал, поэтому, не знаю как писать универсальный код.

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий