Форум программистов, компьютерный форум, киберфорум
Теория программирования
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
542 / 163 / 79
Регистрация: 23.09.2013
Сообщений: 316

Применение рефакторинга для увеличения тестируемости кода

13.02.2016, 09:54. Показов 1347. Ответов 7

Студворк — интернет-сервис помощи студентам
Мои цели:
1) Высокая читаемость кода
2) Легкость тестирования кода (юнит тесты, интеграционные тесты, приемочные тесты)
3) Высокая модульность кода
4) Возможность повторного использования кода

Конкретная задача (может быть использована для людей, которые предпочитают показывать на примере):
Кликните здесь для просмотра всего текста
Необходимо скопировать набор файлов из одной папки в другую.
На этапе компиляции известны: Имена всех файлов, путь до папки из которой копируют, путь до папки куда копируют.
Дополнительные требования: графический интерфейс должен отображать имя копируемого в данный момент файла.
Объем оперативной памяти меньше чем размер копируемых файлов, копировать файлы нужно небольшими порциями, размер порции известен на этапе компиляции.
Прогресс копирования конкретного файла должен отображаться в виде прогресс бара на графическом интерфейсе.
Реализация общения с файловой системой, а так же графический интерфейс реализуются с использованием Qt-4.8


Далее предположим, что данная задача или подобная ей реализована в виде одного god-like класса, этот класс содержит 500-2000 строк кода. В нем заданы все константы, осуществлена наиболее примитивная декомпозиция на методы. Класс не содержит кода по отображению GUI - эта логика вынесена в другой модуль с которым идет общение через интерфейс (или через сигналы Qt).
Код является полной противоположностью поставленных целей. Необходимо покрыть его тестами на 70-100 процентов.

Вопросы:
Какой из типов швов следует применять по умолчанию, при решении о увеличении модульности/тестируемости некоторого god-like класса? (Швы по Майклу Физерсу)
Каким образом Вы производили бы декомпозицию задачи и до какой степени разделения (от чего зависела бы эта степень) ?
В каком случае Вы применяли бы рефакторинг извлечение класса и в каком - дополнительно, извлечение интерфейса?
По каким признакам Вы определили бы, что в дополнительном выделении классов отсутствует необходимость?
Как при этом Вы предпочли бы управлять памятью и на каком уровне инвертировать зависимости? (DIP из SOLID)

В чем моя проблема:
Кликните здесь для просмотра всего текста
Ловлю себя на мысли, что не знаю где следует остановиться. В попытке максимального покрытия кода тестами сталкиваюсь с тем, что проще всего тестировать, если в каждый из взаимодействующих классов через конструкторы внедряются все зависимости, с которыми ему предстоит работать. Но это порождает достаточно большой набор базовых интерфейсов, например по представленной задаче абстракции которые я смог выделить: Файловая система, файл, объект ввода-вывода, абстракция копирования по частям, абстракция копирования из файла в файл, абстракция копирования множества зарегистрированных путей в одну заданную папку, интерфейс вывода прогресса, интерфейс вывода имени копируемого файла и т.д. Я такой сепарации практически нигде не видел, поэтому и задаюсь вопросом как другие программисты применяют рефакторинги и к чему они приходят в итоге.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
13.02.2016, 09:54
Ответы с готовыми решениями:

Загрузка элементов класса откуда-то для увеличения читабельности кода
Доброго времени суток! Есть у мне клас: public class Symbol { public Bitmap picture; // картинка public...

Возможно ли применение сетей Петри для улучшения качества кода и реверс инжинеринга?
Т.к. в ветке "С++ для экспертов" у меня нет прав на создание сообщения и оно не совсем связано с программированием, то задаю вопрос тут. ...

Зашифровать текст путем увеличения кода символа на 1
помогите написать программу , которая сначала будет кодировать введено с клавиатуры текстовое сообщение путем увеличения кода символа на 1...

7
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
13.02.2016, 13:15
Цитата Сообщение от Melg Посмотреть сообщение
Код является полной противоположностью поставленных целей.
Так, предположим код есть и работает. Откуда возникла необходимость в рефакторинге? Какие бизнес-проблемы он поможет решить? Всякие ни о чем типа "потому что я так могу и в книжках пишут, что так правильно" не рассматриваются как причины.

Цитата Сообщение от Melg Посмотреть сообщение
Необходимо покрыть его тестами на 70-100 процентов.
Откуда такие числа?

Цитата Сообщение от Melg Посмотреть сообщение
Какой из типов швов следует применять по умолчанию, при решении о увеличении модульности/тестируемости некоторого god-like класса? (Швы по Майклу Физерсу)
Каким образом Вы производили бы декомпозицию задачи и до какой степени разделения (от чего зависела бы эта степень) ?
В каком случае Вы применяли бы рефакторинг извлечение класса и в каком - дополнительно, извлечение интерфейса?
По каким признакам Вы определили бы, что в дополнительном выделении классов отсутствует необходимость?
Как при этом Вы предпочли бы управлять памятью и на каком уровне инвертировать зависимости? (DIP из SOLID)
Я бы предпочел не увлекаться теорией, а делать все исходя из сроков, практичности, опыта, и здравого смысла. Вопросы слишком общие - на них просто невозможно ответить однозначно в условиях нашего реального мира. Факторов, учитываемых при принятии решений, слишком много, - я даже не буду пытаться их перечислять, - а их приоритеты меняются от ситуации к ситуации. Если бы все было однозначно - самыми крутыми разработчиками были бы те, кто больше всех читает. Но это не так.

Цитата Сообщение от Melg Посмотреть сообщение
как другие программисты применяют рефакторинги и к чему они приходят в итоге
У каждого изменения кода есть
1) кол-во времени, потраченное на изменение
2) кол-во профита, от это изменения полученного.
Из всех возможных выбираем изменение с максимальным соотношением профит/время, производим его. Повторяем по желанию до тех пор, пока не останутся только те изменения, профит от которых не окупает потраченное время.
0
542 / 163 / 79
Регистрация: 23.09.2013
Сообщений: 316
13.02.2016, 14:33  [ТС]
ct0r, в данном конкретном случае причина начала рефакторинга никак не связана ни с самим легаси кодом, ни с тем, какие бизнес проблемы он решает в данный момент и сможет решать после проведения рефакторинга. Целью данной активности в конечном счете является как раз приобретение необходимых навыков/подходов при решении подобных задач в реальных условиях. В общем случае ставится задача получения опыта в проведении рефакторингов без (или с минимальным количеством) ошибок в условиях большого объема кода не покрытого тестами, приобретения навыков тестирования для предотвращения регрессии кода при внесении изменений (связанных с изменениями в бизнес-правилах). А так же освоения методологии разработки через тестирования.
100 процентов покрытия - выбраны как идеальный случай, к которому я стремлюсь, 70 процентов как случай достаточного покрытия, предполагающий тестирование бизнес логики, и критических сегментов кода без необходимости тестировать не используемые при решаемой задаче возможности, либо код связывания элементов логики в единое целое (которое может быть перекрыто статическим анализом, корректной компиляцией, приемочным тестированием и т.д.)
Если бы все было однозначно - самыми крутыми разработчиками были бы те, кто больше всех читает. Но это не так.
У Вас завалялась статистика на этот счет? выработанная система, описывающая положение дел? может быть, хотя бы личный опыт? Поделитесь? Пока-что это утверждение звучит крайне самонадеянно.
Если Вам хотелось услышать примеры обоснования первопричин проведения рефакторингов и покрытия тестами, по приведенной задаче, я могу синтезировать пару, тройку. Относительно глобальной ситуации:
1) менеджмент по итогам прошедшего года пришел к выводу, что группа программистов не справляется с поставленными задачами в срок и качество продукта ниже заявленного, новый тех. лид. проекта принимает решение о последовательном изменении методологии разработки, постулируется необходимость покрывать новый код и изменения в старый код тестами перед тем как он попадет на ревью.
2) В унаследованный проект для его поддержки и модификации нанята группа программистов - цель номер один - не допустить регрессии существующего кода, цель номер два, увеличить скорость добавления новых фич в проект, цель номер три понять как работает уже написанный код - для решения этих целей среди прочих выбрано дополнительное покрытие тестами.
3) Сотрудник отдела ведет подрывную деятельность на предприятии и безнаказанно занимается рефакторингом легаси кода.
Локально по коду:
1) Изначально код копировал файлы целиком, теперь появилась необходимость копировать по частям, поскольку изменились требования к системе.
2) Изначально код копировал файлы по частям, теперь появилась необходимость для множества маленьких файлов выполнять один способ копирования, а для других другой.
3) Изначально код копировал файлы по одному, теперь процесс необходимо распараллелить по носителям.
4) Изначально код копировал известный на этапе компиляции набор файлов, теперь пользователю необходимо дать возможность включить/исключить некоторые из них
5) Изначально код копировал файлы локально, теперь требуется посылать команды на удаленную машину.
6) Изначально код копировал файлы, а теперь он должен их перемещать с гарантией удаления информации с изначальной позиции считывания.
7) Изначально код решал одну из выше перечисленных задач, теперь требуется написать на его основе небольшую библиотеку классов, используемую в компании для решения каждой из представленных задач без необходимости переписывать общую для алгоритма часть.
0
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
13.02.2016, 15:07
Цитата Сообщение от Melg Посмотреть сообщение
Целью данной активности в конечном счете является как раз приобретение необходимых навыков/подходов при решении подобных задач в реальных условиях. В общем случае ставится задача получения опыта в проведении рефакторингов без (или с минимальным количеством) ошибок в условиях большого объема кода не покрытого тестами, приобретения навыков тестирования для предотвращения регрессии кода при внесении изменений (связанных с изменениями в бизнес-правилах). А так же освоения методологии разработки через тестирования.
Ну и в чем вопрос тогда? В сферическом вакууме вылизывать код можно бесконечно долго. Рефакторишь пока рефакторится, тестируешь пока тестируется. Изучение же ж.

Цитата Сообщение от Melg Посмотреть сообщение
100 процентов покрытия - выбраны как идеальный случай, к которому я стремлюсь, 70 процентов как случай достаточного покрытия, предполагающий тестирование бизнес логики, и критических сегментов кода без необходимости тестировать не используемые при решаемой задаче возможности, либо код связывания элементов логики в единое целое (которое может быть перекрыто статическим анализом, корректной компиляцией, приемочным тестированием и т.д.)
Так и думал, что число 70 выбрано пальцем в небо.

Цитата Сообщение от Melg Посмотреть сообщение
У Вас завалялась статистика на этот счет? выработанная система, описывающая положение дел? может быть, хотя бы личный опыт? Поделитесь?
Личный опыт наблюдения за окружением + опыт коллег и руководителей + куча прочитанных интервью. Ну вообще и так очевидно - за одного практика двух теоретиков дают. Это не значит, что читать не надо, - надо конечно. Но практика важнее.

Цитата Сообщение от Melg Посмотреть сообщение
Локально по коду:
Какое отношение все нижеперечисленное имеет к рефакторингу?
0
542 / 163 / 79
Регистрация: 23.09.2013
Сообщений: 316
13.02.2016, 15:43  [ТС]
ct0r, Вопрос не был о том сколько мне часов, минут, секунд выделить на рефакторинг или покрытие тестами и кто сколько разрешит. Временная составляющая не затрагивалась вообще, перечитайте озвученные мной вопросы. Более того я не акцентировал внимание на том какие причины привели к задаче рефакторинга и покрытия тестами, а спрашивал про то, какие практические методы используют люди в своей каждодневной работе с их требованиями и их ограничениями. Общим остается наличие куска кода, который слишком велик и который нужно протестировать. Насколько сильно разделяют задачу и от чего это зависит, кроме того каким образом это разделение достигается - вот что меня интересует.
70 выбрано не совсем случайно, мне нужно число гарантированно больше 50 процентов, позволяющее увидеть как люди действуют в условиях необходимости тестирования классов с зависимостями от других классов.
Какое отношение все нижеперечисленное имеет к рефакторингу?
Вы спрашивали, зачем в принципе проводить рефакторинг кода, я привел примеры возможных изменений в бизнес правилах, удовлетворить которые можно путем изменения кода, добавления в него новой функциональности, добавление которой при существующем дизайне (один класс который занят всем) было бы не слишком простой задачей, это один из весомых доводов к проведению рефакторинга, разве нет?
0
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
13.02.2016, 17:04
Цитата Сообщение от Melg Посмотреть сообщение
а спрашивал про то, какие практические методы используют люди в своей каждодневной работе с их требованиями и их ограничениями.
Ну то есть про это я уже сказал, так? А конкретные методы рефакторинга описаны в книгах.

Цитата Сообщение от Melg Посмотреть сообщение
какие практические методы используют люди в своей каждодневной работе с их требованиями и их ограничениями. Общим остается наличие куска кода, который слишком велик и который нужно протестировать. Насколько сильно разделяют задачу и от чего это зависит, кроме того каким образом это разделение достигается
Вот мы и подошли к тому, как надо было сформулировать вопрос в два предложения, избегая кучи ненужной информации Я вижу, что ты прешься по умным словам, терминам, предложениям (поправь меня, если я не прав), потому что зачем например иначе упоминать "швы Физерса", ограничивая аудиторию тех, кто понял вопрос, только теми, кто читал его книгу? Особенно если учесть, что сама по себе суть шва элементарна, и ее понимает каждый.

Цитата Сообщение от Melg Посмотреть сообщение
70 выбрано не совсем случайно, мне нужно число гарантированно больше 50 процентов, позволяющее увидеть как люди действуют в условиях необходимости тестирования классов с зависимостями от других классов.
Число 70 мне ни о чем не говорит. Другим тоже. Почему бы просто не сказать: дофига зависимостей в классе, по-любому надо будет их разруливать?

Цитата Сообщение от Melg Посмотреть сообщение
добавления в него новой функциональности, добавление которой при существующем дизайне (один класс который занят всем) было бы не слишком простой задачей, это один из весомых доводов к проведению рефакторинга, разве нет?
Если мы действительно поимеем большой гемор без рефакторинга, то да, все так. Я именно это и хотел услышать

Цитата Сообщение от Melg Посмотреть сообщение
Я такой сепарации практически нигде не видел, поэтому и задаюсь вопросом как другие программисты применяют рефакторинги и к чему они приходят в итоге.
А сможешь для начала показать не детский проект с 90-100% покрытием (я так понял, что у тебя при именно таких процентах проблема), где мало интерфейсов, шаблонов и в этом духе?
0
Антикодер
Эксперт функциональных языков программирования
1888 / 870 / 48
Регистрация: 15.09.2012
Сообщений: 3,088
19.02.2016, 10:55
обычно этим занимаются люди, которым не сказали, что есть функциональное программирование.
0
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
19.02.2016, 14:03
Цитата Сообщение от XRuZzz Посмотреть сообщение
обычно этим занимаются люди, которым не сказали, что есть функциональное программирование.
Справедливости ради, в ФП языках тоже можно все смешать в кучу. Так что разруха в головах. Но рефакторить там проще и юнит-тестить приятнее, факт.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.02.2016, 14:03
Помогаю со студенческими работами здесь

Применение кода из Unit1 в Unit2
Здравствуйте. Как можно применить один код в нескольких Unit-ах ссылаясь на Unit1. В Unit1, Unit2, Unit3 .... много формул и из-за этого...

Применение кода js при определенной ширине экрана
var win = $(this); //this = window if (win.width() <= 992) { $(document).ready(function(){ $('.bxslider').bxSlider({ mode:...

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

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

Напишите фрагмент кода для определения кода нажатой клавиши (расширенного кода в том числе)
Напишите фрагмент кода для определения кода нажатой клавиши (расширенного кода в том числе). Найдите коды клавиш Esc, Enter, BackSpace,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru