DragonЦитата:
Но я руководствуюсь тем, что сначала то, что ты делаешь должно заработать, а только потом уже думать, как заставить это работать быстрее (гдето было - множество проектов гибнет от преждевременной оптимизации)
В общем верно, но не всегда. Например, если заранее понятно, что некий алгоритм требует большого времени для выполнения или пожирает очень много памяти, то следует сначала хорошенько подумать: возможно, удастся найти иной способ решения стоящей задачи. А вот низкоуровневую оптимизацию проводить действительно следует лишь после того, как модуль (или вся программа в целом) уже работает. Исключением является разве что передача параметров в процедуры, если разработка ведётся на ассемблере: там надо заранее озаботиться о передаче либо через регистры, либо через стек, чтобы потом не менять в тысяче мест. Правда, помочь в этой ситуации могут макрокоманды (не вызывать подпрограммы непосредственно с помощью CALL, а оформлять вызов с помощью макросов) -- но в любом случае надо чётко описывать, какие регистры сохраняются, какие изменяются... Понятно, что на ЯВУ этой проблемы нет.
SadKoЦитата:
В ООП ничего плохого нет
Что
ничего плохого, не соглашусь: ООП может привести к уменьшению производительности, а это плохо. Другое дело, что обычно достоинства превосходят недостатки.
Цитата:
Если использовать полиморфизм и инкапсуляцию, то можно защититься от всякого рода мэджиков. Преимущество - больше, чем даёт класс в своём интерфейсе, сделать с объектом нельзя
Тоже вставлю свои три копейки. Во-первых, инкапсуляция вовсе не обязательно требует ООП: дели программы на модули, которые "видят" друг друга только через явно прописанные интерфейсы -- и всё. Во-вторых, полиморфизм -- штука мощная и полезная, но иногда можно его имитировать без явного применения ООП. Например, ядро ОС вызывается прикладными программами через единую точку входа (либо шлюз для CALL, либо через какой-то INT). Ядро выполняет первоначальную обработку запроса, общего для всех функций, а затем передаёт управление конкретному обработчику, опираясь на код функции. Это можно реализовать через ООП (каждый обработчик представляет собой класс, наследующий свои свойства от базового класса "обработчик"), но эффективнее (да, пожалуй, в данном конкретном случае и проще) реализовать то же самое через обычную таблицу вызовов без ООП. Ну и в-третьих, с объектом нельзя сделать больше, чем позволяет интерфейс, только в том случае, если использовать исключительно высокоуровневые "фичи". Понятно, что если, например, осуществлять копирование участков памяти на низком уровне, то можно и напортачить, хотя такое копирование будет выполняться быстрее, чем с использованием специализированных методов.
Потому я и говорю: ООП -- инструмент, который надо уметь держать в руках и правильно употреблять, а заодно помнить, что чем универсальнее инструмент, тем он хуже подходит для каждого конкретного применения. Т.е. всегда думать головой, а не использовать "ООП ради ООП".
Цитата:
Шаблоны - тоже хорошая вещь. Но плодить их без надобности нет смысла. Они резко увеличивают объём кода
Жутко удобная и почти столь же жутко неэффективная :) Дизассемблировал как-то игрушку такую -- Герои меча и магии 3 (написана на VS 6, судя по библиотекам). Там используются шаблоны для хранения различных объектов (деревья применяются, строки, ещё что-то). Работать всё работает, но лишнего кода... "о мама мия!" В общем, при ручном написании того же самого даже на том же Си (не говоря уже об асме) объём кода сократился бы, наверное, вдвое, а скорость работы соответствующих подпрограмм в несколько раз выросла б. Понятное дело, что на пне-4 это несущественно, но когда игрушка только появилась, она откровенно тормозила на первых "пнях" с невысокой частотой (типа 133 МГц).
Кстати, мораль сей басни такова: тестируйте свои гениальные программы на медленных машинах :)
Цитата:
С механизмом генерации и отлова исключений я пока так и не смог разобраться. Но скажу, что на это тратится прилично кода, да и это весьма такая скрытая вещь в себе. Поэтому использовать исключения в ядре крайне не рекомендую
Частично разобрался в процессе упомянутого дизассемблирования и полностью присоединяюсь к рекомендациям :) В ядре -- только ЯВНЫЕ проверки всего, что может быть неправильным, и ЯВНАЯ же обработка всех этих неправильностей. Использовать SEH в низкоуровневых программах себе дороже выйдет. В высокоуровневых -- когда как. Я обычно стараюсь не допустить возникновения исключений в принципе, но иногда использую и SEH, когда программа красивше от этого становится или ради универсальности (например, упоминаемые мною деревья вырабатывают исключения при обнаружении какой-то кривизны).
Цитата:
Так что, разумный подход и знание, того как генерируется код для классов позволят найти оптимальное решение. Пусть и производительность немного упадёт (а, может и вырастет?)
Вспоминается известная шутка: "Наша работа настолько секретная, что мы сами не знаем, что мы делаем". Так что, действительно, если не знаешь -- сначала разберись, а потом программируй, а не наоборот.
Кстати, если при применении менее эффективных с технической точки зрения методов производительность выросла, значит, программист что-то не так написал. Повод задуматься над качеством своего кода ;)