Почему рефакторинг приносит результаты [Кент Бек]

Ценность программы имеет две составляющие — то, что они могут делать для нас сегодня, и то, что они смогут делать завтра. В большинстве случаев мы сосредотачиваемся при программировании на том, что требуется от программы сегодня. Исправляя ошибку или добавляя новую функцию, мы повышаем ценность программы сегодняшнего дня путем расширения ее возможности.

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

Я знаю достаточно, чтобы выполнить сегодняшнюю задачу. Я знаю не достаточно чтобы выполнить завтрашнюю. Но если я буду работать только на сегодняшний день, завтра я не смогу работать вообще.

Рефакторинг — один из путей решения описанной проблемы. Обнаружив что вчерашнее решение сегодня потеряло смысл, мы его изменяем. Теперь мы можем выполнить сегодняшнюю задачу. Завтра наше сегодняшнее представление задачи покажется наивным, по этому мы и его изменим.

Из-за чего бывает трудно работать с программами? В данный момент мне приходят в голову 4 причини:
— программы трудные для чтения, трудно модифицировать;
— программы в логике которой есть дублирование, трудно модифицировать;
— программы, которым нужно дополнительные функции, что требует изменения в работающем коде, трудно модифицировать,
— программы, реализующие сложную логику условных операторов, трудно модифицировать.

Итак нам нужны программы которые легко читать, вся логика которых задана в одном и только одном месте, модификация которых не ставит под угрозу существующие функции и которые позволяют выражать условную логику возможно более простым способом.

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

Spreadsheet_Excel_Writer генерит пустой файл

В общем была проблема после переезда на другой хостинг, на timeweb. Попросил поставить Spreadsheet_Excel_Writer, ТП быстро отреагировала и поставила библиотеку, но она напроч отказывалась писать в файл. Т.е. файл генерила, но данные не записывались в файл. Я не дождался ответа в выходной день, оказывается у них админы в выходные не работают, поставил другую библиотеку для работы с Exel, PHPExcel называется. В работе даже полегче чем выше указанная. Она потребовала настройки mbstring.func_overload != 2, что и было сделано, оказалось что и Spreadsheet_Excel_Writer не работала по той же причине, в общем проблема тут mbstring.func_overload

Выводим в header.php компонент с параметрами переданными в теле странцы

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

Делается это так. Пишется функция вида

function componentHeader($text)
{
	global $APPLICATION;
	$arParams = $APPLICATION->GetPageProperty('PARAMS');
	if(is_array($arParams))
	{
		ob_start();
			$APPLICATION->IncludeComponent('demo:test', '', $arParams);
			$contentTime = ob_get_contents();
		ob_end_clean();
		return $contentTime;
	}
}

кладем ее как через init.php и в хидере выводим $APPLICATION->AddBufferContent(«componentHeader»); должно работать.

Мини GetList для файлов

В исходниках битрикса есть CAllFile::GetList($arOrder, $arFilter, $arParams); но он видимо служит для внутреннего использования и не описан в документации. Нам нужно выбрать описание по 10 файлам за раз, этот метод, в качестве параметра фильтра массив из ID файлов не принял. Пришлось накидать свою функцию.

function __arfileGetList($ar_FileID)
{
	if(is_array($ar_FileID) && count($ar_FileID) > 0)
	{
		global $DB;
		$rs_File = $DB->Query(
			"SELECT * FROM b_file WHERE ID IN 
                               (". implode(',', $ar_FileID). ")",
			false,
			"FILE: ".__FILE__." LINE: ".__LINE__
		);
		while($ar_File = $rs_File->Fetch())
		{
			$ar_Result[] = $ar_File;
		}

		if(is_array($ar_Result) && count($ar_Result) > 0)
			return $ar_Result;
	}
}

P/S
Не забудте проверить $ar_FileID, чтобы там были именно ID файлов…

Битрикс и большой кэш по ID

Итак представим что у вас или у вашего клиента большой, высоко-посещаемый сайт. Также представим инфоблок в котором больше 80k элементов. Наверняка у этих элементов есть детальное описание  и я уверен 99,9% что ID кэша это ID вашего элемента.

Итак у нас получается что в папке допустим /bitrix/cache/object_80k/ — 80 000 папок с кэшем, т.е.

/bitrix/catche/object_80k/1

/bitrix/catche/object_80k/2

/bitrix/catche/object_80k/3

/bitrix/catche/object_80k/n

/bitrix/catche/object_80k/80 000

Какой бы у вас не был сервер, поиск папки в общем списке из 80k занимает время. Плюс если сайт посещаемый то вы догадываетесь что происходит, нагрузка на ровном месте, даже я бы сказал в том месте где мы пытаемся ее уменьшить.

Итак решение, на мой взгляд просто очень красивое и элегантное, его подсказал мой коллега  Николай Рыжонин.

function __getGenerationCachePath($id)
{
    $hash = md5($id);
    $path = substr($hash,-4,2).'/'.substr($hash,-2);
    return $path;
}

Пример:

$ob_Cache     = new CPHPCache;
$i_CacheTime  = 3600;
$s_CacheID    = $ID;
$s_CachePatch = "/object_80k/" . __getGenerationCachePath($ID) . "/" . $ID . "/";
if($ob_Cache->InitCache($i_CacheTime, $s_CacheID, $s_CachePatch))
{
    $ar_Cache  = $ob_Cache->GetVars();
    $ar_Result = $ar_Cache['ITEAM'];
}
else
{
    $ar = ''; // выборка
    if($obCityCache->StartDataCache())
    {
        $obCityCache->EndDataCache(array('ITEAM' => $ar));
    }
}

Итак функция создаст путь вида /object_80k/as/df/ID и тем самым разобьет 80k папок на под папки, тем самым уменьшит время поиска кэша и общую нагрузку на сервер.

Да и еще важный момент, функция написана с учетом что ID > 100 000k. хотя тем кому это пригодится это не важно…

str_replace, если работаем с массивами

Сегодня заметил небольшую особенность в стандартной php функции, которую раньше как-то не замечал. Вылез баг в замене значения по маске через  str_replace. Код выглядит вот так :

    $ar_ResultList[] = str_replace(
	array("#ID#", "", "", "", "#CODE#", 
"#CITY_CODE#", "#DETAIL_URL#", "#HOTEL_CODE#"),
	$ar_ObjectFiled,
	$s_LinkTemplates
   );

Это уже исправленный код, т.е если мы ищем и заменяем в массиве то ключи должны совпадать и по расположению, т.е. по ключам.

1c-Битрикс, плохо или хорошо для разработчика?

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

Я каждый раз радуюсь когда приходится решать какие-то не стандартные задачи, это подстегивает и пинает мозги. Надоел GetList и $arResult. Хочется чего-то новенького….

1c-Битрикс, работаем с агентами [bitrix api]

Для новичков так сказать, про агенты.

Что такое агенты в битриксе?

— Это функция которая будет запущена в определенное время, поддерживает периодичность запуска.

Если вам нужно динамически добавлять агентов, то есть для это API. Если вам просто нужно прикрутить один или два агента то прошу под кат, там по шагам разберемся с этим вопросом.

Continue reading