Сообщение Re[6]: Оцените качество кода на С++ от 23.01.2015 16:10
Изменено 23.01.2015 16:21 Юрий Лазарев
Здравствуйте, ononim, Вы писали:
O>Весь код рефакторить не буду, мне еще есть чем заняться, но могу показать как я бы начал делать декомпозицию, даже не вникая пока в весь алгоритм. К примеру берем одну из самых длинных ф-ий — CSewingDlg::PseudoProcessAcceptedData. ВИдим цикл в самом начале. [] назвать ее AcceptrdDataPseudoProcessor а все что я написал выше, и что не написал — сделать ее методами. Про мелочи типа именования переменных и т.п. я уж не говорю (ii0 — это жесть). Ваш код для proof-of-concept вполне годный, но для продакшена его нужно переделать. К счастью его и _можно_ переделать, что бывает далеко не всегда.
Вообще, да, это первое что приходит в голову. Открою вам страшную тайну — примерно так я и сделал перед вторым этапом работы, именно, разбил код этой гиперфункции на 8 последовательных вызовов, с более-менее замкнутым содержанием в каждой. Но они все пользуются общими переменными, которые в класс тащить не очень хочется. Потому что это рабочие переменные, потому что их определение и время жизни уходит из-под контроля, они становятся для алгоритма в некоем смысле "глобальными", что конечно, не смертельно, но и не помогает в разработке. Поэтому я поступил проще — передаю их все как ссылки через параметры. Это временная мера, и также я продолжаю искать лучшее решение. Несмотря на то, что выглядят вызовы "ужасно", зато я сразу вижу все зависимости, где переменные возникают, где они используются.
Но в любом случае это насилие над кодом, реально не приносящее особых выгод. Слишком искусственный подход, еще немного, и получится обертка каждой строки. Я ищу семантический (осмысленный) способ рефакторинга. Скажем, если бы можно было придумать определенную алгебру узлов, я взял бы ее за основу класса безоговорочно.
Теперь с точки зрения разработки. Допустим, я пишу локальный цикл, еще не зная, насколько он будет полезен в окончательном алгоритме. Вы рекомендуете мне сразу оформлять его в виде метода класса, или подождать, пока код устоится? Если я его оформляю в метод, то 1) он отрывается визуально от контекста (а именно из контекста я решаю о его полезности), мне надо проделать лишнюю техническую работу по заведению метода, разрешить вопросы с переменными и т.д. В результате я выбрасываю этот метод.
Или же просто я пишу цикл по месту алгоритма, оцениваю его и при желании правлю или удаляю, никуда не перемещаясь. Результат получается тот же, но без лишних хлопот.
Поскольку логика алгоритма в основном последовательная, то нет большой беды в раздувании функции, — при исследовании каждого блока необходим лишь ближайший участок кода. Кажется, и у МакКонелла говорится об том же, что подобная последовательность кода не обязательно требует формального ограничения числа строк.
Если вернуться к аналогии с Войной и Миром, то заведение отдельных методов для мелких частей алгоритма подобно простановке названий параграфов в оглавлении длинной главы. Насколько это будет полезно? Кто читает главы по параграфам?
O>Весь код рефакторить не буду, мне еще есть чем заняться, но могу показать как я бы начал делать декомпозицию, даже не вникая пока в весь алгоритм. К примеру берем одну из самых длинных ф-ий — CSewingDlg::PseudoProcessAcceptedData. ВИдим цикл в самом начале. [] назвать ее AcceptrdDataPseudoProcessor а все что я написал выше, и что не написал — сделать ее методами. Про мелочи типа именования переменных и т.п. я уж не говорю (ii0 — это жесть). Ваш код для proof-of-concept вполне годный, но для продакшена его нужно переделать. К счастью его и _можно_ переделать, что бывает далеко не всегда.
Вообще, да, это первое что приходит в голову. Открою вам страшную тайну — примерно так я и сделал перед вторым этапом работы, именно, разбил код этой гиперфункции на 8 последовательных вызовов, с более-менее замкнутым содержанием в каждой. Но они все пользуются общими переменными, которые в класс тащить не очень хочется. Потому что это рабочие переменные, потому что их определение и время жизни уходит из-под контроля, они становятся для алгоритма в некоем смысле "глобальными", что конечно, не смертельно, но и не помогает в разработке. Поэтому я поступил проще — передаю их все как ссылки через параметры. Это временная мера, и также я продолжаю искать лучшее решение. Несмотря на то, что выглядят вызовы "ужасно", зато я сразу вижу все зависимости, где переменные возникают, где они используются.
Но в любом случае это насилие над кодом, реально не приносящее особых выгод. Слишком искусственный подход, еще немного, и получится обертка каждой строки. Я ищу семантический (осмысленный) способ рефакторинга. Скажем, если бы можно было придумать определенную алгебру узлов, я взял бы ее за основу класса безоговорочно.
Теперь с точки зрения разработки. Допустим, я пишу локальный цикл, еще не зная, насколько он будет полезен в окончательном алгоритме. Вы рекомендуете мне сразу оформлять его в виде метода класса, или подождать, пока код устоится? Если я его оформляю в метод, то 1) он отрывается визуально от контекста (а именно из контекста я решаю о его полезности), мне надо проделать лишнюю техническую работу по заведению метода, разрешить вопросы с переменными и т.д. В результате я выбрасываю этот метод.
Или же просто я пишу цикл по месту алгоритма, оцениваю его и при желании правлю или удаляю, никуда не перемещаясь. Результат получается тот же, но без лишних хлопот.
Поскольку логика алгоритма в основном последовательная, то нет большой беды в раздувании функции, — при исследовании каждого блока необходим лишь ближайший участок кода. Кажется, и у МакКонелла говорится об том же, что подобная последовательность кода не обязательно требует формального ограничения числа строк.
Если вернуться к аналогии с Войной и Миром, то заведение отдельных методов для мелких частей алгоритма подобно простановке названий параграфов в оглавлении длинной главы. Насколько это будет полезно? Кто читает главы по параграфам?
Re[6]: Оцените качество кода на С++
Здравствуйте, ononim, Вы писали:
O>Весь код рефакторить не буду, мне еще есть чем заняться, но могу показать как я бы начал делать декомпозицию, даже не вникая пока в весь алгоритм. К примеру берем одну из самых длинных ф-ий — CSewingDlg::PseudoProcessAcceptedData. ВИдим цикл в самом начале. [] назвать ее AcceptrdDataPseudoProcessor а все что я написал выше, и что не написал — сделать ее методами. Про мелочи типа именования переменных и т.п. я уж не говорю (ii0 — это жесть). Ваш код для proof-of-concept вполне годный, но для продакшена его нужно переделать. К счастью его и _можно_ переделать, что бывает далеко не всегда.
Вообще, да, это первое что приходит в голову. Открою вам страшную тайну — примерно так я и сделал перед вторым этапом работы, именно, разбил код этой гиперфункции на 8 последовательных вызовов, с более-менее замкнутым содержанием в каждой. Но они все пользуются общими переменными, которые в класс тащить не очень хочется. Потому что это рабочие переменные, потому что их определение и время жизни уходит из-под контроля, они становятся для алгоритма в некоем смысле "глобальными", что конечно, не смертельно, но и не помогает в разработке. Поэтому я поступил проще — передаю их все как ссылки через параметры. Это временная мера, и также я продолжаю искать лучшее решение. Несмотря на то, что выглядят вызовы "ужасно", зато я сразу вижу все зависимости, где переменные возникают, где они используются.
Но в любом случае это насилие над кодом, реально не приносящее особых выгод. Слишком искусственный подход, еще немного, и получится обертка каждой строки. Я ищу семантический (осмысленный) способ рефакторинга. Скажем, если бы можно было придумать определенную алгебру узлов, я взял бы ее за основу класса безоговорочно.
Теперь с точки зрения разработки. Допустим, я пишу локальный цикл, еще не зная, насколько он будет полезен в окончательном алгоритме. Вы рекомендуете мне сразу оформлять его в виде метода класса, или подождать, пока код устоится? Если я его оформляю в метод, то 1) он отрывается визуально от контекста (а именно из контекста я решаю о его полезности), мне надо проделать лишнюю техническую работу по заведению метода, разрешить вопросы с переменными и т.д. В результате я выбрасываю этот метод.
Или же просто я пишу цикл по месту алгоритма, оцениваю его и при желании правлю или удаляю, никуда не перемещаясь. Результат получается тот же, но без лишних хлопот.
Поскольку логика алгоритма в основном последовательная, то нет большой беды в раздувании функции, — при исследовании каждого блока необходим лишь ближайший участок кода. Кажется, и у МакКонелла говорится об том же, что подобная последовательность кода не обязательно требует формального ограничения числа строк.
Если вернуться к аналогии с Войной и Миром, то заведение отдельных методов для мелких частей алгоритма подобно простановке названий параграфов в оглавлении длинной главы. Насколько это будет полезно? Кто читает главы по параграфам?
К слову сказать, те 8 подфункций, к которым я прибег, в этой аналогии приобретают смысл страниц — чисто технический прием для преодоления иэбыточного объема.
O>Весь код рефакторить не буду, мне еще есть чем заняться, но могу показать как я бы начал делать декомпозицию, даже не вникая пока в весь алгоритм. К примеру берем одну из самых длинных ф-ий — CSewingDlg::PseudoProcessAcceptedData. ВИдим цикл в самом начале. [] назвать ее AcceptrdDataPseudoProcessor а все что я написал выше, и что не написал — сделать ее методами. Про мелочи типа именования переменных и т.п. я уж не говорю (ii0 — это жесть). Ваш код для proof-of-concept вполне годный, но для продакшена его нужно переделать. К счастью его и _можно_ переделать, что бывает далеко не всегда.
Вообще, да, это первое что приходит в голову. Открою вам страшную тайну — примерно так я и сделал перед вторым этапом работы, именно, разбил код этой гиперфункции на 8 последовательных вызовов, с более-менее замкнутым содержанием в каждой. Но они все пользуются общими переменными, которые в класс тащить не очень хочется. Потому что это рабочие переменные, потому что их определение и время жизни уходит из-под контроля, они становятся для алгоритма в некоем смысле "глобальными", что конечно, не смертельно, но и не помогает в разработке. Поэтому я поступил проще — передаю их все как ссылки через параметры. Это временная мера, и также я продолжаю искать лучшее решение. Несмотря на то, что выглядят вызовы "ужасно", зато я сразу вижу все зависимости, где переменные возникают, где они используются.
Но в любом случае это насилие над кодом, реально не приносящее особых выгод. Слишком искусственный подход, еще немного, и получится обертка каждой строки. Я ищу семантический (осмысленный) способ рефакторинга. Скажем, если бы можно было придумать определенную алгебру узлов, я взял бы ее за основу класса безоговорочно.
Теперь с точки зрения разработки. Допустим, я пишу локальный цикл, еще не зная, насколько он будет полезен в окончательном алгоритме. Вы рекомендуете мне сразу оформлять его в виде метода класса, или подождать, пока код устоится? Если я его оформляю в метод, то 1) он отрывается визуально от контекста (а именно из контекста я решаю о его полезности), мне надо проделать лишнюю техническую работу по заведению метода, разрешить вопросы с переменными и т.д. В результате я выбрасываю этот метод.
Или же просто я пишу цикл по месту алгоритма, оцениваю его и при желании правлю или удаляю, никуда не перемещаясь. Результат получается тот же, но без лишних хлопот.
Поскольку логика алгоритма в основном последовательная, то нет большой беды в раздувании функции, — при исследовании каждого блока необходим лишь ближайший участок кода. Кажется, и у МакКонелла говорится об том же, что подобная последовательность кода не обязательно требует формального ограничения числа строк.
Если вернуться к аналогии с Войной и Миром, то заведение отдельных методов для мелких частей алгоритма подобно простановке названий параграфов в оглавлении длинной главы. Насколько это будет полезно? Кто читает главы по параграфам?
К слову сказать, те 8 подфункций, к которым я прибег, в этой аналогии приобретают смысл страниц — чисто технический прием для преодоления иэбыточного объема.