Рефакторинг без тормозов (десять приемов в одной задаче)

11.09.13

Разработка - Рефакторинг и качество кода

На примере рефакторинга одной простой функции показаны приемы преобразования текста программы на языке 1С, которые можно использовать при улучшении кода.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
РазбитьПериод.erf
.erf 10,41Kb
4
4 Скачать (1 SM) Купить за 1 850 руб.

Функция, используемая для примера, решает задачу разбиения периода времени, заданного начальной и конечной датой, на отрезки, принадлежащие различным месяцам. Пусть в исходном варианте вид функции будет таким -ВАРИАНТ0:

Функция РазбитьПериод0(ДатаС, ДатаПо) Экспорт
    МассивПериодов = Новый Массив;
    Дата1 = ДатаС;
    Дата2 = ДобавитьМесяц(НачалоМесяца(Дата1), 1);
    Пока Истина Цикл
        Дата3 = Дата2 - 1;
        Если Дата3 > ДатаПо Тогда
            Дата3 = ДатаПо
        КонецЕсли;
        ЗаписьПериода = Новый Структура;
        ЗаписьПериода.Вставить("НачалоПериода", Дата1);
        ЗаписьПериода.Вставить("КонецПериода", Дата3);
        МассивПериодов.Добавить(ЗаписьПериода);
        Если Дата3 = ДатаПо Тогда
            Прервать
        КонецЕсли;
        Дата1 = Дата2;
        Дата2 = ДобавитьМесяц(Дата1, 1)
    КонецЦикла;
    Возврат МассивПериодов
КонецФункции

Здесь можно сделать следующее

  1. Можно не выполнять присваивания "Дата1 = ДатаС". Вместо этого достаточно использовать сам параметр «ДатаС» как переменную, а чтобы после выполнения функции его значение не оказалось «испорченным», перед ним в заголовке функции нужно использовать лексему «Знач». Это означает, что параметр передается не «по ссылке», когда используется ранее выделенная переменной память, а «по значению», когда создается новый экземпляр переменной.

  2. Можно сэкономить на придумывании осмысленного названия переменной, предназначенной для вычисляемого значения функции. Если результат функции строится в ходе ее выполнения и должен быть как-то заранее назван, лучше не выдумывать нового термина, так как у функции уже есть имя, а назвать результат выполнения функции в процессе его вычисления просто «Результат» или «Ответ».

  3. Последовательность операторов «Дата3 = Дата2 - 1;Если Дата3 > ДатаПо Тогда Дата3 = ДатаПо КонецЕсли» это всего лишь присвоение значения переменной «Дата3» с учетом ограничения ее значения сверху значением переменной «ДатаПо». Эта задача проще и нагляднее решается с помощью функции «Мин». То есть, если результат выражения должен учесть ограничения на результат сверху или снизу, следует использовать функцию  минимум или максимум, которые читаются легче и пишутся короче, чем условный оператор «если» или условный оператор с вопросом.

  4. Конструктор структуры позволяет сразу проинициализировать ее элементы, поэтому вставку элементов можно сократить. Для создания структуры и инициализации ее полей можно пользоваться соответствующей формой конструктора, куда сразу передать имена полей через запятую и значения полей. Так создаются структуры периодов, добавляемых в массив.

  5. Можно не создавать переменную для ссылки на создаваемую структуру. Так как она будет использована лишь однажды – в следующей строке программы. Вместо этого результат можно сразу записать на место его использования. Тогда не нужно будет «вымучивать» названия лишних переменных. Исключением являются случаи, когда промежуточный результат требует пояснения или контроля в процессе отладки. В нашем случае строка и без этого легко читается: в массив-результат добавляется новая структура из полей «НачалоПериода», «КонецПериода», имеющих соответствующие значения.

В результате функция оказывается приведенной к виду ВАРИАНТ1:

Функция РазбитьПериод1(Знач ДатаС, ДатаПо) Экспорт
    Ответ = Новый Массив;
    Дата2 = ДобавитьМесяц(НачалоМесяца(ДатаС), 1);
    Пока Истина Цикл
        Дата3 = Мин(Дата2 - 1, ДатаПо);
        Ответ.Добавить(Новый Структура("НачалоПериода, КонецПериода", ДатаС, Дата3));
        Если Дата3 = ДатаПо Тогда
            Прервать
        КонецЕсли;
        ДатаС = Дата2;
        Дата2 = ДобавитьМесяц(ДатаС, 1)
    КонецЦикла;
    Возврат Ответ
КонецФункции

Анализируя эту запись, можно придти к выводу, что переменные «ДатаС», «Дата2» и «Дата3» связаны простой зависимостью. "ДатаС" – это начало периода или начало текущего месяца, "Дата2" – это начало следующего, а "Дата3" – конец текущего месяца. Выполним подстановку и

  1. Избавимся от лишних, то есть связанных простой зависимостью, переменных.

В результате этого получаем ВАРИАНТ2:

Функция РазбитьПериод2(Знач ДатаС, ДатаПо) Экспорт
	Ответ = Новый Массив; 	
	Пока ДатаС < = ДатаПо Цикл
		Ответ.Добавить(Новый Структура("НачалоПериода, КонецПериода", ДатаС, Мин(КонецМесяца(ДатаС), ДатаПо)));
		ДатаС = КонецМесяца(ДатаС) + 1
	КонецЦикла;	
	Возврат Ответ
КонецФункции

Внимание: Из-за того, что знак "меньше или равно" в тексте функции неправильно отрабатывается при редактировании статьи на этом сайте, в него добавлен пробел!

Похожий вариант уже публиковался на Инфостарте [?], вот он - ВАРИАНТ3:

Функция РазбитьПериод3(ДатаС, ДатаПО) Экспорт
	Ответ=Новый Массив;
	Мес=НачалоМесяца(ДатаС);
	Пока Мес< =НачалоМесяца(ДатаПО) Цикл
		Период=Новый Структура;
        Период.Вставить("НачалоПериода", ?(НачалоМесяца(ДатаС)=Мес,ДатаС,Мес));
		Период.Вставить("КонецПериода", ?(НачалоМесяца(ДатаПО)=Мес,ДатаПО,КонецМесяца(Мес)));
        Ответ.Добавить(Период);
	    Мес=ДобавитьМесяц(Мес,1);
	КонецЦикла; 	
	Возврат Ответ;
КонецФункции

Здесь само собой напрашивается применение приемов 3, 4 и 5, в результате чего получается более красивый и компактный ВАРИАНТ4 

Функция РазбитьПериод4(ДатаС, ДатаПО) Экспорт
	Ответ = Новый Массив;
	Мес = НачалоМесяца(ДатаС);
	Пока Мес < = ДатаПО Цикл
        Ответ.Добавить(Новый Структура("НачалоПериода, КонецПериода", Макс(ДатаС,Мес), Мин(ДатаПО,КонецМесяца(Мес))));
	    Мес = ДобавитьМесяц(Мес, 1)
	КонецЦикла; 	
	Возврат Ответ
КонецФункции

В общем, результат в варианте 2 уже можно было бы принять, однако функция «Мин» смотрится инородно. Возможно, это от того, что она срабатывает лишь однажды – на самом последнем периоде. И если периодов много – эти сравнения оказываются лишними. Также, кажется, что можно избавиться от переменной «ДатаС», которая всегда на единицу больше конца периода, только что записанного в массив. А если попробовать сначала записать в массив исходный интервал, а затем при необходимости делить его на две записи, выделяя последний месяц в следующую запись? Алгоритм уместился в одном предложении. Возможно, и его запись окажется понятнее и проще?

Чтобы при этом не приходилось затем удалять записи, если интервал «отрицательный», выполним в этом случае обмен «ДатаС» и «ДатаПо». Здесь повторим прием 3 и обойдемся без условных операторов: началом периода будем считать минимум, а концом – максимум значений этих переменных. С точки зрения пользователя функции, это будет удобнее: программисту при записи вызова функции не нужно будет помнить, какую дату записывать первой – меньшую или большую, период можно будет задать и так и так. Функция станет более «робастной», то есть станет лучше защищена от ошибок в исходных данных. Конечно, это будет иметь свою цену - так отсекается возможность использования функции для контроля, что «ДатаС» меньше «ДатаПо». В результате получаем следующий ВАРИАНТ5:

Функция РазбитьПериод5(ДатаС, ДатаПо) Экспорт
    Ответ = Новый Массив;
    Ответ.Добавить(Новый Структура("НачалоПериода, КонецПериода", Мин(ДатаС, ДатаПо), Макс(ДатаС, ДатаПо)));
    Пока НачалоМесяца(Ответ[0]["НачалоПериода"]) < НачалоМесяца(Ответ[0]["КонецПериода"]) Цикл
        Ответ.Вставить(1, Новый Структура("НачалоПериода, КонецПериода", НачалоМесяца(Ответ[0]["КонецПериода"]), Ответ[0]["КонецПериода"]));
        Ответ[0]["КонецПериода"] = Ответ[1]["НачалоПериода"] - 1
    КонецЦикла;
    Возврат Ответ
КонецФункции

Рассматривая этот результат, можно заметить, что текст «НачалоПериода», «КонецПериода», "Ответ[0]" часто повторяется. Поэтому,

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

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

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

Функция Сколько(Массив, Образец, Ответ = 0) Экспорт
    Для Каждого Элемент Из Массив Цикл
        Ответ = Ответ + Число(Элемент = Образец)
    КонецЦикла;
    Возврат Ответ
КонецФункции

Если массив «Слова» хранит слова программного кода некоторой функции, то выражение

    Сколько(Слова, «Цикл», Сколько(Слова, «Тогда», 1))

рассчитает показатель цикломатической сложности функции.

Возвращаясь к исходной функции, применение приемов 7 и 8 дает следующий результат - ВАРИАНТ6:

Функция РазбитьПериод6(ДатаС, ДатаПо, Поле1 = "НачалоПериода", Поле2 = "КонецПериода") Экспорт
    Ответ = Новый Массив;
    Э = Новый Структура(Поле1 + "," + Поле2, Мин(ДатаС, ДатаПо), Макс(ДатаС, ДатаПо));
    Ответ.Добавить(Э);
    Пока НачалоМесяца(Э[Поле1]) < НачалоМесяца(Э[Поле2]) Цикл
        Ответ.Вставить(1, Новый Структура(Поле1 + "," + Поле2, НачалоМесяца(Э[Поле2]), Э[Поле2]));
        Э[Поле2] = Ответ[1][Поле1] - 1
    КонецЦикла;
    Возврат Ответ
КонецФункции

Рассматривая текущий вариант функции, можно заметить повтор в четырех местах названия функции «НачалоМесяца». Если это название разделить на два слова и сделать второе из них параметром функции, то она станет более универсальной, сможет выполнять разбивку на «Минуты», «Часа», «Дни», «Недели», «Месяца», «Квартала», «Года» (по понятным причинам придется смириться с некоторым диссонансом в произношении названий периодов). Для этого нам понадобится функция «Выполнить», которая воспринимает код как строку и выполняет его. В исходном коде название функции заменяется на «_», то есть «впишите что хотите», а перед выполнением туда вписывается нужный интервал заменой подстроки. В данном случае применяется наиболее спорный, ухудшающий понимание программы, прием

  1. Универсализации кода с использованием оператора «Выполнить». Этот прием следует применять с осторожностью.

Получаем следующий ВАРИАНТ7:

 
Функция РазбитьПериод7(ДатаС, ДатаПо, НаЧто = "Месяца", Поле1 = "НачалоПериода", Поле2 = "КонецПериода")	Экспорт
	М = Новый Массив;
	Э = Новый Структура(Поле1 + "," + Поле2, Мин(ДатаС, ДатаПо), Макс(ДатаС, ДатаПо));
	М.Добавить(Э);
	Выполнить(СтрЗаменить(
	"Пока _(Э[Поле1])< _(Э[Поле2])Цикл М.Вставить(1,Новый Структура(Поле1+"",""+Поле2,_(Э[Поле2]),Э[Поле2]));Э[Поле2]=М[1][Поле1]-1 КонецЦикла"
	, "_", "Начало" + НаЧто));	
	Возврат М
КонецФункции

Переменная «Ответ» заменена однобуквенной переменной «М» для сокращения длины строковой константы, содержащей шаблонизированный код.

Оглядев результат, видим, что в последнем варианте совершенно потеряна простота и понятность кода, которая ранее оправдывала менее компактную запись функции в варианте 5. Поэтому вернемся к варианту 2 и применим к нему приемы 7, 8 и 9. Здесь мы используем прием

  1. Сохранение промежуточных вариантов улучшения кода и возврат к ним из тупиковых ветвей процесса рефакторинга.

В итоге получили следующую универсальную функцию, решающую поставленную задачу (знак "_" заменен словом "Край", что обеспечивает читабельность функции внутри строки ), ВАРИАНТ8:

 
Функция РазбитьПериод8(Знач А, Б, Чего = "Месяца", Поля = "НачалоПериода, КонецПериода") Экспорт	
	М = Новый Массив; 	
	Выполнить(СтрЗаменить("Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(Край(А),Б)));А=Край(А)+1 КонецЦикла", "Край", "Конец" + Чего));
	Возврат М
КонецФункции


Можно предложить еще дальше и переписать функцию на английский. Получим последний, десятый ВАРИАНТ9

 

Function РазбитьПериод9(Val A, B, What = "Месяца", Fields = "НачалоПериода, КонецПериода") Export	
	M = New Array; 	
	Execute(StrReplace("While A<=B Do M.Add(New Structure(Fields,A,Min(Edge(A),B)));A=Edge(A)+1 EndDo", "Edge", "Конец" + What));
	Return M
EndFunction

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

Нужно сказать, что улучшение кода – процесс, результат которого не всегда можно оценить однозначно. Объективная составляющая оценок представлена метриками кода. Значения метрик компактности и цикломатической сложности [Анализ цикломатической сложности кода] для всех промежуточных вариантов рассматриваемой функции приведены в таблице.

Номер варианта Число строк Число знаков Цикломатическая сложность Произвольный период
0 21 494 4 Нет
1 14 348 3 Нет
2 8 255 2 Нет
3 12 385 4 Нет
4 9 279 2 Нет
5 9 469 2 Нет
6 10 399 2 Нет
7 9 407 1 Да
8 5 263 1 Да
9 5 242 1 Yes!

Субъективная составляющая оценок отражает простоту и понятность кода. Применяя все перечисленные приемы исключительно в погоне за компактностью, можно пропустить момент утраты понятности кода, то есть важно вовремя затормозить. Но когда? Наверное, каждый должен решать сам. В конце концов, кто-то считает, что «тормоза придумали трусы», а кто-то: «тише едешь – дальше будешь».

рефакторинг функция разбивка интервала

См. также

Рефакторинг и качество кода Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В последнее время термин «чистый код» стал очень популярным. Появились даже курсы по данной тематике. Так что же это такое?

16.09.2024    15372    markbraer    66    

42

Рефакторинг и качество кода Программист Бесплатно (free)

В статье рассматривается отказ от использования процедур и унификация формата ответа функций. Способ описывается на примере развития абстрактной информационной системы, работающей с PDF файлами.

10.09.2024    1091    acces969    4    

6

Рефакторинг и качество кода Бесплатно (free)

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

28.08.2024    1369    Chernazem    3    

6

Рефакторинг и качество кода Программист Бесплатно (free)

SOLID – принципы проектирования программных структур (модулей). Акроним S.O.L.I.D. образован из первой буквы пяти принципов. Эти принципы делают код более гибким, упрощают разработку. Принято считать, что принципы SOLID применимы только в объектно-ориентированном программировании. Но их можно успешно использовать и в 1С. Расскажем о том, как разобраться в принципах SOLID и начать применять их при работе в 1С.

22.08.2024    11110    alex_sayan    41    

53

Рефакторинг и качество кода Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Рассмотрим основные принципы шаблона проектирования "Стратегия" на простом примере.

25.06.2024    4729    MadRave    34    

27

Рефакторинг и качество кода Программист Платформа 1С v8.3 Абонемент ($m)

В статье расскажу и покажу процесс проведения Code-review на примере обработки с GitHub.

1 стартмани

04.06.2024    6633    mrXoxot    55    

42

Рефакторинг и качество кода Платформа 1С v8.3 Бесплатно (free)

Поделюсь своим опытом аудита кода авторских продуктов с Infostart.ru как одним из элементов применения DevOps-практик внутри Инфостарт. Будет настоящий код, боевые скриншоты, внутренние мемы от команды ИТ-лаборатории Инфостарт и прочее мясо – все, что любят разработчики.

10.04.2024    13916    artbear    85    

109

Рефакторинг и качество кода Программист Платформа 1С v8.3 Россия Бесплатно (free)

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

01.04.2024    4444    DrAku1a    15    

39
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. ivanov660 4587 06.09.13 16:58 Сейчас в теме
Молодца. Мне понравилось, жаль что в типовых решениях не всегда увидишь подобного подхода. С удовольствием плюсую!
2. mymyka 06.09.13 17:14 Сейчас в теме
Рефа́кторинг (англ. refactoring) или реорганизация кода — процесс изменения внутренней структуры программы, не затрагивающий её внешнего поведения и имеющий целью облегчить понимание её работы.
Экономия букв/строк в коде - не есть рефакторинг.
Читабельность, возможность отладки определенно ухудшаются.
(1)
в типовых решениях не всегда увидишь подобного подхода

И слава богу.
kote; user761890; Silenser; WanGoff; gigabyte_artur; amon_ra; fzt; fomaOp; cheburashka; q_i; krv2k; juntatalor; charushkin; Den_D; bk-81; help1Ckr; Kosstikk; ManyakRus; krylovim; +19 Ответить
3. ManyakRus 489 08.09.13 21:49 Сейчас в теме
(2) mymyka,
mymyka прав :)
а автор вредитель :)
user761890; +1 Ответить
4. ildarovich 7938 08.09.13 23:42 Сейчас в теме
(3) Я не вредитель, я - перфекционист - со времен программирования на Ассемблере не люблю избыточность в коде. Ну а Вы свою позицию обозначили, я ее упоминул в статье: "тише едешь - дальше будешь".
40. RailMen 828 12.10.13 00:14 Сейчас в теме
(4) достойно!
Обратил внимание только сейчас на ваше имя.
Хотя на этой недели с ребятами ознакомились с "батерфляем". Очень достойно.
Голосую за Вариант 6.
Выполнить() - это не безопасно и имеет смысл применять в очень ограниченных случаях.
Дожимать рефакторинг разбития периода до Выполнить() - это уже не перфекционизм, а полудикий трешь.

(36) Что касается использования Запроса для решения этой задачи - это не обосновано. А если надо все выполнить на клиенте? Будете сервер вызывать? А вот ildarovich не будет! Он может свою функцию вставить в общий модуль и задать ему свойства "клиент" и "сервер". И спокойно вызывать ее и с клиента и с сервера, когда потребуется.

Сам разность дат вычислял с применением запроса. Пока не заморочился с клиент серверной архитектурой.
user761890; +1 Ответить
42. RailMen 828 14.10.13 12:30 Сейчас в теме
(4)
Вот тут:
"Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(Край(А),Б)));А=Край(А)+1 КонецЦикла"
дважды встречается в тексте "Край(А)", а это значит...
корум; +1 Ответить
43. ildarovich 7938 14.10.13 14:28 Сейчас в теме
(42) В черновике статьи юмора было больше. Интересно, что одной из шуток была именно эта.
5. ildarovich 7938 09.09.13 00:21 Сейчас в теме
(2) Знаете, мне более близко определение из английской Википедии
Code refactoring is a "disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior", undertaken in order to improve some of the nonfunctional attributes of the software. Advantages include improved code readability and reduced complexity to improve the maintainability of the source code, as well as a more expressive internal architecture or object model to improve extensibility.
В нем НИЧЕГО НЕ ГОВОРИТСЯ об облегчении понимания программы. Рефакторинг - это любое улучшение качества кода, борьба за его чистоту. Как говорил Экзюпери
В любом деле совершенство достигается не тогда,когда больше нечего добавить, а тогда, когда больше нечего отнять
В моем понимании чистота кода - это отсутствие необоснованной избыточности. Все приемы,перечисленные в статье (за исключением 9-го, который готов отстаивать отдельно), это классические приемы рефакторинга, перечисленные и в русской Википедии тоже.
Так что не прячтесь за цитированием вырванных из контекста отрывков из Википедии, а объясните толком, конкретно, чем Вам не нравится вариант 2, например, или вариант 5. Или с каким приемам из 1-10 Вы не согласны.
6. mymyka 09.09.13 09:22 Сейчас в теме
(5)Избыточность кода никак не влияет на работу программы. Время исполнения отличается на микросекунды.
Данный "рефакторинг" увеличивает время разработки, ухудшает читабельность, увеличивает трудоемкость по внесению изменений сторонним разработчиком, усложняет отладку, делает невозможным подробное комментирование.
Не забывайте, мы все таки пишем бизнес-приложение, а не компилированный экземпляр ускоспециализированной программы. Если бизнес-приложение не развивается, это значит, что оно не используется.
Функция РазбитьПериод8(Знач А, Б, НаЧто = "Месяца", Поля = "НачалоПериода, КонецПериода") Экспорт    
    М = Новый Массив;     
    Выполнить(СтрЗаменить("Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(_(А),Б)));А=_(А)+1 КонецЦикла", "_", "Конец" + НаЧто));
    Возврат М
КонецФункции

А теперь просто добавьте сюда функционал, дающий возможность, при желании, исключить из периодов выходные и праздничные дни.
Перфекционизм это хорошо, особенно, когда за него платит заказчик.
user761890; Bazil; +2 Ответить
7. ildarovich 7938 09.09.13 10:15 Сейчас в теме
(6) Избыточность в коде - это мусор. Скажете, что мусор в лесу никак Вам мешает? Мусор в коде отвлекает наше внимание, забирает место на дисках, такты процессора, а в конечном счете - электроэнергию. Мусор в коде снижает его надежность, затрудняет внесение в него изменений.
Впрочем, на эту тему уже исписаны груды бумаги. Вот, например: "Раньше я думал, что системы становятся более гибкими благодаря тому, что в них добавляется новый код. Однако сейчас я пришел к выводу, что системы становятся более гибкими потому, что из них удаляют лишний код. Пространство вокруг кода обладает значительно большим потенциалом, чем сам код" (Майкл Федерс). "Добавить код в систему значительно проще, чем убрать оттуда код. Рефакторинг позволяет делать вам код настолько простым, насколько это возможно, благодаря этому вы можете сконцентрироваться на добавлении в код новых возможностей" (Кен Ауэр, Рой Миллер).
А Вы сами практикуете рефакторинг? Как Вы это делаете? Приведите пример хорошо отрефакторенной, с Вашей точки зрения функции!
Вы прицепились к приемы 9, который является, в некотором смысле, "провокацией", оправдывающей "отвязное" название статьи. Я отчасти соглашусь с Вами и заменю знак "_" в теле строки на нечто более осмысленное, например "Край". Тогда, на мой взгляд строка
"Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(Край(А),Б)));А=Край(А)+1 КонецЦикла"
будет вполне читаемой.
Любой рефакторинг увеличивает время разработки. Выигрыш получается потом.
Читабельность(забудьте на секунду про прием 9 - он исключение) я стараюсь не ухудшать.
Данная функция является готовым законченным решением. Она не требует внесения изменений внутри нее. Выходные и праздничные дни нужно исключать не "соединяя ужа с ежом" (такого бреда в 1С предостаточно), а постобработкой полученных на первом этапе периодов (подкинули отличную идею - обязательно покажу как это максимально просто сделать!), то есть еще важно правильно структурировать код.
Как раз для будущего развития мы и убираем постоянно мусор в коде, чтобы не спотыкаться о него впоследствии.
kalyaka; slimper; awk; +3 Ответить
8. mymyka 09.09.13 10:53 Сейчас в теме
(7)
Избыточность в коде - это мусор

Мусор это то, что нельзя использовать повторно. Подробный код - это залог на будущую модернизацию кода.
Любой рефакторинг увеличивает время разработки. Выигрыш получается потом.

Выигрыш в чем?? Замерьте время выполнения варианта 1 и варианта 9, там 0.1% прироста нет.
Данная функция является готовым законченным решением. Она не требует внесения изменений внутри нее. Выходные и праздничные дни нужно исключать не "соединяя ужа с ежом"

Т.е. вы призываете всех писать недокументируемый, недорабатываемый, неустойчивый к ошибкам код исключительно из личных предпочтений?
Рефакторинг провожу(и требую от подчиненных) только в случае:
1) недостаточной производительности выполняемого участка
2) отсутствие комментов в коде(при большой сложности решаемой задачи)
3) универсализация кода, который раньше был решением частной задачи, а теперь используется вторично.
4) необходимость влиять на результат без внесений изменений в код(из режима предприятия)
Пример рефакторинга(с увеличением производительности участка примерно в 12 раз)
Было
Скрытый текст

Стало
Скрытый текст


В итоге - базовый функционал не изменен, скорость работы и возможность доработки повышены на порядок. Код отвязан от предопределенных значений и устойчив к любым ошибкам пользователя. В качестве приятного бонуса появилась возможность редактировать формулы в режиме предприятия.
user761890; Pawlick; +2 Ответить
9. ildarovich 7938 09.09.13 11:42 Сейчас в теме
(8) Ага!
Очень жадная девочка пошла выбрасывать мусор, а вернулась с двумя пакетами


Код, устойчивый к ошибкам - это и есть мой код. Чем меньше код, тем меньше вероятность ошибки (могу доказать математически). Где легче найти ошибку: в 254 знаках или в 500? Кстати, поверьте, такой код практически не приходится отлаживать (вариант 5-7), поскольку в него сразу встроены необходимые проверки.

Посмотрел Ваш код. Выводы: "... и эти люди запрещают мне ковырять в носу!".
Для читабельности не хватает отступов.
Обязательно выделите в отдельные функции или процедуры часто используемые фрагменты кода. Сможете их использовать повторно (сэкономите деньги заказчика или свою прибыль повысите), а размер основной функции должен укладываться в страницу.
Видно, что заботы о красоте кода здесь пока нет, а жаль, тут есть где развернуться.
Для примера посмотрите код УТ11 - он достаточно красив, на него можно равняться.
12. mymyka 10.09.13 08:50 Сейчас в теме
(9)Отступы съел тэг спойлера,
Код, устойчивый к ошибкам - это и есть мой код

Код не имеющий ни одной проверки(лишние строчки же) даже на элементарную заполненость параметров, это НЕ устойчивый код.
Пример: в код, указанный в статье как эталонный, передаю 2 параметра, ДатаС не заполнена, ДатаПо 09.09.2013, итог - имею массив из 24152 периодов. А если я по этим периодам зарплату считаю? На каждый, например, для 200 сотрудников. Насколько залипнет 1С?. И это
Данная функция является готовым законченным решением

?
Где легче найти ошибку: в 254 знаках или в 500?

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

что там выносить в отдельную процедуру? объявления массивов, типов, цикл, запрос, добавление строки? как это позволит "сэкономить" чьи бы то ни было деньги?
Для примера посмотрите код УТ11 - он достаточно красив, на него можно равняться.

Так может сказать только тот, кто не дорабатывал УТ11. Отладка миллиона вложенных однострочных функций и тупиковых "Оповестить()" может пошатнуть даже самую стойкую психику. Для примера, при простом перепроведении заказа вызываются функции 24(!!!!) общих модулей.
Arc; user761890; Silenser; корум; klinval; alest; fzt; cheburashka; krv2k; It-developer; Garfild12; TaTaPuH-Magic; MikStyle; bulpi; +14 Ответить
54. alex_sayan 53 02.02.19 08:31 Сейчас в теме
(5)
В нем НИЧЕГО НЕ ГОВОРИТСЯ об облегчении понимания программы. Рефакторинг - это любое улучшение качества кода, борьба за его чистоту.

В моем понимании чистота кода - это отсутствие необоснованной избыточности


Приведу в пример лютый трешак, который бродит по интернету

Функция ПадежС(z1,Знач z2=2,Знач z3="*",z4=0) Экспорт
  z5=Найти(z1,"-");z6=?(z5=0,"","-"+ПадежС(Сред(z1,z5+1,СтрДлина(z1)-z5+1),z2,z3,z4));z1=?(z5=0,z1,Лев(z1,z5-1))//под составные слова 
  z1=НРег(?((z2<0)и(z4>1)и(z1<>""),Лев(z1,1)+".",z1));
  z7=Прав(z1,3);z8=Прав(z7,2);z9=Прав(z8,1);
  z2=?(((z4=2)и((z3="а")или(z3="ы"))и(Найти("бвгджзклмнопрстфхцчшщъиеу",z9)>0))или((z4=2)и(z3="ч")и(Найти("оиеу",z9)>0))или((z4=1)и(Найти("мия мяэ лия кия жая лея",z7)>0)),1,Макс(z2,-z2));
  z5=СтрДлина(z1);
  z10=Найти("ая ия ел ок яц ий па да ца ша ба та га ка",z8);
  z11=?(z4=1,?(Найти("оеиую",z9)+Найти("их ых аа еа ёа иа оа уа ыа эа юа яа",z8)>0,-1,?((z3="а")или(z3="ы"),?(z10=1,8,?(z9="а",?(z10>18,3,9),-1)),?(((Найти("ой ый",z8)>0)и(z5>4))или(Найти("гий жий кий ний чий хий ший щий",z7)>0),10,0))),0);
  z11=?(z11=0,?(z10=4,7,Найти(".чайяь",z9)), z11);
  z12=Найти("лец вей дец пец мец нец рец вец аец иец ыец бер бей",z7);
  z14=?((z11=10)и(z2<>5),?(Найти("чшщ",Лев(z7,1))+Найти("жий ний",z7)>0,"е","о"),?(z1="лев","ьв",?((Найти("аеёийоуэюя",Сред(z1,z5-3 ,1))+Найти("аеёийоуэюя",Лев(z7,1))=0)и(z12<>41),"",?(z10=7,"л",?(z10=10,"к",?(z10=13,"йц",?(z12=0,"",?((z12<9)или(z12=49),"ь"+?(z12=1,"ц",""),?(z12<33,"ц",?(z12<45,"йц","р"))))))))));
  z14=?((z2=1)или(z11<0)или((z4=3)и(z3="ы")или(""=z1)),z1,Лев(z1,z5-?((z11=8)или(z14<>"")или(z11=10),2,?(z11>2,1,0)))+z14+СокрП(Сред("а у а "+Сред("оыыыоео",Найти(" внтчц",z9)+1,1)+"ме           а у а еме "+?(Найти("гжкхш",Лев(z8,1))>0,"и","ы")+" е у ойе я ю я ем"+?(z10=16,"и","е")+" и е ю ейе и и ь ьюи и и ю ейи ойойуюойойойойу ойойгомуго"+?((z14="е")или(z10=16)или(Найти("гой хой кой",z7)>0),"и","ы")+"мм",10*?((z11=6)и(z3="ч"),4,z11)+2*z2-3,2)));
Возврат ?(z4>0,ВРег(Лев(z14,1))+Сред(z14,2),z14)+z6;
КонецФункции
Показать

Совершенно не читаемый говнокод, зато автор хорошо так сэкономил на строках и символах. "Никакой избыточности" и нулевая гибкость.
10. Yashazz 4798 09.09.13 17:26 Сейчас в теме
К сожалению, солидарен с Ильдаровичем. К сожалению потому, что иногда чрезмерно увлекаюсь означенным рефакторингом, вплоть до чистого эргономо-эстетства и оптимизации, когда сие уже не особенно требуется. Время иногда трачу слишком. Силы трачу несоразмерно. Перфекционизм, как он есть. :)
13. ildarovich 7938 10.09.13 10:34 Сейчас в теме
(10) Тут не о чем сожалеть. Работа должна приносить удовольствие, в том числе и эстетическое. Пожалеть нужно тех, кто занимается этим делом не из любви к искусству программирования, к процессу программирования, а как к скучной обязанности, экономя умственные усилия на работу с кодом. Посмотрите, что пишет Шон МакГраф (Shawn McGrath) — игровой разработчик, создатель популярной психоделической игры для Playstation 3 — паззла-гонки Dyad
В статье Исключительная красота исходного кода Doom 3
Да я, на самом деле, не слишком люблю называть себя «программистом». У меня неплохо получается, но для меня программирование длится ровно до того момента, как все начнет работать.

Получается, что не все пишушие код люди могут себя называть "программистами".
Впрочем, ремесленников всегда будет больше, как и кода в стиле "что вижу, о том пою". Я, со своей стороны, понимаю этих людей, в идеале хотелось, чтобы они меня понимали тоже. Но получается, что люди, которым не нравится опера, просто затыкают уши.
14. mymyka 10.09.13 10:50 Сейчас в теме
(13)Если вам работодатель готов платить за эстетические изыски исключительно из любви к высокому и прекрасному, рад за вас. Сочувствую ему и тому, кто придет после вас. Ибо этот ктулху-диалект 1Сного языка разобрать будет весьма и весьма непросто.
Но получается, что люди, которым не нравится опера, просто затыкают уши

копать карьер серебрянной ложечкой и во фраке, артистично оттопырив мизинчик, наверно очень эстетично, но в бизнесе обычно используют экскаватор, управляемый мужиками в промасленной спецовке.
user761890; fomaOp; help1Ckr; +3 Ответить
15. ildarovich 7938 10.09.13 12:15 Сейчас в теме
(14) Хорошо, копайте свои ямы, карьеры (недостаточно их ещё?), рубите лес, стригите "бабло". А мне дайте выращивать свой японский садик и делиться своими произведениями с другими. Ну и все-таки, поймите, профессии экскаваторщика и программиста очень разные. Трудно представить экскаваторщика, копающего по ночам на своем экскаваторе "для души". Возможно, когда нибудь потом (мы пришли в этот мир не для того, чтобы торопиться) Вам понадобится заровнять карьер и украсить пейзаж. Одна функция "в японском стиле" для этого у Вас уже есть.
kote; kalyaka; anreko; soulsteps; mickey.1cx; VZhulanov; Den_D; hogik; Yashazz; +9 Ответить
11. Гость 10.09.13 05:38
Я не вредитель, я - перфекционист - со времен программирования на Ассемблере не люблю избыточность в коде.


Автор, Вы не перфекционист, а обфускацианист. Сам себе обфускатор:)

Автор пишет код для себя и только для себя выступая в роли компилятора для 1С с лозунгом "после меня - хоть трава не расти". Для ассемблера подобный подход оправдан и то не всегда.

Автор, даешь перенос всего кода во внешние DLL. А здесь можно публиковать ассемблерный или бинарный код этих DLL. Мы ведь все Нео и видим блондинок в розовом в строчках кода
 Выполнить(СтрЗаменить("Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(Край(А),Б)));А=Край(А)+1 КонецЦикла", "Край", "Конец" + Чего));
user761890; alest; +2 Ответить
16. help1Ckr 11.09.13 09:59 Сейчас в теме
(105)Gazza,
согласен во многом с mymyka. Вы таки немного вредитель) ибо молодые юные программисты, которые пришли в 1с ибо не нашли себя на почве ассемблера и пошли в 1с пишут такой код, который потом фиг отладишь. Вам все таки стоит в статье больше внимания уделить пояснению что пункт 9 должен таки использоваться в том случае, когда процедура НИКОГДА не потребует изменения. Сам был увлекся рефакторингом кода пока не понял что все таки должна быть разумная средина) Одно дело сократить процедуру в 14000 строчек кода выбросив ненужные ответвления и сократив его до 3000 строк, другое дело втиснуть оставшиеся 3000 строчек в 10 но настолько непонятных, что доработка будет занимать больше времени чем поддержка 14000
user761890; AndrewKiev; +2 Ответить
17. eeeio 126 11.09.13 10:09 Сейчас в теме
На мой взгляд, стоило бы остановиться после шага 5. Итоговый результат тяжел для понимания (и не работает в безопасном режиме).
18. ildarovich 7938 11.09.13 10:47 Сейчас в теме
(17) Мои личные предпочтения - между 2(из-за краткости) и 6(из-за самоконтролируемости кода и гибкости). Я нарочно оставил все варианты, чтобы можно было обсудить и выбрать. Вижу, что прием 9 мало кому понравился, но все же: использовать одну функцию вместо 8-ми показалось очень заманчиво! Планирую еще усилить провокацию и перевести последний вариант на английский - тогда вариантов станет ровно 10 (с 0 по 9) и устроить опрос.
19. МимохожийОднако 142 11.09.13 11:57 Сейчас в теме
20. ildarovich 7938 11.09.13 15:00 Сейчас в теме
21. bulpi 217 11.09.13 16:25 Сейчас в теме
Да вы все не о том спорите, господа. Автор написал статью. Статья интересная ? Несомненно! Нужная ? Конечно! А вот применять описанные приемы, или нет - личное дело каждого. По мне, так и вариант 0 был неплох. Но знать приемы надо, хотя бы для того, чтобы потом разбирать такое вот творчество.
22. Pawlick 10 13.09.13 11:15 Сейчас в теме
По моему вот этот код будет:
а) работать быстрее
б) понятнее для коллег

Функция РазбитьПериод(ДатаНачало, ДатаКонец) 

Запрос = Новый Запрос; 
Запрос.Текст = 
"ВЫБРАТЬ 
|	РАЗНОСТЬДАТ(&ДатаНачало, &ДатаКонец, МЕСЯЦ) КАК РазностьДат"; 
Запрос.УстановитьПараметр("ДатаНачало",ДатаНачало); 
Запрос.УстановитьПараметр("ДатаКонец",ДатаКонец); 
РазностьДат = Запрос.Выполнить().Выгрузить()[0].РазностьДат; 

МассивПериодов = Новый Массив; 

Интератор = РазностьДат - (РазностьДат * 2); 

Пока Интератор <= 0 Цикл 

Запрос = Новый Запрос( 
"ВЫБРАТЬ 
|	НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ," + Интератор + "), МЕСЯЦ) КАК НачалоПериода, 
|	КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ," + Интератор + "), МЕСЯЦ) КАК КонецПериода"); 
Запрос.УстановитьПараметр("ДатаНачало",ДатаНачало); 

Выборка = Запрос.Выполнить().Выбрать(); 
Выборка.Следующий(); 

ЗаписьПериода = Новый Структура; 
ЗаписьПериода.Вставить("НачалоПериода", Выборка.НачалоПериода); 
ЗаписьПериода.Вставить("КонецПериода", Выборка.КонецПериода); 
МассивПериодов.Добавить(ЗаписьПериода); 
Интератор = Интератор + 1; 

КонецЦикла; 

Возврат МассивПериодов 

КонецФункции
Показать
23. mymyka 13.09.13 11:21 Сейчас в теме
(22)тут есть тег кода с подсветкой )
51. kote 537 24.09.18 00:49 Сейчас в теме
(22)
Быстрее не будет.
Будет медленнее.
"Дергать" БД на каждой итерации очень "расточительно"..

Код 1С будет работать заметно шустрее.
Особенно, если функцию вызывать из внешнего цикла на небольших входных данных.
24. Pawlick 10 13.09.13 11:27 Сейчас в теме
Разукрашка почему то не работает.
Получается вот что:

<p style="text-align: left; font-family: courier new,courier; color: blue">
<font color=red>Функция </font>РазбитьПериод<font color=red>(</font>ДатаНачало<font color=red>, </font>ДатаКонец<font color=red>)



    </font>Запрос <font color=red>= Новый </font>Запрос<font color=red>;

    </font>Запрос<font color=red>.</font>Текст <font color=red>=

    </font><font color=black>"ВЫБРАТЬ

    |   РАЗНОСТЬДАТ(&ДатаНачало, &ДатаКонец, МЕСЯЦ) КАК РазностьДат"</font><font color=red>;

    </font>Запрос<font color=red>.</font>УстановитьПараметр<font color=red>(</font><font color=black>"ДатаНачало"</font><font color=red>,</font>ДатаНачало<font color=red>);

    </font>Запрос<font color=red>.</font>УстановитьПараметр<font color=red>(</font><font color=black>"ДатаКонец"</font><font color=red>,</font>ДатаКонец<font color=red>);

    </font>Результат <font color=red>= </font>Запрос<font color=red>.</font>Выполнить<font color=red>().</font>Выбрать<font color=red>().</font>Следующий<font color=red>();

    </font>РазностьДат <font color=red>= </font>Запрос<font color=red>.</font>Выполнить<font color=red>().</font>Выгрузить<font color=red>()[</font><font color=black>0</font><font color=red>].</font>РазностьДат<font color=red>;



    </font>МассивПериодов <font color=red>= Новый </font>Массив<font color=red>;



    </font>Интератор <font color=red>= </font>РазностьДат <font color=red>- (</font>РазностьДат <font color=red>* </font><font color=black>2</font><font color=red>);



    Пока </font>Интератор <font color=red><</font><font color=red>= </font><font color=black>0 </font><font color=red>Цикл



        </font>Запрос <font color=red>= Новый </font>Запрос<font color=red>(

        </font><font color=black>"ВЫБРАТЬ

        |   НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ," </font><font color=red>+ </font>Интератор <font color=red>+ </font><font color=black>"), МЕСЯЦ) КАК НачалоПериода,

        |   КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ," </font><font color=red>+ </font>Интератор <font color=red>+ </font><font color=black>"), МЕСЯЦ) КАК КонецПериода"</font><font color=red>);

        </font>Запрос<font color=red>.</font>УстановитьПараметр<font color=red>(</font><font color=black>"ДатаНачало"</font><font color=red>,</font>ДатаНачало<font color=red>);



        </font>Выборка <font color=red>= </font>Запрос<font color=red>.</font>Выполнить<font color=red>().</font>Выбрать<font color=red>();

        </font>Выборка<font color=red>.</font>Следующий<font color=red>();



        </font>ЗаписьПериода <font color=red>= Новый </font>Структура<font color=red>;

        </font>ЗаписьПериода<font color=red>.</font>Вставить<font color=red>(</font><font color=black>"НачалоПериода"</font><font color=red>, </font>Выборка<font color=red>.</font>НачалоПериода<font color=red>);

        </font>ЗаписьПериода<font color=red>.</font>Вставить<font color=red>(</font><font color=black>"КонецПериода"</font><font color=red>, </font>Выборка<font color=red>.</font>КонецПериода<font color=red>);

        </font>МассивПериодов<font color=red>.</font>Добавить<font color=red>(</font>ЗаписьПериода<font color=red>);

        </font>Интератор <font color=red>= </font>Интератор <font color=red>+ </font><font color=black>1</font><font color=red>;



    КонецЦикла;



    Возврат </font>МассивПериодов



<font color=red>КонецФункции

</font></p>

в чем может быть проблема?
25. mymyka 13.09.13 11:32 Сейчас в теме
(24)Сейчас тебя сожрут за запрос в цикле )
26. Pawlick 10 13.09.13 11:41 Сейчас в теме
(25) mymyka,

Возможно...

Но если добавить проверку на пустые даты, то ...
27. Pawlick 10 13.09.13 11:43 Сейчас в теме
Ща сделаю формирование текста запроса в цикле, тогда может и не сожрут
28. Pawlick 10 13.09.13 12:05 Сейчас в теме
Вот. Вариант №2.
В цикле формируем не запрос для получения каждого по отдельности элемента массива, а текст запроса.
Потом выгружаем запрос в таблицу, а из нее уже формируем массив.
Хотя для реальной задачи формировать массив нет необходимости: можно вернуть сразу таблицу.

Функция РазбитьПериод1(ДатаНачало, ДатаКонец)
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	РАЗНОСТЬДАТ(&ДатаНачало, &ДатаКонец, МЕСЯЦ) КАК РазностьДат";
	Запрос.УстановитьПараметр("ДатаНачало",ДатаНачало);
	Запрос.УстановитьПараметр("ДатаКонец",ДатаКонец);
	РазностьДат = Запрос.Выполнить().Выгрузить()[0].РазностьДат;
	
	МассивПериодов = Новый Массив;
	
	Интератор = РазностьДат - (РазностьДат * 2);
	Запрос = Новый Запрос;
	Текст = "";
	
	Пока Интератор <= 0 Цикл
		
		Текст = Текст + 
		"ВЫБРАТЬ НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ," + Интератор + "), МЕСЯЦ) КАК НачалоПериода, 
		| КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ," + Интератор + "), МЕСЯЦ) КАК КонецПериода
		| ОБЪЕДИНИТЬ " + Символы.ПС;
		
		
		Интератор = Интератор + 1;
	КонецЦикла;
	
	Текст = Лев(Текст,СтрДлина(Текст) - 14);
	Запрос.Текст = Текст;
	Запрос.УстановитьПараметр("ДатаНачало",ДатаНачало);
	//
	Выборка = Запрос.Выполнить().Выгрузить();
	
	Для Каждого Строка Из Выборка Цикл
		
		ЗаписьПериода = Новый Структура;
		ЗаписьПериода.Вставить("НачалоПериода", Строка.НачалоПериода);
		ЗаписьПериода.Вставить("КонецПериода", Строка.КонецПериода);
		МассивПериодов.Добавить(ЗаписьПериода);
		
	КонецЦикла;
	
	Возврат МассивПериодов
	
КонецФункции
Показать
29. ildarovich 7938 14.09.13 14:40 Сейчас в теме
(28)
Худенькая девушка считает себя толстой. Толстая - жирной. А жирная одела леопардовые лосины и красавица!
К чему это я? - Посмотрите на свой код со стороны! Во-первых, он не работает. Задайте интервал с 1-го по 14-е сентября - вываливается с ошибкой. С 1-го сентября 2000 года - интервалы "не те". А почему так? - Где-то спряталась ошибка! В 31-ой строке и 1089 символах Вашего кода есть где спрятаться. Во вторых, если читать код со скоростью 100 символов в минуту, только на чтение Вашего кода уйдет 10 минут, а моего - 2,5 минуты. А ведь, чтобы понять код, нужно его хотя бы прочитать, а возможно, и не один раз. Так что мой код понимается быстрее. В-третьих, время выполнения Вашего кода в 10!!! раз больше моего (проверял на 200 месяцах - 0,140 сек против 0,016, при этом из-за чувствительности таймера выигрыш может быть и больше). Использовать запросы в этой задаче - мешать чай в стакане ковшом экскаватора - это не то, чтобы не эстетично, а еще и не гигиенично.
ixijixi; kalyaka; troubleshooter; 1cWin; +4 Ответить
33. Pawlick 10 15.09.13 22:51 Сейчас в теме
(29) Ув. ildarovich!

Худенькая девушка считает себя толстой. Толстая - жирной. А жирная одела леопардовые лосины и красавица!. К чему это я?


А Действительно, к чему ?!

Вы уж меня простите, я немножко Ваши мысли в кучу соберу:
1. По условиям задачи, установленным ВАМИ:
Функция, используемая для примера, решает задачу разбиения периода времени, заданного начальной и конечной датой, на отрезки, принадлежащие различным месяцам.

далее Вы пишите:
Задайте интервал с 1-го по 14-е сентября

Что то я в Ваших "стараниях" не увидел "функции разбивающей период времени с 1 по 14 сентября на отрезки, принадлежащие различным месяцам."
Может на калькуляторе попробуете?

2.
Посмотрите на свой код со стороны! А ведь, чтобы понять код, нужно его хотя бы прочитать, а возможно, и не один раз. Так что мой код понимается быстрее.

Да, особенно в Варианте 6. Я его пока читал все понял... Даже до конца не прочитал, а уже все понял.
А потом перешел к варианту 7 и 8 и ... бросил: легче самому нибудь придумать. Да еще и отладить нельзя. Замечательный "рефакторинг". А при разнице выполнения в милисекундах при 200 периодах ЧИТАБЕЛЬНОСТЬ ИМХО, будет являться ОСНОВНЫМ ПОКАЗАТЕЛЕМ УДАЧНОГО РЕФАКТОРИНГА. Включите мой вариант в голосование, там видно будет, чей читабельнее...

Ну и напоследок:
3. Я Вам Вас процитирую:
В статье Рефакторинг без тормозов (десять приемов в одной задаче) было предложено ДЕСЯТЬ! разных вариантов решения одной и той же задачи, возникшие в процессе "улучшения" кода функции. В том числе довольно неоднозначные и даже провокационные по своей форме.

Использовать запросы в этой задаче - мешать чай в стакане ковшом экскаватора - это не то, чтобы не эстетично, а еще и не гигиенично.


"Довольно неоднозначное и даже провокационное по своей форме решение" использование оператора Выполнить(), помещая в него текст с кодом, я бы назвал "порнографично".
Ваша статья: это бравада, "смотри как я умею, вот так умею, и так умею". И уж к рефакторингу она ТОЧНО не имеют НИКАКОГО отношения. На практике ни один вменяемый программист не будет использовать Ваш вариант №8.
user761890; +1 Ответить
30. krv2k 377 14.09.13 16:12 Сейчас в теме
(0) Автор, попробуйте подумать в другом направлении:
1) берем вариант 2
2) добавляем две новые универсальный функции "НачалоПериода(Дата, Период)" и "КонецПериода(Дата, Период)" (аналоги функций из языка запросов)
3) получаем компактный, понятный и универсальный вариант
ildarovich; +1 Ответить
31. ildarovich 7938 14.09.13 16:47 Сейчас в теме
(30) Отличное предложение! - Правда, придется себя сдерживать, чтобы не написать
Функция НачалоПериода(Дата, Период)
    Выполнить(СтрЗаменить("Возврат НачалоЧего(Дата)", "Чего", Период))
КонецФункции
Ну а в общем-то, статья все-таки, как здесь уже говорилось, посвящена не конкретной функции, а демонстрации различных приемов, которые показалось возможным показать на одном удобном примере.
Также обратите, пожалуйста, внимание на вариант 5. Он кажется более громоздким, но это пример самоконтролируемой функции, записанной через требования к результату.
Ну и наконец, если Вас интересуют другие примеры сублимированного кода 1С, обратите внимание на мой блог.
32. krv2k 377 14.09.13 17:46 Сейчас в теме
(31)
Ну а в общем-то, статья все-таки, как здесь уже говорилось, посвящена не конкретной функции, а демонстрации различных приемов, которые показалось возможным показать на одном удобном примере.

Всё, что идёт после варианта №2, считаю деструктивным рефакторингом, здесь мне ближе позиция (2). Но это ИМХО, ничего личного.

Также обратите, пожалуйста, внимание на вариант 5. Он кажется более громоздким, но это пример самоконтролируемой функции, записанной через требования к результату.

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

Ну и наконец, если Вас интересуют другие примеры сублимированного кода 1С, обратите внимание на мой блог.

Спасибо, на досуге почитаю.
34. Pawlick 10 15.09.13 23:21 Сейчас в теме
Во-первых, он не работает. Задайте интервал с 1-го по 14-е сентября - вываливается с ошибкой.


при заданных датах с 1-го по 14-е сентября возвращает массив с одним элементом:
01.09.2013 00.00.00 - 31.09.2013.23.59.59,

все работает.

Что касается периода с 01.09.2000, действительно, результат был не корректен: спешил, писал, пракически без проверки.
Выкладываю исправленный вариант.
user761890; +1 Ответить
36. Pawlick 10 15.09.13 23:26 Сейчас в теме
Опять почему то разукрашка не сработала, выкладываю в чистом виде:
Функция РазбитьПериод(ДатаНачало, ДатаКонец)
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	РАЗНОСТЬДАТ(&ДатаНачало, &ДатаКонец, МЕСЯЦ) КАК РазностьДат";
	Запрос.УстановитьПараметр("ДатаНачало",ДатаНачало);
	Запрос.УстановитьПараметр("ДатаКонец",ДатаКонец);

	РазностьДат = Запрос.Выполнить().Выгрузить()[0].РазностьДат;
	
	МассивПериодов = Новый Массив;
	
	Запрос = Новый Запрос;
	
	Интератор = 0;	
	Пока Интератор <= РазностьДат Цикл
		
		Запрос.Текст = Запрос.Текст + 
		"ВЫБРАТЬ НАЧАЛОПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ," + Интератор + "), МЕСЯЦ) КАК НачалоПериода, 
		| КОНЕЦПЕРИОДА(ДОБАВИТЬКДАТЕ(&ДатаНачало, МЕСЯЦ," + Интератор + "), МЕСЯЦ) КАК КонецПериода
		| ОБЪЕДИНИТЬ " + Символы.ПС;
	
		Интератор = Интератор + 1;
	КонецЦикла;
	
	Запрос.Текст = Лев(Запрос.Текст,СтрДлина(Запрос.Текст) - 14);
	
	Запрос.УстановитьПараметр("ДатаНачало",ДатаНачало);

	ТаблицаПериодов = Запрос.Выполнить().Выгрузить();
	
	Для Каждого Строка Из ТаблицаПериодов Цикл
		
		ЗаписьПериода = Новый Структура;
		ЗаписьПериода.Вставить("НачалоПериода", Строка.НачалоПериода);
		ЗаписьПериода.Вставить("КонецПериода", Строка.КонецПериода);
		МассивПериодов.Добавить(ЗаписьПериода);
		
	КонецЦикла;
	
	Возврат МассивПериодов;
	
КонецФункции
Показать
41. RailMen 828 12.10.13 00:29 Сейчас в теме
(36) Товарищ...(где моя металлическая линейка)...запрос то в цикле...
37. wbazil 140 16.09.13 11:40 Сейчас в теме
прочитал статью с большим удовольствием, спасибо больше
в результате чтения получилась небольшая таблица
	мПер = РазбитьПериод0(Дата(1175,05,02),Дата(2213,11,15)); //320
	мПер = РазбитьПериод1(Дата(1175,05,02),Дата(2213,11,15)); //225
	мПер = РазбитьПериод2(Дата(1175,05,02),Дата(2213,11,15)); //160
	мПер = РазбитьПериод5(Дата(1175,05,02),Дата(2213,11,15)); //310
	мПер = РазбитьПериод6(Дата(1175,05,02),Дата(2213,11,15)); //300
	мПер = РазбитьПериод7(Дата(1175,05,02),Дата(2213,11,15)); //210
	мПер = РазбитьПериод8(Дата(1175,05,02),Дата(2213,11,15)); //85
	мПер = РазбитьПериод9(Дата(1175,05,02),Дата(2213,11,15)); //85
Показать


в конце после комментария указано время в миллисекундах
результат от первого и последнего отличается в 3,8 РАЗА!! это поражает
хотя для себя я бы остановился на РазбитьПериод2 как выигрыш в два раза уже получен, а код ещё читабелен. результат 8 и 9 конечно отличный, но увидеть первый раз такой код в нем без "бутылки" не разобраться.
fzt; AlexanderKai; RailMen; ildarovich; +4 Ответить
38. krv2k 377 16.09.13 20:18 Сейчас в теме
(37) wbazil, Напишите варианты 8 и 9 одной строкой, результат будет ещё лучше.
39. wbazil 140 17.09.13 08:58 Сейчас в теме
результат хоть и не на много но лучше:
73
79
82
78
78
44. kuzev 48 14.10.13 17:14 Сейчас в теме
ildarovich, твоя статья мне напоминает решение головоломки, целью решения которой является получение удовольствие от процесса. Разминка для ума, так сказать.
Ты не одинок, тоже страдаю периодически =) Ниже мой велосипед начала 90-х. Задача для cебя была - минимум строк на BASIC-е. Сейчас смотрю с ужасом =)

10 INPUT "АРАБСКОЕ ЧИСЛО: "; А$
20 FOR I=0 TO LEN(A$)-1
30 X=VAL(MID$(A$,LEN(A$)-I,1))
40 IF X=4 OR X=9 THEN B$=MID$("IXCM",I+1,1)+MID$("VXLCDM",I*2+(X+1)/5,1)+B$
50 IF X<4 THEN B$=MID$("IIIXXXCCCMMM",1+I*3,X)+B$
ELSE IF X>4 AND X<9 THEN B$=MID$("VLD",I+1,1)+MID$("IIIXXXCCCMMM",1+I*3,X-5)+B$
60 NEXT I
70 PRINT "РИМСКОЕ ЧИСЛО: "; B$
45. asved.ru 37 10.06.14 11:43 Сейчас в теме
perl -e '$??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`~{;;y; -/:-@[-`{|~};`-{/" *-;;s;;$_;see'
49. ildarovich 7938 11.06.14 11:17 Сейчас в теме
50. asved.ru 37 12.06.14 04:52 Сейчас в теме
(49) это как напоминание, до чего может довести особо нездоровый рефакторинг, так и указание, что в таком случае делать.
46. kot30688 3 11.06.14 09:01 Сейчас в теме
Интересный вариант. А если организовать все это дело в запрос, не в цикле, а "прямой" - к любому периодическому регистру накоплений, периодичность запрашивать в нужном отрезке времени (хоть до секунды) - не читабельней и быстрее ли это будет?
47. fzt 11.06.14 09:53 Сейчас в теме
Все было хорошо до варианта 5.
Было легко читать, легко расширить, легко отладить.
Дальше пошли крайности. Да так тоже будет работать, но это неприемлемо. Трудно читать, трудно сопровождать и чтобы отладить - придется модифицировать код. Я бы не заострил своё внимание, если не комментарии автора. Он уверен что так нужно делать.
Увидев у своих кодеров что-то похожее на варианты старше 4, они бы рисковали стать безработными, пока получали по ушам.
Автору хочется пожелать повзрослеть. Наконец понять что программирование - такое же, местами кстати тупое, вкалывание, как работа экскаваторщика. Рано или поздно ты прекратишь заниматься научной мастурбацией, это у всех взрослых дядек проходит.

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

И я практиковал ассемблер. В ваших байтах по сколько бит бывало? ;-) C,Cpp,Delphi,php,python,java,js etc etc.. не просто знаю кучу страшных слов, а реально умею ими работу работать. В данный момент практикую с микроконтроллерами. Знаешь, даже с ними уже нет проблем, когда не влазит байт, или даже килобайт. Памяти много и она дешевая.
user761890; Sergey.Noskov; unichkin; +3 Ответить
48. ildarovich 7938 11.06.14 11:15 Сейчас в теме
(47) fzt, вы пишете
Он уверен что так нужно делать
Прочитал еще раз все комментарии. Действительно, так может показаться. Но на самом деле это не так. Я защищал свою позицию, которая заключается в том, что код нужно постоянно улучшать и поэтому писать в несколько проходов, а не в один и, возможно, в нескольких местах не сделал нужные оговорки. Наверное, это была чрезмерная защитная реакция из-за обвинений в обфускации.
В статье я предложил 10 приемов для использования не всегда всех вместе, а каждого при необходимости и с оговоркой рисков. В комментарии (18) я уже написал
Мои личные предпочтения - между 2(из-за краткости) и 6(из-за самоконтролируемости кода и гибкости). Я нарочно оставил все варианты, чтобы можно было обсудить и выбрать
А суть варианта 5 вы поняли? - Она весьма интересна. Или не стали вникать из-за его "многобуквенности"? А как вы относитесь к приемам 7, 8 и 10?
52. kote 537 24.09.18 00:52 Сейчас в теме
Немного некорректно подощли к метрике сложности..
Код спрятанный в Выполнить() - не учитывается при вычислении цикломатической сложности. А он может быть любой сложности..
53. alex_sayan 53 02.02.19 08:08 Сейчас в теме
Ужасный пример рефакторинга. Избавление от цикломатической сложности своей целью подразумевает снижение сложности кода. А тут всё с точностью до наоборот, сложность кода только повышается.
55. пользователь 26.09.23 09:25
Сообщение было скрыто модератором.
...
Оставьте свое сообщение