Re[20]: Ошибок не делает тот, кто ничего не делает
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 29.03.07 13:52
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Не, ну Янус конечно кое какую логику содержит. Но, вот беда, львиная доля багов в нем приходится как раз на GUI.


Ладно. Что бы поспорить и что-то доказать прийдётся сырцы Януса читать. Я уж лучше просто останусь при мнении, что юнит-тесты вельми полезная штука
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[14]: Ошибок не делает тот, кто ничего не делает
От: bkat  
Дата: 29.03.07 13:55
Оценка:
Здравствуйте, AndrewVK, Вы писали:

B>>Может сначала стоит потратить время на то, чтобы продумать интерфейсы.


AVK>Как все просто


Чертовски сложно, но никуда без этого.
Иначе ведь вообще ничего до конца не довести.

Ну в общем у нас явно разный опыт.
У меня затраты на юнит-тесты не настолько велики, чтобы от них (юнит-тесты) стоило бы отказаться.
При всяких рефакторингах затраты на обновление именно юнит-тестов минимальны.
Потом, как я уже писал в другом топике, все равно программер
практически всегда создает свое окружение, в котором он может "играться"
со своим кодом и как-то убеждаться в том, что его творение в принципе дышит
и делает ожидаемые вещи.
Разработку без подобного окружения я лично вообще не представляют.
Юнит-тесты — это просто часть этого окружения.
Можно вообще большую часть подобного окружения поддерживать именно как юнит-тесты.
Re[14]: Ошибок не делает тот, кто ничего не делает
От: Gajdalager Украина  
Дата: 29.03.07 14:01
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, red_dragon, Вы писали:


_>>Делали рефакторинг без юнит-тестов?


AVK>Я делаю регулярно. Ужасов не замечено.


Каким образом уверяешься, что ничего не поломал при рефакторинге? Кент Бек в Test Driven Development говорит о юнит-тестах как раз о средстве повишения уверенности.
Еще тут было замечание что при рефакторинге ломается много тестов — ну вы для того же их и писали, чтобы зафиксировать поведение системы и быть уверенными в том, что она ведет себя именно так, как до правок. Если ломается слишком много тестов — значит у вас одно и то же действие тестируется многими тестами.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[15]: Ошибок не делает тот, кто ничего не делает
От: degor Россия  
Дата: 29.03.07 14:05
Оценка: 3 (1) :))
Здравствуйте, Gajdalager, Вы писали:

G>Каким образом уверяешься, что ничего не поломал при рефакторинге? Кент Бек в Test Driven Development говорит о юнит-тестах как раз о средстве повишения уверенности.


это для слабых духом. настоящий программист всегда уверен в себе.
Re[15]: Ошибок не делает тот, кто ничего не делает
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.03.07 14:09
Оценка: -1
Здравствуйте, aka50, Вы писали:

A>>>Это примерно то, на что распадается приложение, которое проектируется с использованием паттерна IoC. Если приложение не проектировалось изначально под IoC, прикрутить потом IoC — себе дороже.


AVK>>Да, ребяты. Вопросов больше не имею.

A>А расшифровать? А то ощущение что "послали"...

У меня как то в нематерный русский не расшифровывается, уж извини.
... << RSDN@Home 1.2.0 alpha rev. 675>>
AVK Blog
Re[15]: Ошибок не делает тот, кто ничего не делает
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.03.07 14:09
Оценка:
Здравствуйте, bkat, Вы писали:

B>>>Может сначала стоит потратить время на то, чтобы продумать интерфейсы.


AVK>>Как все просто


B>Чертовски сложно, но никуда без этого.

B>Иначе ведь вообще ничего до конца не довести.

Уверен? А как же XP?

B>Потом, как я уже писал в другом топике, все равно программер

B>практически всегда создает свое окружение, в котором он может "играться"
B>со своим кодом и как-то убеждаться в том, что его творение в принципе дышит
B>и делает ожидаемые вещи.

Видишь ли, простенькое окружение и хорошее покрытие юнит-тестов это две большие разницы. Ничего не имею против нескольких тестов, имитирующих базовые сценарии использования тестируемого кода.
... << RSDN@Home 1.2.0 alpha rev. 675>>
AVK Blog
Re[3]: Никак. Я их не делаю.
От: Zuka Россия  
Дата: 29.03.07 14:23
Оценка: :))
Здравствуйте, Tilir, Вы писали:

T>В целом да. Тяжко покрыть юнит-тестами драйвер на сях/ассемблере.


А что тяжкого-то? Берем и паяем MockDevice...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[15]: Ошибок не делает тот, кто ничего не делает
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.03.07 14:29
Оценка:
Здравствуйте, Gajdalager, Вы писали:

G>Каким образом уверяешься, что ничего не поломал при рефакторинге? Кент Бек в Test Driven Development говорит о юнит-тестах как раз о средстве повишения уверенности.


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

G>Еще тут было замечание что при рефакторинге ломается много тестов — ну вы для того же их и писали, чтобы зафиксировать поведение системы и быть уверенными в том, что она ведет себя именно так, как до правок.


Э нет. Не все так просто. Правильное их срабатывание, это когда они срабатывают там, где я этого не ожидал. А если у меня юнит-тесты ломаются не из-за того, что сломалось то, что они непосредственно проверяли, а просто потому что система сильно изменилась, то это срабатывание бесполезно.
... << RSDN@Home 1.2.0 alpha rev. 675>>
AVK Blog
Re: Как Вы боретесь с ошибками?
От: IT Россия linq2db.com
Дата: 29.03.07 14:35
Оценка: 191 (16) +4
Здравствуйте, _Mihail, Вы писали:

Несколько практических советов от настоящих индейцев.

1. Настоящий индеец прежде всего заходит в меню Debug и в диалоге Exceptions включает галку Thrown на CLR Exceptions для managed языков. Это позволяет сэкономить не просто хучу, а туеву хучу времени при поиске ошибок. Отсюда следствие — настоящие индейцы не используют логику на исключениях, иначе весь кайф пропадает.

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

3. Copy/Paste vs. повторное использование. Copy/Paste — это разносчик багов, что есть плохо. Но шизиловка, когда каждые две строчки кода оформляются в виде отдельного метода ни чем не лучше. Поэтому настоящие индейцы копипейстят, но только один раз. Если некоторый фрагмент кода повторяется уже в третий раз, то это хорошая причина для оформления его в виде отдельного метода.

4. Настоящие индейцы не боятся длинных линейных методов, они не любят запутанных ветвистых уродцев, в которых легко прятаться багам. Существуют задачи, например, по генерации кода, которые выполняются в несколько последовательных шагов. Разбиение таких задач на несколько методов, которые используются только один раз не имеет никакого смысла, особенно учитывая, что часто приходится передавать контекст в эти методы, что выливается в длиннючий список параметров. Лучше отделить более менее независимые блоки коментариями, кратко описывающими суть действия. Если же выполняемая операция становится действительно сложной и плохоуправляемой, а рефакторинг такого метода приводит к выделению методов с невменяемым числом передаваемых параметров, то настоящие индейцы выносят такой код в отдельный класс. В отличии от метода в отдельном классе вместо передаваемых параметров можно использовать контекст самого класса.

5. Настоящий индеец думает 10 раз прежде чем объявить статическую переменную. Статический контекст самый злобный источник багов и кривого дизайна. Даже если не будет багов, то кривизну дизайна в дальнейшем придётся выкривлять с помощью линз с обратной кривизной. Если же индеец всё же решилися на использование статического контекста, то он возвращается к началу данного пункта ещё раз. В принципе, статические переменные можно использовать для кеширования некоторых данных при соблюдении правил гигиены в многопоточных приложениях. В остальных случаях как правило стоит серьёзно задуматься.

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

7. Ошибки происходят не только из-за неправильного кода, но и из-за неправильных данных, которые впрочем могут быть порождены неправильным кодом. Настоящие индейцы используют логи и вывод отладочной печати в отладочное окно студии. Зачастую сложную структуру данных проще напечатать и иметь сразу всю картину, чем бродить по окну Watch, заглядывая по очереди во все переменные класса.

8. Настоящий индеец знает, что только что написанный код обязательно будет меняться либо им самим, либо кем-то другим, может быть через 5 минут, может быть через 5 лет. В трудно модифицируемом коде сложно исправлять существующие баги и не вностить новые. Поэтому, основной критерий качества кода для настоящего индейца — это готовность кода к модификациям и способность после этого оставаться готовым к следующим модификациям.
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: Никак. Я их не делаю.
От: aka50 Россия  
Дата: 29.03.07 14:41
Оценка:
Здравствуйте, Zuka, Вы писали:

Z>Здравствуйте, Tilir, Вы писали:


T>>В целом да. Тяжко покрыть юнит-тестами драйвер на сях/ассемблере.


Z>А что тяжкого-то? Берем и паяем MockDevice...


Ты будешь смеяться, но так обычно и делают... http://www.ddj.com/dept/debug/197801325

An emulator contains both hardware and software technology. Emulation hardware consists of functionality on the DSP chip, which enables the collection of data. This data provides state behavior and other system visibility. Hardware is also required to extract this information from the DSP device at high rates and format the data. Emulator software provides additional higher level control and an interface with the host computer, usually in terms of an interface called a debugger. The debugger provides the development engineer an easy migration from the compilation process (compiling, assembling, and linking an application) to the execution environment. The debugger takes the output from the compilation process (for example, a .out file) and loads the image into the target system. The engineer then uses the debugger to interact with the emulator to control and execute the application and find and fix problems. These problems can be hardware as well as software problems. The emulator is designed to be a complete integration and test environment

Re[16]: Ошибок не делает тот, кто ничего не делает
От: bkat  
Дата: 29.03.07 15:31
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, bkat, Вы писали:


B>>>>Может сначала стоит потратить время на то, чтобы продумать интерфейсы.


AVK>>>Как все просто


B>>Чертовски сложно, но никуда без этого.

B>>Иначе ведь вообще ничего до конца не довести.

AVK>Уверен? А как же XP?


А что XP? Про него ничего не знаю

А вот если ты разрабатываешь библиотеку для других и
будешь постоянно менять интерфейсы, то успеха точно не будет.
Re[3]: Как Вы боретесь с ошибками?
От: FDSC Россия consp11.github.io блог
Дата: 29.03.07 15:40
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, FDSC, Вы писали:


FDS>>Вообще, когда используешь C# и .NET постоянно используешь сразу несколько компонентов. Обязательно надо что-то куда-то создать, записать, передать интерфейс и т.п. Куча служебных действий, иногда создаётся впечатление, что вернулся в assembler. Всё время думаешь о коде, а не о программе.

S>А ты не мог бы привести примеры этих "служебных действий", которые были тебе не нужны на С++?
S>По моим впечатлениям, код на С# обычно компактнее кода на С++.

Дело в том, что если бы я писал функцию сохранения в файл на C++ я бы написал всё с нуля, но вызов был бы в одну строку.
А, скажем, для сериализации мне необходимо (вместо пары сотен строк)
1. Создать поток, связанный с файлом, открытым в правильном режиме (одна строка)
2. Создать форматтер (одна строка)
3. Передать в форматтер сериализуемый объект.

Вот я и говорю: я просто нетерпелив. Мне мешает то, что это занимает 3 строки

При сравнении строк примерно то же: я должен создать итератор, что бы обращаться к строке независимо от кодировки, затем я должен выбрать каким образом я должен сравнивать строки (т.е. настройки локализации) и т.д.

Само по себе это всё идёт плюс несколько строк в код, но экономит, за счёт того, что это сделано, очень много кода. Но то, что я должен думать о том, что у меня в using не стоит System.IO при выполнении сериализации, которая якобы реализована, лично меня очень сильно раздражает. Именно тем, что думаешь уже высокоуровневыми терминами и когда тебе компилятор выдаёт ошибку, что он не нашёл соотв. namespace System.IO, ты как-будто об стенку грохаешься. Т.е. я бы ожидал отдельно для бинарной сериализации некоторый конструктор форматтера, который бы брал все необходимые параметры и не заставлял создавать мне поток, который я, скорее всего, после сериализации сразу же закрою.

Соотв., пример кода можно взять даже из rsdn.editor или любой другой программы: я специально смотрел код других программистов. Насколько я помню, там Влад (и кто там ещё?) всё делал как раз в таком же духе...
Re[17]: Ошибок не делает тот, кто ничего не делает
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.03.07 15:42
Оценка:
Здравствуйте, bkat, Вы писали:

B>А вот если ты разрабатываешь библиотеку для других и

B>будешь постоянно менять интерфейсы, то успеха точно не будет.

Вот если я ее уже кому то отдал, то да. А если я ее только разрабатываю?
... << RSDN@Home 1.2.0 alpha rev. 675>>
AVK Blog
Re[18]: Ошибок не делает тот, кто ничего не делает
От: bkat  
Дата: 29.03.07 16:04
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, bkat, Вы писали:


B>>А вот если ты разрабатываешь библиотеку для других и

B>>будешь постоянно менять интерфейсы, то успеха точно не будет.

AVK>Вот если я ее уже кому то отдал, то да. А если я ее только разрабатываю?


Разрабатываешь все равно с целью получить стабильные интерфесы,
которые не придется постоянно перелапачивать.

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

Верю, что в твоем конкретном случае юнит-тесты не работают,
но это не повод мне, и другим, от него отказываться.
Впрочем и мой положительый опыт ты тоже можешь запросто игнорировать,
если ты достигаешь качества другими, более эффективными способами.
Ничего против этого не имею
Re[18]: Ошибок не делает тот, кто ничего не делает
От: bkat  
Дата: 29.03.07 16:09
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, bkat, Вы писали:


B>>А вот если ты разрабатываешь библиотеку для других и

B>>будешь постоянно менять интерфейсы, то успеха точно не будет.

AVK>Вот если я ее уже кому то отдал, то да. А если я ее только разрабатываю?


Кстати, почему-то вот этот пост возражений не вызвает:
http://www.rsdn.ru/Forum/Message.aspx?mid=2424637&amp;only=1
Автор: IT
Дата: 29.03.07

Хотя IT тоже упомянул про автоматическое unit тестирование...
Re[19]: Ошибок не делает тот, кто ничего не делает
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.03.07 16:24
Оценка: +1
Здравствуйте, bkat, Вы писали:

AVK>>Вот если я ее уже кому то отдал, то да. А если я ее только разрабатываю?


B>Разрабатываешь все равно с целью получить стабильные интерфесы,

B>которые не придется постоянно перелапачивать.

Ну то есть тесты надо писать в конце, когда уже все интерфейсы стабилизировались?

B>В общем это абстрактный спор


А по мне так совершенно конкретный.

B>Верю, что в твоем конкретном случае юнит-тесты не работают,

B>но это не повод мне, и другим, от него отказываться.

А я и не призываю никого отказываться. Я призываю голову включать, а не агитировать за совецкую власть.
... << RSDN@Home 1.2.0 alpha rev. 675>>
AVK Blog
Re[19]: Ошибок не делает тот, кто ничего не делает
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.03.07 16:24
Оценка:
Здравствуйте, bkat, Вы писали:

B>Кстати, почему-то вот этот пост возражений не вызвает:

B>http://www.rsdn.ru/Forum/Message.aspx?mid=2424637&amp;only=1
Автор: IT
Дата: 29.03.07

B>Хотя IT тоже упомянул про автоматическое unit тестирование...

У IT немного иное понимание unit-тестирования. В свое время мы, кажется здесь, это уже обсуждали и пришли к консенсусу. Суть в том, что не нужно добиваться полного покрытия, нужно описывать в тестах только основные сценарии применения. Против этого (я, кажется, сегодня уже писал) я ничего не имею. Но это не совсем unit-тестирование в классическом его понимании.
... << RSDN@Home 1.2.0 alpha rev. 675>>
AVK Blog
Re[4]: Как Вы боретесь с ошибками?
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.03.07 16:24
Оценка: +1
Здравствуйте, FDSC, Вы писали:

FDS>Само по себе это всё идёт плюс несколько строк в код, но экономит, за счёт того, что это сделано, очень много кода. Но то, что я должен думать о том, что у меня в using не стоит System.IO при выполнении сериализации, которая якобы реализована, лично меня очень сильно раздражает. Именно тем, что думаешь уже высокоуровневыми терминами и когда тебе компилятор выдаёт ошибку, что он не нашёл соотв. namespace System.IO, ты как-будто об стенку грохаешься.


У тебя 2005 студия? На смарттеги внимания не обращаешь? Тогда поставь Решарпер.
... << RSDN@Home 1.2.0 alpha rev. 675>>
AVK Blog
Re[2]: Можно парочку дерзких вопросов?
От: FDSC Россия consp11.github.io блог
Дата: 29.03.07 16:28
Оценка:
Здравствуйте, IT, Вы писали:

IT>Несколько практических советов от настоящих индейцев.




IT>7. Ошибки происходят не только из-за неправильного кода, но и из-за неправильных данных, которые впрочем могут быть порождены неправильным кодом. Настоящие индейцы используют логи и вывод отладочной печати в отладочное окно студии. Зачастую сложную структуру данных проще напечатать и иметь сразу всю картину, чем бродить по окну Watch, заглядывая по очереди во все переменные класса.


Ммм. А если их сложно напечатать, что делать?
Например, 4-х мерная матрица 100х100х100х100 (помню, я так и не написал ту программу из-за того, что не смог нормально проанализировать её содержание)
Или, скажем, граф с представлением в виде списков следования? Это ж замучиться распечатывать! (я форму специальную делал)

IT>3. Copy/Paste vs. повторное использование. Copy/Paste — это разносчик багов, что есть плохо. Но шизиловка, когда каждые две строчки кода оформляются в виде отдельного метода ни чем не лучше. Поэтому настоящие индейцы копипейстят, но только один раз. Если некоторый фрагмент кода повторяется уже в третий раз, то это хорошая причина для оформления его в виде отдельного метода.


Хм. А вот что делать, если мне нужно реализовать процедуру умножения транспонированных матриц (очень просто, неправда ли?).
Варианты реализации:

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

2. Записать почти одинаковые алгоритмы для всех 4-х вариантов (т.е. AB, AtB, ABt, AtBt)
Минус: 4 раза копируется один и тот же метод

3. Записать метод с передачей в него флагов транспонированности, но тогда там тоже будет небольшой copy/paste
Минус: пользователь запутывается с флагами и становится тяжело использовать метод или необходимо написать 4 доп. метода, вызывающих этот для разных вариантов перемножений

4. Обращаться к матрице через свойство, что бы можно было не транспонировать матрицу физически
Минусы: * придётся возится с передачей указателей на соотв. методы взятия элемента матрицы, что неудобно
* небольшое (но чувствительное) снижение производительности в связи с дополнительными вызовами методов

5. Я могу писать перемножение прямо в методе (кстати, так и делаю, хоть дальше ругаюсь на пункт 4)
Минус: постоянные повторения одного и того же кода

Какой из этих вариантов предпочтительней?

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


IT>4. Настоящие индейцы не боятся длинных линейных методов, они не любят запутанных ветвистых уродцев, в которых легко прятаться багам.


Вот с этого начнём, точнее закончим. Не согласен

Где прятаться багам, если методы до отупения просты? Представьте себе, у вас все методы из 3-5 строк. Ну 10 максимум, обычно.
При этом есть одно условие: название вызываемого метода говорит о том, что этот метод делает, а этот метод делает только то, что сказано в названии (это, кстати, рекомендация Макконнелла). Тогда получаем кучу вот этих самых методов, которые просто и в которых не где прятаться багам, так как, фактически, такой код представляет собой обычный псевдокод.
Я почему это говорю, я не так давно пробовал (на C++) писать исключительно мелкими методами, как сказал, и скорость разработки у меня повысилась приблизительно в 1,5 раза (с отладкой). При этом большое количество багов из разряда логических ошибок перекочевало в разряд "забыл вызвать метод", "при кодировании использовал неправильный алгоритм расчётов". Кстати, в последнем случае, в мелких методах гораздо лучше видно несоответствие кода используемому алгоритму и несоответствие алгоритма решаемой задачи.

IT>Существуют задачи, например, по генерации кода, которые выполняются в несколько последовательных шагов. Разбиение таких задач на несколько методов, которые используются только один раз не имеет никакого смысла, особенно учитывая, что часто приходится передавать контекст в эти методы, что выливается в длиннючий список параметров. Лучше отделить более менее независимые блоки коментариями, кратко описывающими суть действия.


О! В январе так делал. Правда на Delphi, а не на C#. Сначала я написал бо-о-о-ольшую процедуру (200-300 строк). Её предназначение было — распознавание зашумлённых шестнадцатиричных чисел, написанных от руки на неровной поверхности. Дальше у меня появились предложения по улучшению... я стал писать вложенные процедуры, по 50-70 строк. Дальше это всё отказалось стабильно и хорошо работать . В итоге вся эта первоначальная процедура с вложенными функциями занимала почти 1000 строк.

IT> Если же выполняемая операция становится действительно сложной и плохоуправляемой, а рефакторинг такого метода приводит к выделению методов с невменяемым числом передаваемых параметров, то настоящие индейцы выносят такой код в отдельный класс. В отличии от метода в отдельном классе вместо передаваемых параметров можно использовать контекст самого класса.


Число параметров у методов было довольно небольшим, но их было ОЧЕНЬ много, до того много, что я стал их просто терять, я стал не понимать вообще где используется метод, который я вижу.

Я переписал всё через несколько классов, используя маленькие логичные как можно более простые блоки (и как можно более простые классы). Заняло у меня это один день, всё заработало и даже довольно прилично смотрится.

Как вы это объясните?
Кстати, таких примеров из моей личной практики программирования до фига. Я имею ввиду, преимущества мельких методов над крупными, но с комментариями над каждой частью. Например, год назад я писал рассчёт обратной задачи кинематики плоского манипулятора с замкнутой кинематикой (на C#) и заметил ошибку в реализации метода Ньютона только когда разбил его на много мелких методов. До этого же эта ошибка существовала чуть ли не с самого начала, я о ней знал, но думал совершенно на другие части программы.

Осенью я писал расчёт деформаций шпинделя (C++) и пока не начал разбивать неожиданно разросшийся класс на два, не нашёл правильного решения. Плюс, у меня там был как раз такой метод, какой вы советуете: генерация матрицы жёсткости. В этом методе было наибольшее число ошибок, он был труден для понимания и т.п. Разбей я его на несколько методов — всё было бы хорошо.
Может быть я вас неправильно понял?
Вот этот уродец (он и сейчас такой ):

// Вычисление формы деформации конструкции и реакций опор
void Spindle::CalcShifts()
{
        // Вычислить длины массива параметров опор и количество столбцов в матрице жёсткости
    int SC = Iteration + 2;
    int Lk = (SC + 1) * 2;
    K      = new double[Lk * (Lk + 1)];

    double * Kf = new double[Lk * (Lk + 1)];

    for (int i = 0; i < Lk * (Lk + 1); K[i++] = 0.0);

    // Создать систему разрешающих уравнений
    // Записать коэффициенты уравнений без учёта кинематических ограничений
    for (i = 0; i < SC; i++)
    {
        Bars[i]->SetK(K, Lk);
    }

    // Записать правые части
    *(K + 0        + Lk) = F;
    *(K + (Lk + 1) + Lk) = M;

    // Скопировать матрицу жесткостей без кинематических ограничений для дальнейших вычислений рекаций опор
    for (i = 0; i <  Lk * (Lk + 1); i++)
    {
        Kf[i] = K[i];
    }

    // Учесть кинематические ограничения первых двух опор обнулением столбцов, так как это упростит расчёт
    for (i = 0; i < Lk; i++)
    {
        *(K + (Lk + 1) * i + (2)     ) = 0.0;
        *(K + (Lk + 1) * i + (Lk - 2)) = 0.0;
    }

    // Учесть кинематические ограничения всех опор
    for (int j = 0; j < SC; j++)
    {
        for(int i = 0; i < Lk; i++)
        {
            *(K + (Lk + 1) * (j + 1)*2 + i) = 0.0;        // j + 1, так как первый узел ни на что не опирается; *2 - так как узлу соответсвует две строчки (перемещение и поворот)
        }
        *(K + (Lk + 1) * (j + 1)*2 + Lk) = Sp[j + this->maxSupportCount * 2];    // Координата кинематического ограничения по y
        *(K + (Lk + 1) * (j + 1)*2 + (j + 1)*2) = 1.0;                            // Единица на главной диагонали

//        ::MessageBox(0, itoa(Sp[j + this->maxSupportCount * 2]*1000000000, new char[11], 10), "EE", 0);
    }

    // Решить систему
    double * Y = NULL;

    // Отладка
    // #define DBG__
    #ifdef DBG__
        static int Z = 0;
        Z++;
        HANDLE File;
        int brum = 0;
        if (Z == 2)
        {
        File = ::CreateFileA("G:\\debug.tmp", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
        ::WriteFile(File, K, Lk*(Lk + 1)*sizeof(double), (LPDWORD)&brum, 0);
        }
    #endif

    MGauss(K, Y, Lk);

    // Отладка
    #ifdef DBG__
        if (Z == 2)
        {
        ::WriteFile(File, Y, Lk*sizeof(double), (LPDWORD)&brum, 0);
        ::CloseHandle(File);
        }
    #endif
    #undef DBG__

    // Установить эти значения в стержни
    for (i = 0; i < SC; i++)
    {
        Bars[i]->SetY(Y);
    }

    // Вычислить реакции опор (только силы, моменты равны нулю)
    for (i = 0, j = 2; j < Lk; i++, j += 2)
    {
        // Обнуление обязательно, т.к. на каждой итерации расчёта идёт запись в одну и ту же строку
        this->Sp[maxSupportCount*3 + i] = 0.0;

        for (int k = 0; k < Lk; k++)
        {
            this->Sp[maxSupportCount*3 + i] += Y[k] * Kf[k + (Lk + 1)*j];
        }
    }

    delete [] Kf;
    delete [] K;
    delete [] Y;
}





Re[5]: Как Вы боретесь с ошибками?
От: FDSC Россия consp11.github.io блог
Дата: 29.03.07 16:30
Оценка: :)
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, FDSC, Вы писали:


FDS>>Само по себе это всё идёт плюс несколько строк в код, но экономит, за счёт того, что это сделано, очень много кода. Но то, что я должен думать о том, что у меня в using не стоит System.IO при выполнении сериализации, которая якобы реализована, лично меня очень сильно раздражает. Именно тем, что думаешь уже высокоуровневыми терминами и когда тебе компилятор выдаёт ошибку, что он не нашёл соотв. namespace System.IO, ты как-будто об стенку грохаешься.


AVK>У тебя 2005 студия? На смарттеги внимания не обращаешь? Тогда поставь Решарпер.


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