IE 2016

КопиПастаМер

Опубликовал ildarovich в раздел Программирование - Инструментарий

Предлагается отчет, который за приемлемое время находит и показывает ВСЕ повторяющиеся фрагменты в текстах программных модулей анализируемой конфигурации. Приводятся подробности реализации отчета, основанного на алгоритме Манбера и Майерса построения суффиксного массива и на алгоритме Касаи построения LCP-массива. В данной реализации поиск повторов ведется до уровня строк. Отчет можно применять для определения повторяющихся последовательностей строк и в любых других текстах.

Считать ли злом копирование фрагментов кода (копипаст) впроцессе программировании на 1С – решайте сами. Есть другой интересный вопрос – как найти и измерить копипаст в уженаписанной программе. Одна из возможностей - использование предлагаемого отчета.

Перед использованием отчета тексты программных модулей анализируемой конфигурации необходимо выгрузить в некоторую папку. Это можно сделать через конфигуратор с использованием пункта меню "Конфигурация\Выгрузить файлы конфигурации". Далее можно запустить формирование отчета, указав ту папку, в которую были выгружены файлы. Через несколько минут (время зависит от общего числа строк в программных модулях) отчет покажет список повторов в виде таблицы, каждая запись которой содержит размер повторяющегося фрагмента в строках, место фрагмента и его копии в сквозной нумерации строк всех модулей. Выделив конкретный повтор в списке, можно увидеть сам фрагмент, имя содержащего его модуля и номер строки начала фрагмента в данном модуле, а также имя модуля и номер строки копии фрагмента. 

Применив отчет к некоторым типовым конфигурациям, можно увидеть, что например, в 1С: Бухгалтерии 2.0 общее число строк всех модулей конфигурации превышает 3,5 миллиона (на их анализ ушло порядка 20 минут). При этом имеется очень большое количество повторений фрагментов. В основном повторяются тексты модулей в регламентированной отчетности. Длина цельнотянутых кусков достигает 10 тысяч строк! А повторение тысячи строк в этой подсистеме - вообще норма. В других подсистемах также можно встретить очень большие повторяющиеся куски. Впрочем, лучше один раз увидеть, чем сто раз услышать: смотрите и удивляйтесь!

Несколько слов о реализации.

Основная идея метода - использование LCP-массива, который строится по конкатенации текстов модулей анализируемой конфигурации.

Формирование отчета состоит из этапов:
  1. Чтение текстов модулей. При этом строки модулей получают сквозную нумерацию в массиве "Ранг", запоминаются размеры модулей (чтобы потом можно было восстановить имя модуля и номер строки в нем), сама строка обрезается от пробелов слева и справа и получает ранг, равный количеству различных строк, встреченных в текстах модулей ранее. Таким образом, все разные строки обозначаются в массиве "Ранг" разными числами от нуля до старшего номера.
  2. Построение суффиксного массива. Входной строкой при этом считается последовательность элементов массива "Ранг". Здесь используется алгоритм, изобретенный в 1993 году Манбером (сейчас вице-президент Гугла) и Майерсом. Особенности данной реализации в том, что строка для удобства зациклена (адресуется по модулю длины строки), а не дополнена сентителами справа. А также в том, что раскладка по корзинам осуществляется с использованием такой структуры данных языка 1С, как массив массивов. При этом первый элемент каждого вложенного массива хранит предыдущий символ, положенный в соответствующую корзину. Смена символа отмечается добавлением к номеру нового символа одной десятой (чтобы не тратить на это дополнительную память). Далее массив "Ранг" обходится "змеей": во внешней цикле по корзинам и во внутреннем цикле - по содержимому корзин и заново нумеруется. Порядок обхода задается следом змеи, а сдвиг (охват) между обрабатываемым символом и корзиной увеличивается каждый раз вдвое, пока все символы в массиве «Ранг» не кажутся разными. Вот код процедуры построения суффиксного массива:
    Процедура ПолучитьСуффиксныйМассив_(Ранг, След, Охват = 1) Экспорт
    	
    	Старший = След.ВГраница();
    	К = Ранг.Количество();
    	
    	Пока Старший < Ранг.ВГраница() Цикл
    		
    		Змея = Новый Массив(Ранг.Количество(), 1);
    		
    		Для у = 0 По След.ВГраница() Цикл 
    			Для ж = 1 По След[у].ВГраница() Цикл 
    				
    				ё = (Цел(След[у][ж]) - Охват + К) % К; 
    				х = Ранг[(ё + Охват) % К]; 
    				Змея[Ранг[ё]].Добавить(ё + 0.1 * (Змея[Ранг[ё]][0] <> х)); 
    				Змея[Ранг[ё]][0] = х 
    				
    			КонецЦикла 
    		КонецЦикла;
    		
    		Старший = - 1;
    		
    		Для у = 0 По К - 1 Цикл 
    			Для ж = 1 По Змея[у].ВГраница() Цикл 
    				
    				ё = Змея[у][ж]; 
    				Старший = Старший + ё % 1 * 10; 
    				Ранг[ё] = Старший 
    				
    			КонецЦикла 
    		КонецЦикла;
    
    		Охват = Охват * 2;
    		
    		След = Змея
    		
    	КонецЦикла
    	
    КонецПроцедуры
     
  3. Построение LCP-массива. LCP-массив показывает для каждого символа строки (это каждая строка программы в нашем случае) длину наибольшего общего префикса для подстроки, начинающейся в данном месте, и подстроки, следующей за ней в суффиксном массиве. Буквально это и есть длина наибольшего повторяющегося фрагмента, начинающегося в данном месте. Небольшая деталь заключается в несимметричности связи этих одинаковых фрагментов, которая в данном случае оказывается даже выгодной. Поскольку найденная копия окажется в суффиксном массиве позже, то для нее уже не будет копией текущий фрагмент.  Поэтому каждый фрагмент будет встречаться в выдаче алгоритма только один раз. Построение LCP-массива выполняется по алгоритму Касаи. Вот код процедуры построения LCP-массива:
    Процедура ПолучитьДлиныНаибольшихОбщихПрефиксов_(Тень, Ранг, Путь, Рост, Плюс = 0) Экспорт
    	
    	Для ё = 0 По Ранг.ВГраница() Цикл 
    		Путь[Ранг[ё]] = ё 
    	КонецЦикла;
    	
    	Для ё = 0 По Ранг.ВГраница() Цикл 
    		
    		ж = ?(Ранг[ё] < Ранг.ВГраница(), Путь[Ранг[ё] + 1], Ранг.Количество()); 
    		
    		Пока Макс(ё, ж) + Плюс < Тень.Количество() И Тень[ё + Плюс] = Тень[ж + Плюс] Цикл 
    			Плюс = Плюс + 1 
    		КонецЦикла; 
    		
    		Рост[ё] = Плюс; 
    		Плюс = Макс(0, Плюс - 1)
    		
    	КонецЦикла
    	
    КонецПроцедуры
  4. Выделение повторов из LCP-массива. Если представить LCP-массив графиком, то интерес для отображения повторов будут иметь только зубцы этого графика, поскольку другие точки будут соответствовать меньшим по размеру повторам, полностью входящим в бОльший по размеру повтор слева (сверху). Наибольшие повторы отбираются простейшим алгоритмом сравнения текущего значения со значениями слева и справа. При этом в отчете можно задать порог, чтобы не выбирались повторы, число строк в которых меньше этого порога. Вот код выделения повторов:
    Функция ОтборМестПовторов_(Ранг, Путь, Рост) Экспорт
    	
    	Ответ = Повторы.ВыгрузитьКолонки();
    	
    	Для ё = 0 По Рост.ВГраница() Цикл
    		
    		у = Макс(0, ё - 1); ж = Мин(ё + 1, Рост.ВГраница());
    		
    		Если Порог < Рост[ё] И Рост[у] <= Рост[ё] И Рост[ё] >= Рост[ж] Тогда 
    			
    			э = Ответ.Добавить(); 
    			э.Место = ё; 
    			э.Рост = Рост[ё]; 
    			э.Копия = Путь[Ранг[ё] + 1] 
    			
    		КонецЕсли
    		
    	КонецЦикла;
    	
    	Возврат Ответ
    	
    КонецФункции
  5. И, наконец,повторы сортируются в порядке убывания их размеров.

Выводы

  1. Правильно выбранный алгоритм может скомпенсировать недостаточное быстродействие платформы 1С при проведении быстрых массовых вычислений без необходимости применения внешних компонент.
  2. В данной задаче не усматривается необходимости применения более сложных алгоритмов построения суффиксного массива (типа алгоритма Каркайнена – Сандерса и других), так как для разовых применений быстродействия алгоритма достаточно.
  3. Структуры данных платформы 1С позволяют получать компактный и выразительный код при реализации самых хитрых алгоритмов.
  4. Подход,положенный в основу данного отчета, может послужить основой и для более изощренных методов обработки текстов программ. С его помощью можно искать часто встречающиеся полезные шаблоны (оставив в анализируемых текстах только ключевые слова или канонизировав тексты модулей другим способом). Можно автоматически выносить повторяющиеся функции и процедуры в общие модули. Можно искать зависимости при внесении изменений в конфигурации. И так далее.
  5. Приведенные алгоритмы – это совсем небольшая (и довольно простая) часть алгоритмов над строками. Имеющих, кроме показанных в данном отчете, множество других применений. Например, на основе суффиксного массива часто строится индекс, используемый при полнотекстовом поиске. Знание этих алгоритмов позволяет эффективно решать и многие другие практические задачи.
  6. Ну и остался загадкой вопрос: есть ли какие-либо фундаментальные причины у большой избыточности текстов программ типовых конфигураций, замеченной с помощью предлагаемого отчета, или играют роль организационный и человеческий факторы?

Ссылки

  1. Суффиксный массив — удобная замена суффиксного дерева http://habrahabr.ru/post/115346/
  2. MANBER U., MAYERS G.. Suffix arrays: a new methodfor on-line string searches // SIAM Journal on Computing. – 1993. – №22. – P.953–948.
  3. http://en.wikipedia.org/wiki/Suffix_array
  4. Kasai, T.; Lee, G.; Arimura, H.;Arikawa, S.; Park, K. (2001). "Linear-Time Longest-Common-PrefixComputation in Suffix Arrays and Its Applications". Proceedings ofthe 12th Annual Symposium on Combinatorial Pattern Matching. LectureNotes in Computer Science 2089. pp. 181–192. doi:10.1007/3-540-48194-X_17. ISBN 978-3-540-42271-6.


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

Наименование Файл Версия Размер Кол. Скачив.
Отчет "КопиПастаМер"
.erf 12,18Kb
14.08.14
102
.erf 12,18Kb 102 Скачать

См. также

Лучшие комментарии

22. ildarovich 05.08.2014 15:23
(20) logarifm, а вот так понятнее?
int pn[maxlen], cn[maxlen];
for (int h=0; (1<<h)<n; ++h) {
	for (int i=0; i<n; ++i) {
		pn[i] = p[i] - (1<<h);
		if (pn[i] < 0)  pn[i] += n;
	}
	memset (cnt, 0, classes * sizeof(int));
	for (int i=0; i<n; ++i)
		++cnt[c[pn[i]]];
	for (int i=1; i<classes; ++i)
		cnt[i] += cnt[i-1];
	for (int i=n-1; i>=0; --i)
		p[--cnt[c[pn[i]]]] = pn[i];
	cn[p[0]] = 0;
	classes = 1;
	for (int i=1; i<n; ++i) {
		int mid1 = (p[i] + (1<<h)) % n,  mid2 = (p[i-1] + (1<<h)) % n;
		if (c[p[i]] != c[p[i-1]] || c[mid1] != c[mid2])
			++classes;
		cn[p[i]] = classes-1;
	}
	memcpy (c, cn, n * sizeof(int));
...Показать Скрыть


Также рекомендую почитать вот эту статью https://ru.wikipedia.org/wiki/%D0%90%D0%B3%D1%80%D0%B5%D1%81%D1%81%D0%B8%D0%B2%D0­%BD%D0%BE%D1%81%D1%82%D1%8C
Там говорится, что
Причинами агрессивности могут выступать разного рода конфликты, в том числе внутренние, при этом такие психологические процессы как эмпатия, идентификация, децентрация — сдерживают агрессию, так как являются ключом к пониманию других и осознанию их самостоятельной ценности
Ответили: (23) (28)
# Ответить
17. zqzq (файл скачал) 01.08.2014 10:55
(15) ildarovich,
как вариант - ПолучитьДанныеУчетаСтраховыхВзносов2011 не предпологается к развитию (и наоборот зафиксирован, чтобы работал как раньше на старых периодах), а 2014 будет развиваться, и решили скопировать, чтобы не городить внутри процедуры проверки на даты (и не испортить старый период при забытии этой проверки). Я не защищаю копипаст, но не всё так просто, особенно в регл. учете.
Ответили: (48) (49)
# Ответить
14. doxflow (файл скачал) 30.07.2014 19:20
(6) kapustinag,

А также такой показатель "Количество выпущенных обновлений конфигурации в месяц".

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

Только последнее - насчет если нужно подправить - бьет непосредственно по фирме-разработчику.

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

То есть текучка кадров - один из факторов, увеличивающих объем копипаста.

Не согласен. Копипаста - это состояние души конкретного разработчика.
+ 2 [ white_sochi; ZOMI; ]
# Ответить

Комментарии

1. KapasMordorov 30.07.2014 12:55
+ за алгоритм.
Про вывод 6.
Ну в чём загадка например в БП?
Смотрим отчет "РегламентированныйОтчетБухОтчетность", в нем три формы ФормаОтчета2011Кв1, ФормаОтчета2011Кв3, ФормаОтчета2011Кв4.
Не надо быть ясновидцем, чтобы понять, что код в них будет практически одинаковый.
И так в куче отчетов.
Ответили: (2)
# Ответить
2. kapustinag 30.07.2014 13:16
(0), (1) - ну вот именно, о том и речь. Почему разработчик регл.отчета "РегламентированныйОтчетБухОтчетность" не вынес одинаковый код в экспортную функцию модуля отчета, а предпочел оставить его в трех экземплярах в этих формах. Я считаю, что это следствие, во-первых, недостаточного контроля качества кода в фирме-разработчике, и, во-вторых, отсутствия времени/заинтересованности/квалификации (нужное подчеркнуть) у самого разработчика.

Кроме того - пусть владеющие indoor-информацией из фирмы 1С меня поправят - система оплаты труда мотивирует разработчика на быстрейшее изготовление формы ФормаОтчета2011Кв4, а совсем не на наведение порядка во всех трех формах.
Тем более что, по известному закону, предпочитают не трогать сделанные ранее формы. Работает - не трогай! И в этом есть практический смысл. Мегабайты-то очень дешевы.

Теперь о самой статье. Опять очень круто, как и все публикации автора. Снимаю шляпу. Конфигурацию УПП анализировать пытались?
Ответили: (3) (4) (11) (29)
+ 1 [ Rustig; ]
# Ответить
3. doxflow (файл скачал) 30.07.2014 14:02
(2) kapustinag,
Почему разработчик регл.отчета "РегламентированныйОтчетБухОтчетность" не вынес одинаковый код в экспортную функцию модуля отчета, а предпочел оставить его в трех экземплярах в этих формах.

Потому что лень.
Скопировал и подправил - гораздо же быстрее, чем анализировать и выносить общий код.

во-первых, недостаточного контроля качества кода в фирме-разработчике

Скорей в конкретной команде разработчиков.

система оплаты труда мотивирует разработчика на быстрейшее изготовление формы ФормаОтчета2011Кв4

Вряд ли, разработчики типовых сидят на окладе.

Мегабайты-то очень дешевы.

Ну не так-то в итоге и дешевы получаются.
1. Увеличивается время на сравнение/объединение.
2. Огромные модули не способствуют быстродействию работы например в веб-клиенте.
3. И самый смак, это когда надо что-то поправить во всех этих местах. Вот тут-то и выходит изначальная мнимая скорость разработки к компенсации и даже наоборот увеличению времени.
Ответили: (4) (6) (50) (52)
+ 2 [ theshadowco; Rustig; ]
# Ответить
4. amon_ra 30.07.2014 14:40
(2) kapustinag, (3) doxflow, А может у разработчиков в 1С оклад как у индусов от кол-ва строк написанного кода)
Ответили: (5) (6)
# Ответить
5. KSy 30.07.2014 15:04
(4) amon_ra, Похоже, там давно одни индусы сидят))) А разработчики в бизнес ушли, например, Насипов и Ко...
# Ответить
6. kapustinag 30.07.2014 16:35
(4) amon_ra, Такая мысль у меня тоже давно появлялась. А также такой показатель "Количество выпущенных обновлений конфигурации в месяц".

(3) doxflow, "Ну не так-то в итоге и дешевы получаются, и далее по тексту" - так это все уже вне фирмы-разработчика. Не ее головная боль.
Только последнее - насчет если нужно подправить - бьет непосредственно по фирме-разработчику. Так это головная боль фирмы, потому что сам разработчик, может быть, уже уволился давно. То есть текучка кадров - один из факторов, увеличивающих объем копипаста.
Ответили: (14)
+ 1 [ Rustig; ]
# Ответить
7. brr (файл скачал) 30.07.2014 17:24
Зачем отчет учитывает пустые строки?
Ответили: (8)
# Ответить
8. ildarovich 30.07.2014 17:30
(7) brr, для того, чтобы правильно нумеровать строки и для того, чтобы различать фрагменты, если в них различное количество пустых строк. Впрочем, это можно легко изменить.
# Ответить
9. brr (файл скачал) 30.07.2014 17:36
Было бы неплохо выводить все имена модулей в которых встречается выбранный фрагмент.
Ответили: (13)
# Ответить
10. brr (файл скачал) 30.07.2014 17:44
Если я правильно интерпретирую заголовок колонки "Копия" как количество копий, то проверка поиском не прошла.
Ответили: (12)
# Ответить
11. ildarovich 30.07.2014 18:03
(2) kapustinag, вот скриншот для УПП:

Прикрепленные файлы:

СкринШотУПП.png
# Ответить
12. ildarovich 30.07.2014 18:05
(10) brr, нет, "копия" - здесь имелось ввиду место начала копии выделенного фрагмента
# Ответить
13. ildarovich 30.07.2014 18:07
(9) brr, думал над этим, но тогда таблица "Повторы" окажется слишком громоздкой - много раз придется повторять длинное имя одного и того же модуля. Вы можете упорядочить строки повторов по колонке "место" и сможете просматривать повторы не перепрыгивая по модулям.
Ответили: (19)
# Ответить
14. doxflow (файл скачал) 30.07.2014 19:20
(6) kapustinag,

А также такой показатель "Количество выпущенных обновлений конфигурации в месяц".

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

Только последнее - насчет если нужно подправить - бьет непосредственно по фирме-разработчику.

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

То есть текучка кадров - один из факторов, увеличивающих объем копипаста.

Не согласен. Копипаста - это состояние души конкретного разработчика.
+ 2 [ white_sochi; ZOMI; ]
# Ответить
15. ildarovich 31.07.2014 14:11
А вот пример из ЗУП 2.5.82.2. Модуль объекта документа "ОтражениеЗарплатыВРеглУчете". Внутри одного и того же модуля(!) скопировано 1098 строк - все содержимое функции ПолучитьДанныеУчетаСтраховыхВзносов2011 без каких либо изменений перенесено в функцию ПолучитьДанныеУчетаСтраховыхВзносов2014.
Ответили: (16) (17)
# Ответить
16. JohnyDeath 01.08.2014 00:58
(15) ildarovich,
Странно, почему пропустили 2012-й и 2013-й года. Разработчик в декрете была? )
− 1 [ KapasMordorov; ]
# Ответить
17. zqzq (файл скачал) 01.08.2014 10:55
(15) ildarovich,
как вариант - ПолучитьДанныеУчетаСтраховыхВзносов2011 не предпологается к развитию (и наоборот зафиксирован, чтобы работал как раньше на старых периодах), а 2014 будет развиваться, и решили скопировать, чтобы не городить внутри процедуры проверки на даты (и не испортить старый период при забытии этой проверки). Я не защищаю копипаст, но не всё так просто, особенно в регл. учете.
Ответили: (48) (49)
# Ответить
18. AlX0id 01.08.2014 15:10
А при копипастомеринге учитывается то, что алгоритм один, а имена переменных разные? ) Это было бы круто )
Ответили: (42) (44)
# Ответить
19. brr (файл скачал) 01.08.2014 15:28
(13) ildarovich, место, я так понимаю, номер строки?
Ответили: (21)
# Ответить
20. logarifm 05.08.2014 14:35
За такой код убить можно...
Ответили: (22)
+ 1 [ xsazar; ]
# Ответить
21. ildarovich 05.08.2014 15:06
(19) brr, да, номер строки
# Ответить
22. ildarovich 05.08.2014 15:23
(20) logarifm, а вот так понятнее?
int pn[maxlen], cn[maxlen];
for (int h=0; (1<<h)<n; ++h) {
	for (int i=0; i<n; ++i) {
		pn[i] = p[i] - (1<<h);
		if (pn[i] < 0)  pn[i] += n;
	}
	memset (cnt, 0, classes * sizeof(int));
	for (int i=0; i<n; ++i)
		++cnt[c[pn[i]]];
	for (int i=1; i<classes; ++i)
		cnt[i] += cnt[i-1];
	for (int i=n-1; i>=0; --i)
		p[--cnt[c[pn[i]]]] = pn[i];
	cn[p[0]] = 0;
	classes = 1;
	for (int i=1; i<n; ++i) {
		int mid1 = (p[i] + (1<<h)) % n,  mid2 = (p[i-1] + (1<<h)) % n;
		if (c[p[i]] != c[p[i-1]] || c[mid1] != c[mid2])
			++classes;
		cn[p[i]] = classes-1;
	}
	memcpy (c, cn, n * sizeof(int));
...Показать Скрыть


Также рекомендую почитать вот эту статью https://ru.wikipedia.org/wiki/%D0%90%D0%B3%D1%80%D0%B5%D1%81%D1%81%D0%B8%D0%B2%D0­%BD%D0%BE%D1%81%D1%82%D1%8C
Там говорится, что
Причинами агрессивности могут выступать разного рода конфликты, в том числе внутренние, при этом такие психологические процессы как эмпатия, идентификация, децентрация — сдерживают агрессию, так как являются ключом к пониманию других и осознанию их самостоятельной ценности
Ответили: (23) (28)
# Ответить
23. premier (файл скачал) 06.08.2014 08:52
(22) ildarovich, я вот тоже считаю, что выкладывать такой код - неуважение к коллегам. Если уж возникло решение транслировать код функции с С++ на встроенный язык 1С, вполне можно сделать это таким образом, чтобы код был хотя бы читабельным. У языка С++ есть своя специфика, которую не имеет смысла переносить в код на 1С. К тому же на дисках ИТС есть руководство по оформлению кода конфигураций 1С, советую ознакомиться.
А в общем и целом - публикация довольно познавательная. Однозначно - "плюс". Я сам не часто использую технологию copy-past, но в некоторых случаях, просто приходится это делать. В целях, например, сокращения сроков разработки (особенно, если эти сроки поджимают). В любом случае, полезно время от времени производить рефакторинг своих разработок и механизм, предложенный автором, вполне подходит для выявления проблемных фрагментов кода.
Ответили: (24)
# Ответить
24. ildarovich 06.08.2014 10:58
(23) premier, в данном конкретном случае у меня не было цели сделать код предельно понятным. Акцент был сделан на быстродействии (кстати, уже есть более быстрая версия). Код приведен для того, чтобы был виден его весьма небольшой объем и используемые структуры данных. Также хочу сказать, что код написан с нуля "по мотивам другого алгоритма" на структурах данных 1С и никак не может является трансляцией кода приведенной функции С++ на 1С. А функция (очень просто читаемая, кстати) приведена для того, чтобы было понятно, в каком коде приходится разбираться, программируя не только на 1С и без всяких мыслей, что его авторы тебя не уважают.
Ответили: (27)
# Ответить
25. Makushimo (файл скачал) 08.08.2014 03:36
Можно ли с помощью этого решить такую задачу:
Есть произвольный текст: например, рассказ или статья на одну страницу. Нужно получить из этого текста основные ключевые фразы или слова, которые проявляют смысловой скелет написанного текста?
Ответили: (26) (51)
+ 1 [ Rustig; ]
# Ответить
26. ildarovich 08.08.2014 10:14
(25) Makushimo, думаю, что такую задачу с помощью данного метода решить нельзя.
# Ответить
27. brr (файл скачал) 08.08.2014 12:50
(24) ildarovich, с нетерпением жду более быструю версию :)
Ответили: (37)
# Ответить
28. awk (файл скачал) 08.08.2014 22:38
(22) ildarovich, В аглицком - понятно. Ибо аглицкие сокращения известны. А русские - нет.
Ответили: (30)
# Ответить
29. serno 11.08.2014 12:51
(2) kapustinag,
Тема дискутабельная, но копи-паст это вовсе не означает что то однозначно плохое, это решение имеет место быть для случаев:
1. снизить себестоимость разработки (например делаем свою независимую подсистему на базе готового решения, находящегося на поддержке)
2. оставить стабильно работающую версию решения
Какой смысл делать рефакторинг регламентного отчета не актуального более года? Он уже имеет законченный вид и не будет дорабатываться, а рефакторинг ради рефакторинга это всегда риск привнесения ошибок.
+ 2 [ Rustig; Sol; ]
# Ответить
30. ildarovich 11.08.2014 13:39
(28) awk, я уже согласился с тем, что в данном случае не потратил достаточного количества усилий на то, чтобы сделать код понятнее. Я этой цели пока не ставил - тем более, что еще продолжаю переписывать этот кусок, выжимая проценты.
Но вот насчет сокращений - я их не использовал. Индексы я предпочитаю обозначать буквами: ё, ж, у и так далее. И использую, в основном, короткие, но целые русские слова: "Змея", "След" (змеи) - для обозначения пути обхода массива массивов, хранящего порядок обхода массива "Ранг". "Тень" - это копия массива "Ранг". Рост - размер фрагмента. "Плюс" - величина приращения длины фрагмента, "Старший" - наибольший ранг и так далее. В русском языке много коротких и выразительных слов и я это стараюсь использовать. Иногда получается даже забавно. Вот, например, кусок кода из статьи "Наш ответ американским лекторам"
Трус = Новый Соответствие;

Трус["Крик"] = "Ой, мама!";

Балбес = Трус;

Балбес["Крик"] = "Ура!";

Сообщить(Трус["Крик"])
Ответили: (31)
# Ответить
31. awk (файл скачал) 11.08.2014 14:13
(30) ildarovich, Не важно, потратил или нет. Просто код напоминает творение первокурсника (чем запутаннее - тем круче).

1. Буква Ё не рекомендуется к использованию в 1С
2. Для итераторов и счетчиков приняты (в 1С) обозначения: "ит", "Сч".

Террариум - это прелестно, но за такое парой штрафуют.
Ответили: (32) (38)
# Ответить
32. ildarovich 11.08.2014 14:39
(31) awk, про рекомендацию не использовать ё ни разу не слышал. С чего бы это? ё - очень нарядная буква, напоминает по звучанию английские итераторы.
ит - дурацкое и уродливое сокращение от английского слова.
Сч - мне не нравится своей обрезанностью.
"Принято в 1С" - где принято? Не видел такого документа (про Сч и ит). Если так пишут многие, то это не значит, что так лучше. Многие и книжек по "computer science" не читали: так и мы не будем читать?
"Чем запутаннее, тем круче" - я к этому не стремлюсь, честно. Думаю, так может показаться по трем причинам:
1) Алгоритмы, которыми я занимаюсь, не просты. Может быть, их вообще невозможно записать так, чтобы было всем понятно.
2) Я злоупотребляю краткостью. Из двух вариантов записи я часто выбираю более короткий.
3) Я стараюсь писать "красивый" для себя код, а понятие о красоте кода у меня свое, сформировавшееся при программировании не только на 1С.
Ну а штрафов я не боюсь.
Ответили: (33) (35)
+ 1 [ Yashazz; ]
# Ответить
33. awk (файл скачал) 11.08.2014 15:12
(32) ildarovich,
1. От русского "итератор". Правда имеющего англоязычные корни.
2. Читайте ИТС - там есть рекомендации по оформлению кода.
3. Не надо писать что бы было понятно всем. Надо писать что бы было понятно себе через три года.
4. Краткость - хорошо. Помнится написал процедуру _(__,___) - которая выполняла произвольный код в контексте формы, для целей тестирования.
5. Самый красивый код - это функция копирования строк С. strcpy(char* src,char* dst) { while (*src=*dst); )
Ответили: (34) (43)
# Ответить
34. ildarovich 11.08.2014 16:37
(33) awk, да читал я ИТС - там только про комментарии, отступы, на одной строке, а про имена переменных ничего нет.
Ответили: (39)
# Ответить
35. Makushimo (файл скачал) 12.08.2014 05:04
(32) ildarovich,
В этом есть какой-то смысл. В попытках понять реализацию метода (и сам метод) проходишь тот (или свой) путь автора в размышлениях. Когда понял - твое.

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

А как иногда хочется, чтобы сложные знания рраз и в башку сразу. сидишь как Нео глазками хлоп-хлоп и радуешься - осталось время на пивасик -)))

Если ildarovich не против, раскурю как нибудь эту и другие его статьи и переведу на понятный чайникам (как я) язык.
# Ответить
36. vis_tmp (файл скачал) 13.08.2014 05:09
Столкнулся с ошибкой при использовании обработки - см. картинку.

Причина в том, что имя файла оказалось усечённым.
Файл назывался
"Обработка.ПомощникНастройкиОбменаДаннымиСБухгалтерияПредприятияКОРП.Макет.ПравилаОбмена_БПКОРП_УТ.Макет.txt"
А в переменной Модуль1.Файл было записано
"Обработка.ПомощникНастройкиОбменаДаннымиСБухгалтерияПредприятияКОРП.Макет.ПравилаОбмена_БПКОРП_УТ.Ма".

Подумал, что простое небольшое увеличение размерности реквизита ИмяМодуля в таб. часть Модули до 110 должно решить проблему, но получил другую ошибку...
Ответили: (37) (45)

Прикрепленные файлы:

КопиПастеМер - ошибка 2.PNG
# Ответить
37. ildarovich 13.08.2014 10:29
(36) vis_tmp, я заменил файл отчета. В новой версии длина имени модуля увеличена до 256 знаков. Та ошибка, которая появилась у вас после правки, у меня не воспроизводится. Собственно код, на котором происходит ошибка выполняет безцикловое копирование массива. И, вроде бы, в этот момент неправильно выделяется память (судя по скриншоту). Это проблема платформы, а не отчета.

(27) brr, кроме того, увеличена скорость работы (примерно на 30-40%) за счет оптимизации операций в основных циклах.

Также добавлен вывод некоторой статистики: общее количество строк, число различных строк, средняя длина повтора. Статистика отображается в заголовке формы после выполнения анализа.
# Ответить
38. doxflow (файл скачал) 13.08.2014 10:34
(31)awk,
2. Для итераторов и счетчиков приняты (в 1С) обозначения: "ит", "Сч".

Это принято у Вас в компании видимо
# Ответить
39. sergei2k (файл скачал) 13.08.2014 11:14
(34) ildarovich,
Правила образования имен переменных
http://its.1c.ru/db/v8std#content:-2145783193:1
Ответили: (40)
+ 1 [ Rustig; ]
# Ответить
40. ildarovich 13.08.2014 11:59
(39) sergei2k, спасибо за ссылку. Не находил ее поиском. Буду иметь ввиду.
# Ответить
41. ildarovich 13.08.2014 14:50
Эх! - 13-е число. Перезалил новую версию отчета не на старое, а на новое место. В результате потерялось общее количество скачиваний. Их было 46.
# Ответить
42. AlexanderKai 13.08.2014 15:58
(18) AlX0id,
Я думаю, такое возможно. Будет время - попробую сделать.
Ответили: (44)
# Ответить
43. AlexanderKai 13.08.2014 16:10
(33) awk,
Самый красивый код - это функция копирования строк С. strcpy(char* src,char* dst) { while (*src=*dst); )

Это такой тонкий сарказм, да? :)
# Ответить
44. ildarovich 13.08.2014 19:50
(42) AlexanderKai, (18) AlX0id, в описании я уже говорил, что для такого нужно использовать тот или иной способ "канонизации" текста программы. Можно, например, перед обработкой текста вообще убрать из него все, кроме ключевых слов.
# Ответить
45. ildarovich 14.08.2014 14:31
(36) vis_tmp, отмеченная Вами ошибка несколько раз воспроизводилась у моих коллег, поэтому я переписал присваивание - сделал циклом. Чуть медленнее, зато надежнее. Выложил исправленный вариант.
Кроме того, обратил внимание, что при анализе текстов в УПП, где 5 миллионов строк, обработке иногда не хватает памяти (хотя внутри обработки память регулярно освобождается). Возможно, нужно вообще избавиться от использования многократного выделения памяти под порядок обхода. Для этого нужно изменить алгоритм. Это в будущем. Сейчас помогает сворачивание - разворачивание окна обработки в процессе ее работы.
Ответили: (46)
# Ответить
46. vis_tmp (файл скачал) 15.08.2014 07:47
(45) ildarovich, Спасибо, теперь заработало!
# Ответить
47. CheBurator 16.08.2014 14:27
если бы еще показывад "совпадающие" куски до уровня похожести - то есть где-то есть очень похожие блоки текста, различающиеся незначительно...
# Ответить
48. Rustig (файл скачал) 18.08.2014 14:08
(17) странно получается: для своих целей облегчения программирования и ведения дальнейших разработок, вы готовы оправдать (оправдаться) словами
не всё так просто, особенно в регл. учете

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

лично я считаю, что ответ на последний вопрос зависит от разработчика, то есть нет здесь никакой фундаментальности
+ 1 [ dassin; ]
# Ответить
49. Rustig (файл скачал) 18.08.2014 14:09
(17) да уж, согласен, не все так просто, особенно в регл.учете: http://infostart.ru/public/195627/
# Ответить
50. Rustig (файл скачал) 18.08.2014 14:27
(3)
Потому что лень.
Скопировал и подправил - гораздо же быстрее, чем анализировать и выносить общий код.

вообще-то вся Россия платит за программы 1С, а программа такого качества вызывает много вопросов...
+ 1 [ dddxddd; ]
# Ответить
51. Rustig (файл скачал) 18.08.2014 14:47
(25) я тоже думал о такой задаче: чтобы из статьи вытащить наибольшее кол-во повторяющихся фраз, на основе этой информации скорректировать статью таким образом, чтобы как можно больше попадалось именно "ключевых слов". Затем готовую статью можно выкладывать в интернет и ждать яндекс-индексацию
# Ответить
52. qwinter 25.08.2014 21:26
(3) doxflow,
Потому что лень.
Скопировал и подправил - гораздо же быстрее, чем анализировать и выносить общий код.
А через месяц, еще раз этот кусок разбивать и выносить еще в отдельные процедуры с условиями, через месяц еще раз и т.д. Через год вы получите общий модуль в котором уже никто не разберется.

Рефакторинг должен быть ради улучшения читаемости и прозрачности кода, а не ради рефакторинга!!
Ответили: (53)
# Ответить
53. doxflow (файл скачал) 29.09.2014 12:27
(52) qwinter,
А через месяц, еще раз этот кусок разбивать и выносить еще в отдельные процедуры с условиями, через месяц еще раз и т.д. Через год вы получите общий модуль в котором уже никто не разберется.

Какое-то у вас странное понимание рефакторинга. То что вы описываете больше похоже на подпорку костылями.
И вообще в хорошем продукте, который постоянно развивается, рефакторинг это непрерывный процесс.
+ 2 [ dddxddd; Evil Beaver; ]
# Ответить
54. ildarovich 07.11.2014 21:48
За это время появилось два соображения в пользу копипаста:
1) Снижение зависимостей. Таким образом, например, в модуль внешней печатной формы переносятся функции из одной конфигурации, чтобы она могла работать в других конфигурациях. С другой стороны, это означает, что все функции для построения универсальных печатных форм, предназначенных для разных конфигураций, должны быть в БСП.
2) Подстановка. Это когда код из тела функции подставляется в тело ее вызова. Она обычно применяется для ускорения выполнения программ. Но в 1С ее применяют для улучшения понимания программы - когда для понимания поведения программы не нужно углубляться в работу модулей - так как весь код оказывается на одном длинном листе. С другой стороны, невозможность прочесть и понять программу на верхнем уровне свидетельствует о неправильном разделении функционала между вызывающей и вызываемыми программами. Также, наверное, можно создать редактор кода, умеющий на этапе прочтения кода выполнять подстановку. Также интересен набор кода по шаблонам. Почему эта техника не бесспорна? - Да потому, что коллекция проверенных и отточенных шаблонов просто обязана быть превращена в функции и добавлена в БСП.
Ответили: (60) (61)
# Ответить
55. ildarovich 13.06.2015 11:22
Нашел еще одну статью http://habrahabr.ru/post/260149/ , где оправдывается копипаст в коде Eclipse Platform (она называется суперкачественно задизайненной платформой)
Ну так вот, гляжу я внутрь eclipse и не понимаю, что за ерунда. С одной стороны все выглядет красиво, качественно, я бы сказал восхитительно, с другой стороны — вот тут же можно было переиспользовать, и тут, и тут, вот тут вообще чуваки сознательно копи-пастят. Что-то думаю не то, они точно могли переиспользовать код, но не делают этого. Для ответа на вопрос мне надо было выйти за рамки своих детских программистских потребностей и посмотреть на мир глазами взрослых мужчин.

Любой факт (пере)использования чего либо, явно или неявно рожает зависимость на эту штуку. И там где для меня благо (эффективное переиспользование) и, как следствие, увеличение продуктивности, то для людей создающих платформу, на которой предполагается одновременный запуск сотен плагинов, различных версий и от десятка не знающих друг о друге вендоров любая лишняя зависимость — зло.
Ответили: (61)
# Ответить
56. kolya_tlt (файл скачал) 06.07.2015 08:41
Добрый день. Подскажите, а как читать результаты работы обработки?
Ответили: (57)
# Ответить
57. ildarovich 06.07.2015 12:53
(56) kolya_tlt,
На форме обработки есть поля:
1) Путь выгрузки. Это папка, куда помещены файлы, повторы в текстах которых нужно найти;
2) Порог. Это минимальное значение длины повторяющихся фрагментов (в строках), которые замечаются обработкой. Когда 0 - все повторы показываются;
3) По алфавиту - несколько замедляет поиск. Параметр нужен был для тестирования, чтобы суффиксный массив строился также, как и другими алгоритмами, чтобы можно было сравнить результаты.
4) Табличная часть с колонками:
4.1) Рост - это длина найденного фрагмента;
4.2) Место - это сдвиг (в строках) от начала всех файлов. Нумерация строк сквозная;
4.3) Копия - сдвиг копии фрагмента (в строках) от общего начала всех файлов.
При выборе строки в табличной части производится переход от сквозной нумерации строк к нумерации внутри отдельных файлов. При этом отображается:
5) Имя файла, содержащего образец (его рост показан в выделенной строке);
6) Сдвиг образца относительно начала указанного файла;
5) Имя файла, содержащего копию (её рост соответствует росту оригинала);
6) Сдвиг копии относительно начала файла, содержащего копию. Файл, содержащий оригинал и копию может быть одним и тем же.
# Ответить
58. kolya_tlt (файл скачал) 07.07.2015 09:31
спасибо, а что делать с информацией в колонках
4.2) Место - это сдвиг (в строках) от начала всех файлов. Нумерация строк сквозная;
4.3) Копия - сдвиг копии фрагмента (в строках) от общего начала всех файлов.
?
ведь требуется увидеть как часто и где встречается тот или иной фрагмент кода, а с местом и копией что делать?
Ответили: (59)
# Ответить
59. ildarovich 07.07.2015 13:51
(58) kolya_tlt, вопрос
как часто и где встречается тот или иной фрагмент кода
не требует таких сложных алгоритмов. Тут работает встроенный метод платформы "Найти" и "СтрЧислоВхождений". Скорее всего, при реализации "Найти" используется алгоритм Боурера-Мура, который предельно быстр.

Здесь решалась проблема найти следы копипаста, то есть обнаружить те фрагменты, которые, вероятнее всего, были целиком скопированы из другого места программы. Буквально это и показано: указано место первого (исходного) фрагмента и указано место, где есть его копия. При этом "первичность" фрагмента (у кого кто списал) точно не определяется. Также если фрагмент 1 был скопирован десять раз и были получены фрагменты 2, 3, 4, ... ,11 нет гарантии того, что будут показаны пары 1-2, 1-3, 1-11. Вполне может быть результат 1-2, 2-3, 4-2... . Это зависит от строк "окружения" фрагментов и порядка их записи в цепочке файлов текстов модулей.

Это не означает, что на основе полученных данных нельзя ответить на другие вопросы анализа текстов программных модулей. Но для этого их нужно четко и однозначно сформулировать.
+ 1 [ kolya_tlt; ]
# Ответить
60. cool.vlad4 07.07.2015 14:10
(54) ildarovich, первый пункт - он не совсем 'за' . основная задача программиста упраление сложностью системы при решении ряда задач. при копипасте у тебя действительно может быть псевдоснижение зависимостей от конкретной части системы , но только сложность системы увеличивается. при обновлении тебе придется обновлять все места копипасты. при ошибке, тебе придется исправлять все места ошибки. сложность увеличилась.
# Ответить
61. cool.vlad4 07.07.2015 14:21
(55) ildarovich, вот как раз в приведенной тобой цитате опровержение первого пункта из (54) . (помню еще слушал какой-то выпуск Радио-Т , там была такая точка зрения, что реюза кода не существует, это миф. в каждой задачи свои НУ, свои требования и т.п., с другой стороны при копипасте, потом все равно код модифицируется. от себя добавлю . что вопрос я бы ставил по другому. - вопрос не в копипасте или нет, вопрос в наличии дизайна и архитектуре и их качестве)
# Ответить
62. ildarovich 21.08.2015 11:31
Вот старая ссылка о работе на ту же тему:
Поиск дублирующегося кода в Visual Studio
# Ответить
63. olbu (файл скачал) 03.09.2015 17:25
может я не правильно им пользуюсь:
1) сохраняю модуль в файл
2)сохраняю другой модуль в файл
3)сохраняю эти файлы в одну папку
4)выбираю в обработке эту папку
Сформировать.
вываливается ошибка:
{ВнешнийОтчет.КопиПастоМер.МодульОбъекта(81)}: Индекс находится за границами массива
Ящик = Змея[Ранг[ё]];
Ответили: (64)
# Ответить
64. ildarovich 03.09.2015 20:39
(63) olbu,
Перед использованием отчета тексты программных модулей анализируемой конфигурации необходимо выгрузить в некоторую папку. Это можно сделать через конфигуратор с использованием пункта меню "Конфигурация\Выгрузить файлы конфигурации".

В папке для анализа должны быть ТЕКСТОВЫЕ ФАЙЛЫ, содержащие ТЕКСТЫ программных модулей конфигурации.
Если в папке, которую вы задавали в параметрах обработки, действительно тексты, то такой ошибки быть не должно.
Ответили: (65)
# Ответить
65. olbu (файл скачал) 04.09.2015 08:50
(64) ildarovich, да так и сделал: выделил процедуру скопировал текст ее в буфер, создал текстовой файл в блокноте, вставил текст процедуры - получил текстовой файл... положил его в папку...
может я что - то упустил?
Ответили: (66)
# Ответить
66. ildarovich 04.09.2015 13:52
(65) olbu, если не трудно, сделайте архив с упомянутой папкой с файлами и пришлите мне на почту. Адрес сообщу в личном сообщении.
Ответили: (67)
# Ответить
67. lustin (файл скачал) 13.02.2016 23:46
(66) ошибки добиться достаточно легко.

1. создаем чистую конфигурацию с одним объектом Документ1
1.2 в документе создаем модуль

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)	
	Сообщить("Тесть");
КонецПроцедуры

Процедура ОбработкаПроверкиЗаполнения2(Отказ, ПроверяемыеРеквизиты)
	Сообщить("Тесть");	
КонецПроцедуры

Процедура ОбработкаПроверкиЗаполнения4(Отказ, ПроверяемыеРеквизиты)
	Сообщить("Тесть");
КонецПроцедуры
...Показать Скрыть


2. делаем магию - нажимаем F9 на Документе1 так чтобы получилось 13 документов (не знаю почему я нажал 12 раз)

3. выгружаем конфигурацию в файлы во временный каталог

4. если используем иерархический режим 8.3.7 - то

* необходимо исправить в копипастамере строку c поиском файлов

Файлы = НайтиФайлы(ПутьВыгрузки, "*.bsl", Истина);


и для удобства меняем Состояние на Сообщить

Сообщить("Построение суффиксного массива: " + Охват + " / " + К);


имеем следующий вывод


Построение суффиксного массива: 1 / 338
Построение суффиксного массива: 2 / 338
Построение суффиксного массива: 4 / 338
Построение суффиксного массива: 8 / 338
Построение суффиксного массива: 16 / 338
Построение суффиксного массива: 32 / 338
Построение суффиксного массива: 64 / 338
Построение суффиксного массива: 128 / 338
Построение суффиксного массива: 256 / 338
Построение суффиксного массива: 512 / 338


и Exception


Индекс находится за границами массива


Собственно проблема в коде в районе

ё = Цел(Шаг[ж] - Охват + К) % К; 				


Эта волшебная Ё как мы видим выше становится отрицательной
Ответили: (68)
# Ответить
68. ildarovich 14.02.2016 18:54
(67) lustin, буду разбираться, сейчас у меня в коде вот такой комментарий
// вообще говоря, против зацикливания строки нужно бы добавить сентител - последний одиночный символ, 
	// равный Нумератор.Количество(), но в данной реализации пока есть еще "ПоАлфавиту", поэтому оставляем так - "на авось"
	// зациклится тогда, когда будут только одинаковые файлы из всех разных строк
Буквально это означает, что "строка" вида 123123123123 зацикливает алгоритм, поскольку при циклическом сдвиге превращается в саму себя. "Строка" тут состоит из "хешей" строк анализируемых файлов.
Значит, пока одинаковые файлы из разных строк алгоритм обрабатывать не может. - Вскорости исправлю.
# Ответить
69. boogie (файл скачал) 13.04.2016 09:27
Подскажите, исправлена ли эта ошибка:
Ответили: (70)

Прикрепленные файлы:

img1C6A.png
# Ответить
70. ildarovich 13.04.2016 14:25
(69) boogie, судя по скриншоту, вы пытаетесь запустить обработку в режиме управляемых форм, а она для обычных. Попытайтесь открыть ее в УТ10.3, ЗУП 2.5, УПП1.3, БП2 и т.п. Собственно, сама конфигурация значения не имеет, главное, что не УФ.
# Ответить
Внимание! За постинг в данном форуме $m не начисляются.
Внимание! Для написания сообщения необходимо авторизоваться
Текст сообщения*
Прикрепить файл