Войти
ПрограммированиеФорумОбщее

Парадигмы эффективно снижающие сложность кода...

Страницы: 1 2 313 14 Следующая »
#0
20:42, 24 апр. 2012

а значит повышающие его прозрачность, структурность...

надо ли говорить, что развитие очень сложных программных комплексов на этом во многом и держится...

давайте в этой ветке не выпендриваться, а делиться ими, и слухами о них, да - но желательно фактами...

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

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

и постараемся:
и формулировать понятно...
и не заставлять никого лишний раз переставлять слова - там где надо просто поднять напряжение понималки, взяв его избыток у важности...

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


#1
21:15, 24 апр. 2012

Чур паттерны из Gang of Four считать всем известными и не упоминать!

#2
21:20, 24 апр. 2012

Не использовать дебагер.

#3
21:43, 24 апр. 2012

прочитать статью "Критерий тестируемости кода"

http://www.rsdn.ru/article/testing/TestCriteria.xml

или мне сделать выжимку?


Мой самый полезный мелкий совет который упрощает всем жизнь.

не использовать в аргументах функций - выражений (return - тоже функция)

BAD
foo( a->getName() );

GOOD
const std::string & name = a->getName();
foo( name );

BAD
const std::string & name = a->getName();
return name;

GOOD
return a->getName();


Пояснения, дебаг это >> 80% времени где проводит время программист, а значит читаемость когда важнее пару лишних минут на написание отдельно стоящего кода.


Сложные выражения
a->getI()->getT()->foo();
в топку.

#4
21:59, 24 апр. 2012

Не пиши акцессор (get(), set()) там где можно обойтись простым мембером (полем) класса.
Не используй шаблон, там где он не нужен (пример - класс 2д и 3д вектора, сколькомерные вектора вы собрались делать вашим шаблоном?)
Не создавай интерфейс и сложное наследование там, где можно обойтись 1 классом.
Не используй класс там, где можно обойтись структурой.
Не используй лист там, где можно обойтись вектором.
Не используй вектор там, где можно обойтись сишным массивом.
Не создавай модуль там, где достаточно пары функций.

ДЗЕН ПИТОНА http://www.python.org/dev/peps/pep-0020/

Красивое лучше некрасивого.
Явное лучше неявного.
Сложное лучше чрезмерно усложнённого.
Плоское лучше вложенного.
Разреженное лучше чем плотно сложенное (Sparse is better than dense).
Читаемость решает.
Особые случаи недостаточно особенны, чтоб нарушать правила.
Практичность лучше чем чистота (purity).
Ошибки никогда не должны проходить незаметно (silently).
Если только их явно не отключили.
Перед лицом двусмысленности избегай соблазна угадывать.
Должен быть один -- и желательно единственный -- способ сделать дело.
Хотя решение может быть не очевидно без накурки (Although that way may not be obvious at first unless you're Dutch.)
Сейчас лучше чем никогда.
Хотя никогда часто лучше чем *прямо* сейчас.
Если реализацию объяснить трудно -- это плохая идея.
Если реализацию объяснить легко -- это может быть хорошей идеей.
Неймспейсы -- отличная идея. Давайте использовать их чаще.

#5
22:13, 24 апр. 2012

kvakvs
> Не пиши акцессор (get(), set()) там где можно обойтись простым мембером (полем) класса.
> Не создавай модуль там, где достаточно пары функций.
Антипатерны? :)

Ну а остальное - не применимо к делу без Вагона опыта(знать эту грань "где можно"/"достаточно")
ИМХО

#6
22:51, 24 апр. 2012

kvakvs
> Не пиши акцессор (get(), set()) там где можно обойтись простым мембером (полем) класса.
> Не используй шаблон, там где он не нужен (пример - класс 2д и 3д вектора, сколькомерные вектора вы собрались делать вашим шаблоном?)
> Не создавай интерфейс и сложное наследование там, где можно обойтись 1 классом.
> Не используй класс там, где можно обойтись структурой.
> Не используй лист там, где можно обойтись вектором.
> Не используй вектор там, где можно обойтись сишным массивом.
> Не создавай модуль там, где достаточно пары функций.
Ни о чем не говорящие высказывания мало опытным людям.

> Не используй класс там, где можно обойтись структурой.
> Не используй лист там, где можно обойтись вектором.
> Не используй вектор там, где можно обойтись сишным массивом.
> Не создавай модуль там, где достаточно пары функций.
А эти ещё и вредные, если неопытный человек не правильно это воспримет.

> Не используй вектор там, где можно обойтись сишным массивом.
А эти ещё и опасные.

> Не пиши акцессор (get(), set()) там где можно обойтись простым мембером (полем) класса.
> Не создавай интерфейс и сложное наследование там, где можно обойтись 1 классом.
> Не используй класс там, где можно обойтись структурой.
> Не используй лист там, где можно обойтись вектором.
> Не используй вектор там, где можно обойтись сишным массивом.
> Не создавай модуль там, где достаточно пары функций.
А эти ещё увеличивают сложность, неизменяемость и антиструктурность кода.

#7
22:52, 24 апр. 2012

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

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

Затем возникло несколько проблем:
- когда я через некоторое время опять пытался понять код, который написал, то это было практически невозможно.
- в коде было множество мелких ошибок, хотя в целом программа вроде работала.

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

Затем я осознал, что пишу код не по ООП законам, хоть и использую классы и объекты. Начал экспериментировать с наследованием, интерфейсами, в потом и генериками в C#. В итоге чаще всего получалось так, что созданный якобы универсальный класс никуда не годится и очень сложен и использует вагон трюков с наследованием базовых классов и прочее. Это был очередной тупик для меня. Не хотел бы я проектировать универсальные библиотеки, например .NET, это дело многих людей, а не одиночек.

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

Короче в итоге от того человека, который мог написать без труда рабочую, хоть и говнокодом программу, практически ничего не осталось. Завершить программы теперь вообще не удавалось, да не то что завершить, а сделать хотябы 10%...

#8
23:03, 24 апр. 2012

igo
> Парадигмы эффективно снижающие сложность кода...
> а значит повышающие его прозрачность, структурность...
Декларативная, объектно-ориентированная, аспектно-ориентированная, функциональная, логическая, предметно-ориентированная, Data-Driven.

#9
23:13, 24 апр. 2012

Серебряной пули нет.

#10
23:22, 24 апр. 2012

... Всё ограничивалось несколькими универсальными классами и бесконечной их доработкой напильником. И вот однажды, продвинулся с мертвой точки и начал писать следующий класс, который должен был использовать предыдущий готовый класс. Как я не был уверен в том, что всё должно было срастись, но в итоге оказывалось, что предыдущий класс требуется изменять, что он оказывается не подходит для нового класса и что они не стыкуются. Это что называется проектирование снизу вверх, здесь я потерпел тотальное поражение. Повелся на сладкие речи ООП пропагандистов. Хоть я и часто пользуюсь готовыми универсальными классами из .NET, но сам писать их больше не намерен.

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

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

Вот собственно и всё. Вспоминаешь вольно не вольно слова "code is design", как бы они парадоксально не звучали для нынешнего ооп программирования.

Дело еще в том, что многие часто повторяют одно и то же: пиши программу по законам ООП, сначала полностью её спроектируй, а только потом..

#11
23:31, 24 апр. 2012

Пару ценных советов.

Никогда не используй левые переменные для сохранения временных значений. Всегда создавай для этого новые, специальные.

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

#12
23:45, 24 апр. 2012

.. и только потом сядь и быстренько напиши код. Так вот заявляю от своего имени, всё это чушь собачья. И проектировал и садился потом писать и всегда оказывалось что при написании появляются совсем другие требования и совсем другой дизайн.

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

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

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

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

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

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

Надеюсь кого то заставит задуматься мой клинический случай.

#13
23:53, 24 апр. 2012

используй const везде где это возможно

#14
0:06, 25 апр. 2012

Pushkoff
> используй const везде где это возможно

CTexture* CMaterialManager::LoadTexture(const std::string &filename)
{
  if (textures[filename])
    return textures[filename];

  CTexture* texture = new CTexture(filename);
  textures[filename] = texture;
    return texture;
}
А так можно делать?
textures - std::map<std::string, CTexture*>
Страницы: 1 2 313 14 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.