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

11.09.13

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

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

Скачать файлы

Наименование Файл Версия Размер
РазбитьПериод.erf
.erf 10,41Kb
4
.erf 10,41Kb 4 Скачать

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

Когда понадобился новый оператор, но его нет в синтакс-помощнике, что делать?

18.03.2024    1154    ZhokhovM    2    

4

Когда разработчик платформы не добавил проверку препроцессоров

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

Когда разработчик платформы решил пойти на кухню за кофе, а проверку препроцессоров не добавил, и вот тут-то и началось: "Что, опять все сломалось? Ну и кофе же я забыл сделать!".😅

18.03.2024    2682    ZhokhovM    4    

8

Реструктуризация - бесконечная история

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

При разработке программ требуемый функционал ставят на первое место, но есть еще и архитектура программы. На горизонте 5-10 лет она становится важнее функционала, который должен работать при масштабировании и росте данных. Реструктуризация 5 терабайтной базы 1С 8.2 в формат 1С 8.3, складывает весь пазл архитектурных просчетов, которые сделали ради функционала. Как это исправить? - для разработки правильной архитектуры, нужно всего лишь сместить фокус с функционала и подумать о «вечном».

29.09.2023    1909    1CUnlimited    15    

22

Чистый код. Мой взгляд на жизнь в макаронных джунглях. Часть 2

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

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

27.09.2023    6969    Lemmonbri    136    

36

Чистый код. Мой взгляд на жизнь в макаронных джунглях. Часть 1

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

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

19.09.2023    4347    Lemmonbri    16    

31

5 подходов при доработке конфигурации 1С, чтобы в будущем не было мучительно больно её обновлять

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

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

10.08.2023    9587    0    1c-izhtc    37    

21

Задача на ошибки и неоптимальности при проведении приходной накладной

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

Задачу эту дают на собеседованиях, видимо, те франчи, которые не в состоянии оценить человека по резюме и в ходе беседы. По идее задачи, подобные этой, должны давать начинающим студентам. Но дают всем подряд. Итак: мои 5 копеек. Критика приветствуется.

11.07.2023    2214    magic1s    32    

11
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. ivanov660 4330 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 483 08.09.13 21:49 Сейчас в теме
(2) mymyka,
mymyka прав :)
а автор вредитель :)
user761890; +1 Ответить
4. ildarovich 7850 08.09.13 23:42 Сейчас в теме
(3) Я не вредитель, я - перфекционист - со времен программирования на Ассемблере не люблю избыточность в коде. Ну а Вы свою позицию обозначили, я ее упоминул в статье: "тише едешь - дальше будешь".
40. RailMen 823 12.10.13 00:14 Сейчас в теме
(4) достойно!
Обратил внимание только сейчас на ваше имя.
Хотя на этой недели с ребятами ознакомились с "батерфляем". Очень достойно.
Голосую за Вариант 6.
Выполнить() - это не безопасно и имеет смысл применять в очень ограниченных случаях.
Дожимать рефакторинг разбития периода до Выполнить() - это уже не перфекционизм, а полудикий трешь.

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

Сам разность дат вычислял с применением запроса. Пока не заморочился с клиент серверной архитектурой.
user761890; +1 Ответить
42. RailMen 823 14.10.13 12:30 Сейчас в теме
(4)
Вот тут:
"Пока А< =Б Цикл М.Добавить(Новый Структура(Поля,А,Мин(Край(А),Б)));А=Край(А)+1 КонецЦикла"
дважды встречается в тексте "Край(А)", а это значит...
корум; +1 Ответить
43. ildarovich 7850 14.10.13 14:28 Сейчас в теме
(42) В черновике статьи юмора было больше. Интересно, что одной из шуток была именно эта.
5. ildarovich 7850 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 7850 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 7850 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 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 4709 09.09.13 17:26 Сейчас в теме
К сожалению, солидарен с Ильдаровичем. К сожалению потому, что иногда чрезмерно увлекаюсь означенным рефакторингом, вплоть до чистого эргономо-эстетства и оптимизации, когда сие уже не особенно требуется. Время иногда трачу слишком. Силы трачу несоразмерно. Перфекционизм, как он есть. :)
13. ildarovich 7850 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 7850 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 123 11.09.13 10:09 Сейчас в теме
На мой взгляд, стоило бы остановиться после шага 5. Итоговый результат тяжел для понимания (и не работает в безопасном режиме).
18. ildarovich 7850 11.09.13 10:47 Сейчас в теме
(17) Мои личные предпочтения - между 2(из-за краткости) и 6(из-за самоконтролируемости кода и гибкости). Я нарочно оставил все варианты, чтобы можно было обсудить и выбрать. Вижу, что прием 9 мало кому понравился, но все же: использовать одну функцию вместо 8-ми показалось очень заманчиво! Планирую еще усилить провокацию и перевести последний вариант на английский - тогда вариантов станет ровно 10 (с 0 по 9) и устроить опрос.
19. МимохожийОднако 141 11.09.13 11:57 Сейчас в теме
20. ildarovich 7850 11.09.13 15:00 Сейчас в теме
21. bulpi 215 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 536 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 7850 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 375 14.09.13 16:12 Сейчас в теме
(0) Автор, попробуйте подумать в другом направлении:
1) берем вариант 2
2) добавляем две новые универсальный функции "НачалоПериода(Дата, Период)" и "КонецПериода(Дата, Период)" (аналоги функций из языка запросов)
3) получаем компактный, понятный и универсальный вариант
ildarovich; +1 Ответить
31. ildarovich 7850 14.09.13 16:47 Сейчас в теме
(30) Отличное предложение! - Правда, придется себя сдерживать, чтобы не написать
Функция НачалоПериода(Дата, Период)
    Выполнить(СтрЗаменить("Возврат НачалоЧего(Дата)", "Чего", Период))
КонецФункции
Ну а в общем-то, статья все-таки, как здесь уже говорилось, посвящена не конкретной функции, а демонстрации различных приемов, которые показалось возможным показать на одном удобном примере.
Также обратите, пожалуйста, внимание на вариант 5. Он кажется более громоздким, но это пример самоконтролируемой функции, записанной через требования к результату.
Ну и наконец, если Вас интересуют другие примеры сублимированного кода 1С, обратите внимание на мой блог.
32. krv2k 375 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 823 12.10.13 00:29 Сейчас в теме
(36) Товарищ...(где моя металлическая линейка)...запрос то в цикле...
37. wbazil 138 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 375 16.09.13 20:18 Сейчас в теме
(37) wbazil, Напишите варианты 8 и 9 одной строкой, результат будет ещё лучше.
39. wbazil 138 17.09.13 08:58 Сейчас в теме
результат хоть и не на много но лучше:
73
79
82
78
78
44. kuzev 47 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 36 10.06.14 11:43 Сейчас в теме
perl -e '$??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`~{;;y; -/:-@[-`{|~};`-{/" *-;;s;;$_;see'
49. ildarovich 7850 11.06.14 11:17 Сейчас в теме
50. asved.ru 36 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 7850 11.06.14 11:15 Сейчас в теме
(47) fzt, вы пишете
Он уверен что так нужно делать
Прочитал еще раз все комментарии. Действительно, так может показаться. Но на самом деле это не так. Я защищал свою позицию, которая заключается в том, что код нужно постоянно улучшать и поэтому писать в несколько проходов, а не в один и, возможно, в нескольких местах не сделал нужные оговорки. Наверное, это была чрезмерная защитная реакция из-за обвинений в обфускации.
В статье я предложил 10 приемов для использования не всегда всех вместе, а каждого при необходимости и с оговоркой рисков. В комментарии (18) я уже написал
Мои личные предпочтения - между 2(из-за краткости) и 6(из-за самоконтролируемости кода и гибкости). Я нарочно оставил все варианты, чтобы можно было обсудить и выбрать
А суть варианта 5 вы поняли? - Она весьма интересна. Или не стали вникать из-за его "многобуквенности"? А как вы относитесь к приемам 7, 8 и 10?
52. kote 536 24.09.18 00:52 Сейчас в теме
Немного некорректно подощли к метрике сложности..
Код спрятанный в Выполнить() - не учитывается при вычислении цикломатической сложности. А он может быть любой сложности..
53. alex_sayan 02.02.19 08:08 Сейчас в теме
Ужасный пример рефакторинга. Избавление от цикломатической сложности своей целью подразумевает снижение сложности кода. А тут всё с точностью до наоборот, сложность кода только повышается.
55. пользователь 26.09.23 09:25
Сообщение было скрыто модератором.
...
Оставьте свое сообщение