Здравствуйте, Дарней, Вы писали:
Д>Это некритично. Если народ мирится со скоростью работы приплюснутого препроцессора, то уж лишние перекомпиляции в .NET точно переживет.
Народ не мирится, а извращается. Так вот, например:
class MySuperClassImpl;
class MySuperClass
{
public:
void myVeryComplexFunction(...);
private:
MySuperClassImpl *m_impl;
};
Здравствуйте, stalcer, Вы писали:
S>Народ не мирится, а извращается. Так вот, например:
Даже с костылями вроде предкомпилированных заголовков и таких вот фокусов средний проект на С++ компилируется минимум на порядок дольше, чем аналогичной сложности проект на C#
Припоминается мне один проект, полная перекомпиляция которого занимала почти сутки И ничего, живут ведь люди. Так что если перекомпиляция занимает 30 секунд, а не 10 — никто от этого точно не помрет
Здравствуйте, Дарней, Вы писали:
Д>Модульная организация в .NET может дать гарантию, что программа будет использовать точно ту версию класса (и классов, от которых он зависит), с которой она была скомпилирована. Модульная организация оберонов такой гарантии не дает.
Скорее так: Модульная организация оберона гарантирует, что используемый модуль имеет тот интерфейс, который использовался при компиляции, а модульная организация .NET позволяет гарантировать, что используемый модуль имеет ту же реализацию.
Здравствуйте, stalcer, Вы писали:
Д>>Это некритично. Если народ мирится со скоростью работы приплюснутого препроцессора, то уж лишние перекомпиляции в .NET точно переживет.
S>Народ не мирится, а извращается. Так вот, например:
S>
Идиома PImpl применяется не столько для уменьшения времени компиляции, сколько для обеспечения безопасности в случае исключений. Для сложных классов PImpl может быть единственным образом реализовать строгую гарантию безопасности для оператора копирования.
А сократить время компиляции можно, например, и так:
class MySuperClass
{
public :
virtual ~MySuperClass();
virtual void myVeryComplexFunction(...) = 0;
};
std::auto_ptr< MySuperClass > createMySuperClassImpl();
// Где-то в реализации.class MySuperClassImpl : public MySuperClass
{
...
};
std::auto_ptr< MySuperClass > createMySuperClassImpl()
{
return std::auto_ptr< MySuperClass >( new MySuperClassImpl );
}
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Что если один модуль импортирует другой, а тот, в свою очередь, импортирует третий модуль, причем так, что первый модуль неявно его использует. В дотнете, оказывается надо добавить в список ссылок сборки и тот модуль тоже! Иначе получим вот такую ругань от компилятора:
СГ>***.dll Referenced class '***' has base class or interface '***' defined in an assembly that is not referenced. You must add a reference to assembly '***'.
СГ>То есть в дотнете в список импортируемых модулей должны быть включены все нужные модули, затем все модули нужные нужным модулям и рекурсивно так далее.
Сборка A. Компилируется.
Сборка B, использует A. Добавляю референс на A. Компилируется.
Сборка C, использует B (неявно использует A). Добавляю референс на B (не добавляю референс на A). Компилируется.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>[..] Я недоумевал почему в дотнете с этим делом все так плохо, в то время как в оберонах с этим же делом все обстоит хорошо. [..]
Ну, "хорошо" — это ещё как посмотреть.
СГ>Уникальный идентификатор версии объекта[...]
Как же, проходили мы этот уникальный идентификатор для объекта. Помнится, называется эта модульная, неимоверно удобная среда COM. Сам по себе уникальный идентификатор версии объекта или сборки — эта выбор гранулярности метаинформации. Выше гранулярность — больше возможностей у среды исполнения. Но удобство программиста определяется не возможностями среды исполнения, а их реализацией. СГ>Цепочка импорта
Не надо путать людей: СГ>Что если один модуль импортирует другой, а тот, в свою очередь, импортирует третий модуль, причем так, что первый модуль неявно его использует. В дотнете, оказывается надо добавить в список ссылок сборки и тот модуль тоже!
И в оберонах тот же принцип — используете объекты, значит, надо добавлять ссылки, а, если, использования нет, то добавлять необязательно. Просто, в .NET'е наследование (в том числе непрямое) означает использование. В качестве примера отсутсвия использований прицепите к пустой сборке любой набор assembly. Все замечательно скомпилируется, никаких ошибок про неправильные ссылки.
СГ>То есть в дотнете в список импортируемых модулей должны быть включены все нужные модули, затем все модули нужные нужным модулям и рекурсивно так далее.
Неверно, необходимость добавления ссылок на сборку определяется наличием использования. СГ>Ни откуда не следует, что размер символьных файлов по ходу цепочки будет становится все больше и больше. Ничего подобного, он может, наоборот, становится все меньше и меньше.
Действительно, может, как и в .NET'е. Вот, только, я пока не видел на .NET'е проекты с тысячей assembly, а использовать тысячу объектов из библиотек в обероновском модуле — в это ещё могу поверить. СГ>На самом деле символьные файлы на столько малы, что как было замечено Мёсенбёком, зачастую читаются с диска всего одной операцией чтения.
А для .NET, надо полагать, стандартные пара десятков ссылок на assembly будут читаться дольше? Не верю. Равно как и в то, что время чтения ссылок вообще существенно для чего-либо. Думаю, что resolve ссылок (и в .NET и в оберонах) обычно требует больше дисковых операций.
Резюме: Уникальный идентификатор версии объекта хорошо, но недостаточно, чтобы в оберонах было лучше, чем в .NET'е. Цепочки — не согласен.
Здравствуйте, Дарней, Вы писали:
Д>MD5 — это тоже часть основного алгоритма цифровой подписи. И хотя хэш-функция может быть одинаковой для разных документов, это никому не мешает.
Если найдена хоть одна коллизия алгоритма хеширования, то ещё как мешает. MD5 уже лет семь как объявлена устаревшей.
А вот гос. стандарт США SHA-1, в которой ещё ни одной коллизии не найдено, но доказано что за 2^69 операций коллизию найти можно (сложнее чем коллизию MD5 = 2^64) и вот уже объявлен конкурс на создание нового стандарта по типу AES ... Опасно.
Шнаер в своём блоге описывал недавно прецедент в Австралийском суде по поводу MD5 — http://www.schneier.com/blog/archives/2005/08/the_md5_defense.html
Здравствуйте, Sergey J. A., Вы писали:
СГ>>***.dll Referenced class '***' has base class or interface '***' defined in an assembly that is not referenced. You must add a reference to assembly '***'.
СГ>>То есть в дотнете в список импортируемых модулей должны быть включены все нужные модули, затем все модули нужные нужным модулям и рекурсивно так далее.
SJA>Сборка A. Компилируется. SJA>Сборка B, использует A. Добавляю референс на A. Компилируется. SJA>Сборка C, использует B (неявно использует A). Добавляю референс на B (не добавляю референс на A). Компилируется. SJA>Что я не так делаю ?
Перечитаем внимательно сообщение:
***.dll Referenced class '***' has base class or interface '***' defined in an assembly that is not referenced. You must add a reference to assembly '***'.
В модуле В должен быть класс потомок класса определенного в модуле А или же реализующий интерфейс определенный в модуле А.
Здравствуйте, andyJB, Вы писали:
JB>Не надо путать людей:
Я людей не путаю. Перечитайте, указанную мной статью, там все понятно написано.
JB>Резюме: Уникальный идентификатор версии объекта хорошо, но недостаточно, чтобы в оберонах было лучше, чем в .NET'е.
В оберонах finger-print-ы имет каждый экспортируемый модулем объект (каждая константа, каждый тип и т.п.), в дотнете finger-print имеет только сам модуль целиком. Ну и разьве это не лучше? Это определённо (даже ультимативно!) лучше.
JB>Цепочки — не согласен.
Здравствуйте, Сергей Губанов, Вы писали:
JB>>Резюме: Уникальный идентификатор версии объекта хорошо, но недостаточно, чтобы в оберонах было лучше, чем в .NET'е.
СГ>В оберонах finger-print-ы имет каждый экспортируемый модулем объект (каждая константа, каждый тип и т.п.), в дотнете finger-print имеет только сам модуль целиком. Ну и разьве это не лучше? Это определённо (даже ультимативно!) лучше.
У меня есть маленькое такое замечание — в .NET строгое имя сборки определяется такими параметрами, как: собственно текстовым именем сборки (например, System.Data), версией сборки, локалью, публичным ключом и хэшем сборки, подписанным приватным ключом изготовителя сборки. В общем-то, "идентификатор" (строгое имя) сборки получается вещью более уникальной, чем Обероновский finger-print (контрольная сумма? судя по тому, что я прочитал).
В голову приходит простая аналогия: я могу залепить все запчасти своей машины (колёса, руль, дворники и т.д.) жвачкой, в надежде что её не удастся угнать, а могу поставить хорошую противоугонную систему (строгое имя) и застраховать тачку (подпись). Какой из этих двух вариантов "ультимативно лучше"?
Здравствуйте, Дарней, Вы писали:
Д>Здравствуйте, Сергей Губанов, Вы писали:
СГ>>Это определённо (даже ультимативно!) лучше.
Д>ЧЕМ лучше?
Лучше — это когда как можно меньше модулей становятся негодными (подлежат перекомпиляции) при внесении изменений в импортируемый модуль.
Я привел простой пример с модулем из которого экспортировались две константы. При изменении только одной из них перекомпиляции подлежат только те модули, которые ее использовали. Модули использовавшие другую (не изменившуюся) константу перекомпилировать не нужно. В дотнете при изменении константы надо будет сменить версию модуля на другую, это приведет к инвалидации всех модулей-клиентов, в результате надо будет перекомпилировать все модули включая те, которые даже не использовали изменившуюся константу.
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Лучше — это когда как можно меньше модулей становятся негодными (подлежат перекомпиляции) при внесении изменений в импортируемый модуль.
Расплатой за что является на порядок возросшая работа при загрузке программы в память. Сравни — как часто обычный пользователь программы компилирует, и как часто — запускает?
При этом, обрати внимание — гарантируется совместимость только на уровне интерфейсов, но не на уровне реализации.
СГ>Я привел простой пример с модулем из которого экспортировались две константы. При изменении только одной из них перекомпиляции подлежат только те модули, которые ее использовали. Модули использовавшие другую (не изменившуюся) константу перекомпилировать не нужно. В дотнете при изменении константы надо будет сменить версию модуля на другую, это приведет к инвалидации всех модулей-клиентов, в результате надо будет перекомпилировать все модули включая те, которые даже не использовали изменившуюся константу.
А насколько часто возникает необходимость изменить в модуле одну-единственную константу? (я уж не говорю о том, что куда уместнее использовать для хранения параметров файлы конфигурации)
Здравствуйте, stalcer, Вы писали:
S>Ню ню. Это не составит и пяти процентов от того, что делает VM при загрузке программы/модуля.
S>И вообще. Формат файлов ассемблей в .Net вообще не заточен под быструю загрузку. Скорее они старались их сделать как можно более компактными.
При всем этом, увеличивать затраты без соответствующих выгод смысла нет. И где же они (выгоды, в смысле)? Возможность использовать сборки с константами вместо файлов конфигурации?
Здравствуйте, Дарней, Вы писали:
Д>При всем этом, увеличивать затраты без соответствующих выгод смысла нет. И где же они (выгоды, в смысле)? Возможность использовать сборки с константами вместо файлов конфигурации?
Ты что же, правда не понимаешь разницу между константами и параметрами, которые следует выносить в файлы конфигурации?
Здравствуйте, stalcer, Вы писали:
S>Ты что же, правда не понимаешь разницу между константами и параметрами, которые следует выносить в файлы конфигурации?
Обсуждаемый здесь вопрос может и не так критичен для обыкновенных программ, разрабатываемых на дот нете, например. Но есть другой класс систем. Например, возьмем Oracle с его встроенным PL/SQL. На этом языке можно писать хранимые процедуры и так называемые модули (наборы объявлений и процедур). Все это хранится в базе данных, Oracle отслеживает зависимости между процедурами/модулями. При изменении какого-либо объекта Oracle инвалидирует, а затем перекомпилирует его и зависимые от него объекты.
Так вот, во-первых, более мелкая гранулярность с точки зрения зависимостей могла бы в некоторых слуаях предотвратить циклические зависимости. Понятно, что если несколько модулей связаны циклической зависимостью, то перекомпилировать их можно только все вместе. А на это необходимо, как минимум, большое количество памяти на сервере (где и происходит перекомпиляция в случае Oracle). А разбивать на "правильные" модули систему никто не будет, потому что, бизнес логику пишут прикладники, которые хотят работать в высокоуровневой среде, которая не заставляет их заниматься всякой фигней.
Во-вторых, часто бывает, что изменения (обычно небольшие) необходимо внести прямо сейчас, т.е. в работающую систему. Oracle, естественно, не нужно останавливать, чтобы изменить хранимую процедуру. Поэтому, при запуске процедуры блокируются. Ну и естественно заблокированную процедуру изменить нельзя. Но также нельзя изменить и другие процедуры, от которых зависит запущенная. Поэтому, чем меньше зависимостей, тем больше шанс того, что мы сумеем сделать необходимые изменения без выгоняния пользователей из системы.
Но, Oracle, это СУБД, и в нем обычно не пишут много логики. А вот если перенести аналогию на сервер приложений...