Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Базарная площадь
  
О разделе

Основная страница

Группы обсуждений


Тематический каталог обсуждений

Архив

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  07:38[Войти] | [Зарегистрироваться]
Обсуждение темы:
Вопросы оптимизации кода

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

Количество сообщений на странице

Порядок сортировки сообщений
Новое сообщение вверху списка (сетевая хронология)
Первое сообщение вверху списка (обычная хронология)

Перейти на конкретную страницу по номеру


Всего в теме 737 сообщений

Добавить свое сообщение

Отслеживать это обсуждение


Смотрите также обсуждения:
Тестирование проекта. Отладка.
  • Подводные камни
  • Централизованная обработка ошибок
  • Бета-тестирование
  • Давайте учиться на ошибках.
  • Почему программисты допускают ошибки?
  • Автоматизированные тесты для GUI
  • О системах контроля ошибок

  • <<<... | 537—488 | 487—438 | 437—388 | ...>>>
    Всего сообщений в теме: 737; страниц: 15; текущая страница: 6


    № 487   28-02-2009 14:30 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 485« (Jack Of Shadows)
    ___________________________

    >>> Азы функционального программирования для императивщиков ?

    А причём тут функц... А, это вы, Jack...


    № 486   28-02-2009 13:38 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 485« (Jack Of Shadows)
    ___________________________
    И так хорошо. Да!
     Cep


    № 485   28-02-2009 11:54 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 484« (Бел Амор)
    ___________________________
    Азы функционального программирования для императивщиков ?
    Можно продолжить:

    Надо писать не


    if x > 5 then
      y := DownloadFromFTP()
    else
      y := ReadFromDatabase();


    а


    y := if x > 5 then DownloadFromFTP else ReadFromDatabase;


    Ах черт, не получается. В императивных языках if это оператор а не выражение. Он не возврашает значение.
    Ну хорошо, напишем свою функцию iif :


    y := iif( x > 5, DownloadFromFTP(), ReadFromDatabase());


    Тьфу, тоже не получается. В императивных языках обе функции DownloadFromFTP() и ReadFromDatabase() будут исполнены до вызова функции iif.

    Да ну и черт с ним, с этими "оптимизациями". И так хорошо.



    № 484   28-02-2009 11:37 Ответить на это сообщение Ответить на это сообщение с цитированием
    Появилось желание сказать несколько слов по поводу оптимизации логических выражений...

    1. При проверке условия не следует сравнивать что-либо с True или False, поскольку то, что с ними можно сравнить, уже само по себе имеет логический тип:

      if Something = True then

      // Следует заменить на

      if Something then

      if Something = False then

      // Следует заменить на

      if not Something then

    2. Не следует явнным образом присваивать чему-либо значения True или False, поскольку само условие является логическим выражением и его значение можно напрямую присваивать, вообще исключив оператор if

      if a = b then
        Result := True
      else
        Result := False;

      // Следует заменить на

      Result := (a = b);

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

      mr := ShowModal;
      if mr = mrOk then
        Result := True
      else
        Result := False;

      // Или

      ShowModal;
      Result := (ModalResult = mrOk); 

      // Следует заменить на

      Result := (ShowModal = mrOk);

    4. Следует максимально использовать ранее полученные результаты проверки при обработке сложных условий:

    function SomethingCheckAndFix: Boolean;
    begin
      if SomethingIsOk then
        Result := True
      else
        if MsgBoxYesNo('Исправить?') then
          Result := FixSomething
        else
          Result := False;
    end;

    // Оптимизация за счёт использования ранее полученного значения Result,
    // которое используется:
    // 1. При проверке в 1-м if
    // 2. При отказе от исправления во 2-м if (как возвращаемый результат)

    function SomethingCheckAndFix: Boolean;
    begin
      Result := SomethingIsOk;
      if not Result then
        if MsgBoxYesNo('Исправить?') then
          Result := FixSomething;
    end;



    № 483   21-11-2008 13:59 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 482« (Mirage)
    ___________________________
    при желании, можно и больше Вот ведь! А я то и не догадался!! Оказывается всё дело в недостатке желания!!! :)
     Cep


    № 482   21-11-2008 13:15 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 481« (Cepгей Poщин)
    ___________________________

    Не знаю что за TMultiThreadFor, но, при желании, можно и больше 1.4 получить. Почти x2.
    Ну а для, видимо, автоматического распараллеливания цикла и 1.4 неплохо. Хотя думаю на разных циклах по-разному будет.


    № 481   21-11-2008 03:52 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 480« (Mirage)
    ___________________________
    Когдато слышал, что при распараллеливании ускорение пропорционально корню из количества процессоров. 1,4 похоже на то. Кто-нибудь на 4 ядрёном запускал?
     Cep


    № 480   21-11-2008 03:22 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 476« (Cepгей Poщин)
    ___________________________

    результат получается на двухядерном процессоре ускорение не 2, а 1.4 раза. Интересно, какие могут быть причины?

    А кто обещал в два раза? Хотя, если потоки не ждут друг друга, то 1.4 тоже не слишком хороший результат.


    № 479   18-11-2008 06:02 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 478« (Cepгей Poщин)
    ___________________________
    Скорее всего потоки создаются и умирают слишком часто. Число потоков не обязательно должно быть равно числу процессоров, так как накладные расходы на ручную диспетчеризацию могут превысить расходы на диспетчеризацию системой. Task Manager не показывает, потому что это нагрузка ядра, Process Explorer Руссиновича скорее всего показал бы загрузку DPC - Deffered Procedure Calls, механизм отложенных вызовов ядра, по сути потоки ядра, выполняющиеся в контексте обработчика потоков, на равне с потоками приложений.


    № 478   18-11-2008 05:15 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 477« (panda)
    ___________________________
    Загрузка обоих ядер по 100%. Про расходы на синхронизацию, трудно сказать, но, если выполнять не в двух потоках а в 100, то время выполнения почти не увеличивается. Возникает чувство, что одно из ядер постоянно чемто занято, а Task Manager об этом стыдливо умалчивает :( Любопытно было бы узнать как будет работать приложение у других, у кого более двух ядер. См. также описание
     Cep


    № 477   18-11-2008 02:57 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 476« (Cepгей Poщин)
    ___________________________

    Интересно, какие могут быть причины?
    Накладные расходы. Например, на синхронизацию.
    Или другой вариант: не получается загрузить именно процессор. Посмотрите графики загрузки по ядрам во время тестирования.


    № 476   18-11-2008 01:46 Ответить на это сообщение Ответить на это сообщение с цитированием
    По поводу распараллеливания »сообщение 570 в теме №389 на БП«. Странный результат получается на двухядерном процессоре ускорение не 2, а 1.4 раза. Интересно, какие могут быть причины?
     Cep


    № 475   19-06-2008 05:25 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 474« (panda)
    ___________________________

    Подобный подход, кстати, описан в статье Анатолия Тенцера Использование Microsoft ScriptControl

    Да, только там свойства то устанавливаются по имени через RTTI, а методы обрабатываются явным анализом имени и параметров (if CompareText(S, 'CONTROLS') = 0 и подобное), а здесь как-бы "Invoke в Invoke-е" и для свойств, и для методов.
     Ins


    № 474   18-06-2008 23:32 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 473« (Ins)
    ___________________________

    Спасибо, интересная идея. Подобный подход, кстати, описан в статье Анатолия Тенцера Использование Microsoft ScriptControl


    № 473   18-06-2008 11:08 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 472« (panda)
    ___________________________

    Ответ на »сообщение 471« (Ins)
    ___________________________

    Огромный case, или обращение к RTTI? Если первое, то очевидно остутствие гибкости и сложности при развитии проекта, если второе - то не во всех языках есть рефлексия :)
    Я бы сделал RTTI - это, на мой взгляд, наименьшее зло в данной ситуации.
    Понятно, что решение будет не абсолютно универсальным, но это хоть что-то.


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

    unit Unit1;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;

    type
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;

      {$METHODINFO ON}
      TRectangle = class(TObject)
      private
        FWidth: Integer;
        procedure SetWidth(const Value: Integer);
      published
        property Width: Integer read FWidth write SetWidth;
      end;

      TPolyline = class(TObject)
      public  // Даже не обязательно published, можно public
        procedure AddVertex(X, Y: Integer);
      end;
      {$METHODINFO OFF}

    var
      Form1: TForm1;

    implementation

    uses ObjComAuto;

    {$R *.dfm}

    function InstanceToVariant(Instance: TObject): Variant;
    begin
      Result := TObjectDispatch.Create(Instance, True) as IDispatch;
    end;

    { TForm1 }

    procedure TForm1.FormCreate(Sender: TObject);
    var
      V: Variant;
    begin
      V := InstanceToVariant(TPolyline.Create);
      V.AddVertex(10, 50);
      V := InstanceToVariant(TRectangle.Create);
      V.Width := 200;
      V.AddVertex(10, 50);  // А здесь ловим исключение
    end;

    { TRectangle }

    procedure TRectangle.SetWidth(const Value: Integer);
    begin
      ShowMessageFmt('SetWidth, Value = %d', [Value]);
    end;

    { TPolyline }

    procedure TPolyline.AddVertex(X, Y: Integer);
    begin
      ShowMessageFmt('AddVertex, X = %d; Y = %d', [X, Y]);
    end;

    end.

     Ins


    № 472   06-06-2008 22:33 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 471« (Ins)
    ___________________________

    Огромный case, или обращение к RTTI? Если первое, то очевидно остутствие гибкости и сложности при развитии проекта, если второе - то не во всех языках есть рефлексия :)
    Я бы сделал RTTI - это, на мой взгляд, наименьшее зло в данной ситуации.
    Понятно, что решение будет не абсолютно универсальным, но это хоть что-то.


    № 471   06-06-2008 08:46 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 470« (panda)
    ___________________________
    Андрей, оно то в принципе можно, но интересна именно реализация методов Invoke, GetIDsOfNames. Что будет представлять собой их код? Огромный case, или обращение к RTTI? Если первое, то очевидно остутствие гибкости и сложности при развитии проекта, если второе - то не во всех языках есть рефлексия :)
     Ins


    № 470   06-06-2008 08:08 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 469« (Ins)
    ___________________________

    Ну а кто и как этот интерфейс реализует?
    Тот же, кто по вашему должен был реализовать методы с директивой message.


    № 469   06-06-2008 06:55 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 468« (panda)
    ___________________________

    Ответ на »сообщение 467« (Ins)
    ___________________________

    А клиент будет обращаться к объектам только через Dispatch (ну или свой метод SendCommand(CmdID, Params), внутри которого просто Dispatch вызывать). По-моему так лучше :)
    Э... А нельзя уж тогда нормальный IDispatch использовать?


    Ну а кто и как этот интерфейс реализует?
     Ins


    № 468   06-06-2008 06:43 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 467« (Ins)
    ___________________________

    А клиент будет обращаться к объектам только через Dispatch (ну или свой метод SendCommand(CmdID, Params), внутри которого просто Dispatch вызывать). По-моему так лучше :)
    Э... А нельзя уж тогда нормальный IDispatch использовать?


    № 467   06-06-2008 04:43 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 466« (panda)
    ___________________________
    Но здесь я этого не увидел (всё было только на уровне: "А вот лично мне больше нравится так").

    Давайте возьмем паттерн Composite. Его очевидными недостатками является тот факт, что в его классической реализации мы обязаны выбирать одно из двух зол: либо у разных классов делать разные интерфейсы, теряя тем самым прозрачность использования клиентом (клиент вынужден будет прибегать к даункастам), либо искусственно расширять интерфейс у всех классов до наименьшего общего знаменателя, что на мой взгляд не менее криво - любопытно видеть в интерфейсе класса TRectangle метод AddVertex только потому, что этот метод нужен классу TPolyline :)
    А в Delphi можно решить эту проблему на мой взгляд более элегантно с помощью методов TObject.Dispatch и TObject.DefaultHandler. В нужных классах пишем необходимое число методов-обработчиков с директивой message и при необходимости перекрываем DefaultHandler, который будет либо кидать исключение, либо возвращать какой-нибудь статус. А клиент будет обращаться к объектам только через Dispatch (ну или свой метод SendCommand(CmdID, Params), внутри которого просто Dispatch вызывать). По-моему так лучше :)
     Ins


    № 466   06-06-2008 04:15 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 465« (Mirage)
    ___________________________

    Я это уже понял. Не понял правда зачем вам Delphi, если писать в стиле C#, не используя языка на 100%. По идее лучше сразу на C#.
    Чтобы потом было "легко" переписать 100К строчек кода?

    Я, в частности, занимаюсь консультациями и обучением программистов, использующих разные ЯП. И потому, если одинаковые по смыслу решения будут близки и в детальной архитектуре - мне проще будет это всем объяснить. Разумеется, если универсальное решение будет обладать какими-то существенными недостатками - придется от него отказаться. Но здесь я этого не увидел (всё было только на уровне: "А вот лично мне больше нравится так").


    № 465   06-06-2008 04:04 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 451« (Ins)
    ___________________________

    В случае классов я прекрасно представляю себе реализацию данной идеи. А как быть с синглтоном в модуле? Модуль будет экспортировать кучу переменных, процедур и типов, которые не нужны клиенту, а нужны лишь для привязки к конкретному хранилищу? А как же инкапсуляция? Или это для Вас пустой звук? Безусловно можно программировать и без классов, инкапсуляции, наследования, полиморфизма, но для этого есть другие более подходящие языки.

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

    Ответ на »сообщение 452« (panda)
    ___________________________

    Почитайте предыдущие посты. Если Вам нужно уникальное для Delphi решение - делайте, я не собираюсь с Вами спорить (а мне нужен другой подход).

    Я это уже понял. Не понял правда зачем вам Delphi, если писать в стиле C#, не используя языка на 100%. По идее лучше сразу на C#.
    Чтобы потом было "легко" переписать 100К строчек кода?


    № 464   05-06-2008 08:48 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 463« (Слава)
    ___________________________
    В использовании функций
    class function TFormX.EditObject(Obj: TObjectX): Boolean;
    function EditObjectX(Obj: TObjectX): Boolean;
    действительно нет никакой разницы.


    Вообще разница между классовыми методами и функциями/процедурами есть, и заключается она в неявном параметре, ссылке на класс, для которого метод выполняется, который играет двойную роль:
    1. Внутри метода - передается внутрь функции как неявный параметр и может быть использован - Self
    2. Снаружи метода - если метод виртуальный, то используется для получения действительного адреса вызова из VMT
     Ins


    № 463   05-06-2008 08:42 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 454« (Антон Григорьев)
    ___________________________

    Ответ на »сообщение 453« (Слава)
    ___________________________

    Функции из разных групп используют друг-друга. Разделить можно, создав иерархию модулей, но тогда функции входящие по смыслу в одну группу окажутся в 20 разных файлах. Абсурд получится, согласны?!

    По-моему, вы сами себе противоречите. Если функции в принципе делятся на группы, то не вижу причин не оформить это разделение в виде модулей. А если в принципе не делятся, то они и пространством имён, и классами тоже не разделятся.


    Они делятся на группы по смыслу.
    И эти группы не совпадают с иерархией зависимости друг от друга.

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

    В использовании функций
    class function TFormX.EditObject(Obj: TObjectX): Boolean;
    function EditObjectX(Obj: TObjectX): Boolean;
    действительно нет никакой разницы.

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


    № 462   05-06-2008 07:14 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 461« (Мухтар )
    ___________________________
    Если я Вас правильно понял, ваша первая сегодняшняя реакция связана не с программированием вообще, а лежит в области психологии и личностных качеств. Я прав?

    Нет. Мой первый сегодняшний комментарий относился к использованию классов для структурирования идентификаторов функций библиотеки, при проектировании которой ОО-подход не использовался и понятие "класс" было введено искуственно. Тут больше подошло бы понятие "namespace", роль которого в Delphi в том числе выполняет модуль.

    я их не понял и не могу сейчас (нет времени и мыслей)

    Вы не ответили на вопрос :) О чем вообще речь? Понимаете, я не могу ничего сказать пока не понимаю, что именно от меня хотят. Ну а если и Вы не поняли моих слов, так как поздно включились в обсуждение, не собираетесь понимать и теперь, то почему же в такой требовательной форме (Ну? :-)) побуждаете меня делать какие-либо комментарии?
     Ins


    № 461   05-06-2008 06:48 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 460« (Ins)
    ___________________________

    >>>Уважаемый, если Ваши вопросы не являются риторическими и Вы действительно хотите чтобы я ответил на них,

    Насчет уважаемый, у меня есть небезоснавательные сомнения (я не про Вас, а вообще). Данные вопросы возникли не на пустом месте, а привязаны к моей работе.

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

    Во-первых, формат форума не позволяет мне создать свою тему. Во-вторых, буду признателен за ссылки на форумы с умными людьми по вопросам программирования и удобным форумным движком, а не таким как на rsdn.ru, например. В третьих, я немного выпал (неуследил) за осбуждением данной ветки, и попасть в русло сложно. В четвертых, логический шаг (в контексте программирования) - недостатки языка и компилятора, и как эти проблемы можно побороть. Прошу воспринимать все буквально "как есть", без негативной подоплеки в сторону участников дискуссии.

    >>>1. С какой высказанной ранее позицией Вы не согласны

    я их не понял и не могу сейчас (нет времени и мыслей)

    >>>2. Как обстоит дело на ваш взгляд

    плохо

    >>>И просьба при ответе на первый вопрос обратить внимание на контекст, в котором она прозвучала.

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

    >>>А то как говорит Geo, "любое самое умное высказывание можно довести до абсурда, подходя к нему как к догме
    Про догму не понял. Не понял в каком контексте и к чему привязывать Вашу фразу.


    № 460   05-06-2008 06:17 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 458« (Мухтар )
    ___________________________
    Уважаемый, если Ваши вопросы не являются риторическими и Вы действительно хотите чтобы я ответил на них, давайте будем последовательны, избегать перепрыгивания на другие темы, между которыми есть как минимум несколько логических шагов, возможно очевидных для Вас, но не очевидных для других и меня в частности. Давайте по пунктам:
    1. С какой высказанной ранее позицией Вы не согласны
    2. Как обстоит дело на ваш взгляд
    И просьба при ответе на первый вопрос обратить внимание на контекст, в котором она прозвучала. А то как говорит Geo, "любое самое умное высказывание можно довести до абсурда, подходя к нему как к догме"
     Ins


    № 459   05-06-2008 06:10 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 458« (Мухтар )
    ___________________________

    И как это согласуется вот с этим?
    http://ru.wikipedia.org/wiki/Разработка_через_тестирование


    Прекрасно согласуется. А у Вас с этим какие-то сложности? ;-)


    № 458   05-06-2008 05:58 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 457« (Ins)
    ___________________________
    И как это согласуется вот с этим?
    http://ru.wikipedia.org/wiki/Разработка_через_тестирование


    № 457   05-06-2008 05:51 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 456« (Мухтар )
    ___________________________
    Юнит-тесты - это тестирование классов (т.е. кода) или объектов (т.е. поведенческих сущностей без отрыва от всей системы)?

    Объектов. А дальше из вашего сообщения лично мне неясна ни суть вопросов, ни отношение их к контексту обсуждения :)

     Ins


    № 456   05-06-2008 05:25 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 455« (Ins)
    ___________________________
    Ins, у меня к вам вопрос. Юнит-тесты - это тестирование классов (т.е. кода) или объектов (т.е. поведенческих сущностей без отрыва от всей системы)?

    1) Объекты: Как тестировать объекты - понятно. Проектируем свой класс из расчета на тестирование объектов и, например, в testable конструкторе передаем свои dummy реализации других объектов.

    Но правильно ли это? Проще - несомненно. Но качественнее ли?

    2) Классы: Как тестировать - неясно. Если тестировать классы, т.е. файлы кода, то нужно позаботиться об создании вместо базовых классов своих dummy заглушек. А как это сделать, не меняя код самого файла с классом?

    Т.е. второй вопрос (после того, как вы мне скажите, какой из 2-ух подходов лучше) написан в пункте 2.

    Хотелось бы услышать рекомендации по поводу организации парадигм ООП (наследование, инкапсуляция, полиморфизм) из расчета на подмену кода базовых классов на свой для тестирования.

    Ну? :-)


    № 455   05-06-2008 04:00 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 453« (Слава)
    ___________________________
    Потрясающий пример использования вещей не по назначению :) ООП - это инкапсуляция + наследование + полиморфизм, а в Вашем случае ООП - это что?

    Разделить этот модуль в 20 000 строк на несколько маленьких идея не удачная. Функции из разных групп используют друг-друга.

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


    № 454   04-06-2008 23:44 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 453« (Слава)
    ___________________________

    Функции из разных групп используют друг-друга. Разделить можно, создав иерархию модулей, но тогда функции входящие по смыслу в одну группу окажутся в 20 разных файлах. Абсурд получится, согласны?!

    По-моему, вы сами себе противоречите. Если функции в принципе делятся на группы, то не вижу причин не оформить это разделение в виде модулей. А если в принципе не делятся, то они и пространством имён, и классами тоже не разделятся.


    № 453   04-06-2008 14:21 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 430« (Антон Григорьев)
    ___________________________

    Ответ на »сообщение 429« (Бел Амор)
    ___________________________

    Это всё - следствие того влияния, которое оказвют на программирование неряшливы спроектированные C++ и C#. Там действительно класс нагружен совершенно несвойственной ему функцией - быть пространством имён.
    ...
    Во-во, именно это я и имел ввиду, когда говорил о том, что классу придают несвойственные ему функции пространства имён. Вообще, всё это следствие моды на ООП, всё засунуть в объекты - это типа хорошо (Java и C# - жертвы такой моды). Между тем, процедурное программирование тоже имеет свои сильные стороны, и надо не фанатично держаться за один подход, а в зависимости от ситуации использовать то или это.

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

    У меня, например, в "геометрическом" модуле СОТНИ функций.
    Их надо как-то группировать.
    Разделить этот модуль в 20 000 строк на несколько маленьких идея не удачная. Функции из разных групп используют друг-друга. Разделить можно, создав иерархию модулей, но тогда функции входящие по смыслу в одну группу окажутся в 20 разных файлах. Абсурд получится, согласны?!

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

    Спустя несколько лет создал пустые классы, состоящие из класс-функций (использую Delphi 7).
    Таких классов получилось десятка три с 10-50 класс-функциями в каждом.

    А запись
    if FloatRect.Intersecting(R1, R2) then
    выглядит лучше чем
    if FloatRect_Intersecting(R1, R2) then
    поскольку при большом числе функций избежать NameSpace-ов или длинных имен не удается.

    Зато теперь набрав FloatRect. я вижу в выпадающем списке то, что мне надо.
    И достаточно помнить имена только 30 классов, а не имена 300-500 функций.

    Я не пожалел скорости в модуле геометрии!
    Буду ли я жалеть ее в другом месте?

    В Delphi7 нет NameSpace-ов, но если бы они были, то структуру модуля я бы менять не стал.
    Обозвал бы методы static вместо class function и все.

    Просто есть приложения которые на 99% состоят из диалоговых и обычных форм.
    Но есть и другие приложения в которых совершенно иные заботы и приоритеты.
    И если вы не писали подобных проектов, то ваши философствования будут серьезно удалены от жизни.


    № 452   03-06-2008 08:06 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 450« (Mirage)
    ___________________________

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

    В принципе, придумыванием разных странных задач можно использование чего угодно оправдать. А проблемы будут уже у того, кто будет это сопровождать.:)
    Если у меня возникает задача, решение которой известно и хорошо задокументировано, то почему она странная? Только потому, что Вам лично не нравится? Первый же пример в http://en.wikipedia.org/wiki/Factory_method показывает использование фабричного метода БЕЗ фабрики.

    Причем тут Oberon? В Delphi модульность пока, слава богу, не отменили.
    Почитайте предыдущие посты. Если Вам нужно уникальное для Delphi решение - делайте, я не собираюсь с Вами спорить (а мне нужен другой подход).


    № 451   03-06-2008 06:23 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 450« (Mirage)
    ___________________________
    Если синглтон у нас модуль, то наследовать нечего - поведение одиночки у модулей само по себе. Или Вы знаете как создать экземпляр модуля? :)
    Что касается "наследования" другого поведения, то можно создать новый модуль, использующий "наследуемый". Никаких проблем.


    Берем задачу. Я хочу описать некую абстрактную сущность, которая представляет собой древовидную структуру. Узлы - параметры вида "имя=значение". Ветви - списки таких параметров и/или других ветвей. В общем что-то очень напоминающее реестр-Windows, только не привязанную к конкретному хранилищу, и поэтому я далее буду использовать термин "абстрактный реестр" Такой абстрактный реестр мне понадобится в различных проектах для структурированного хранения каких-либо глобальных данных или настроек. Разумеется, экземпляр такого реестра должен быть в приложении один и точка входа - тоже. В каждом конкретном проекте мне хотелось бы породить от него потомка, в котором мне только потребуется привязать такой реестр к конкретному хранилищу, которым может быть некая структура в памяти, в реестре Windows, Ini-файле, XML-файле, базе данных и т.д. Все остальное я хотел бы унаследовать от абстрактного реестра (в т.ч. и поведение синглтона). Также я бы хотел бы иметь полную прозрачность для клиента и возможность полиморфного поведения в зависимости от конкретного типа реестра, для которого один и тот же клиентский код выполняется.
    В случае классов я прекрасно представляю себе реализацию данной идеи. А как быть с синглтоном в модуле? Модуль будет экспортировать кучу переменных, процедур и типов, которые не нужны клиенту, а нужны лишь для привязки к конкретному хранилищу? А как же инкапсуляция? Или это для Вас пустой звук? Безусловно можно программировать и без классов, инкапсуляции, наследования, полиморфизма, но для этого есть другие более подходящие языки.
     Ins


    № 450   03-06-2008 05:50 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 448« (panda)
    ___________________________

    Не фабрика, а фабричный метод без фабрики. В том-то его задача и состоит.

    Т.е., в нашем примере, TApplication еще не создан, но формы уже вовсю создаются.
    В принципе, придумыванием разных странных задач можно использование чего угодно оправдать. А проблемы будут уже у того, кто будет это сопровождать.:)

    Причем я не против классовых методов, просто тут они явно неуместны.
    Сам даже встретился один раз с ситуацией, где были бы полезны классовые поля.:)

    Ага, и при этом лучше использовать Oberon, а не Delphi ;-)


    Причем тут Oberon? В Delphi модульность пока, слава богу, не отменили.

    Ответ на »сообщение 447« (Ins)
    ___________________________

    Модуль тоже может рассматриваться как синглтон, но на мой взгляд - с недостатками :) Синглтон лично мне интересен тогда, когда я могу объявить базовый класс TSingletone, в котором раз и навсегда заложить поведение одиночки, а потом по мере необходимости просто создавать от класса потомков, наследующих поведение, и работа с которыми будет одинаковой и прозрачной для клиентов. Почему именно так? Для того, чтобы не дублировать код синглтона для каждого конкретного случая. Ну-ка, унаследуйте поведение от модуля ;-)

    Если синглтон у нас модуль, то наследовать нечего - поведение одиночки у модулей само по себе. Или Вы знаете как создать экземпляр модуля? :)
    Что касается "наследования" другого поведения, то можно создать новый модуль, использующий "наследуемый". Никаких проблем.

    Единственно, если заранее неизвестно какого класса должен быть синглтон (т.е. какой модуль), то тогда придется классом. Но тогда уже во время инициализации модуля его не создашь, а значит его существования везде, где до него можно дотянуться, не прогарантируешь. Так что такой синглтон смысла особого не имеет - используем обычный класс. :)
    Ну или Оберон - там можно решать какие модули грузить.;)


    № 449   03-06-2008 03:41 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 448« (panda)
    ___________________________
    Что вы и продемонстрировали с блеском ;-)

    Ясно где собака зарыта - разное толкование термина class static ;) Я под этим понимаю методы, которые в последних версиях объявляются с директивой static - т.е. этим метода не нужен Self и кажется они не могут быть виртуальными. И считаю что нужно различать термин "классовый метод" и "статик-метод", по крайней мере в Delphi, где это не одно и то же.
     Ins


    № 448   03-06-2008 03:31 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 447« (Ins)
    ___________________________

    Вы утверждали, что паттерн factory method не реализуется с помощью классовых ссылок и виртуальных конструкторов, и что либо он будет кривым, либо это совсем другой паттерн.
    Не совсем так. Я говорил, что не удастся обойтись одними только виртуальными конструкторами без class methods. Что вы и продемонстрировали с блеском ;-)


    Ответ на »сообщение 446« (Mirage)
    ___________________________

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

    Правда непонятно, почему классовый. Т.е. экземпляров TAncestor еще не существует, а фабрика уже вызывается? Криво как-то.
    Не фабрика, а фабричный метод без фабрики. В том-то его задача и состоит. Другое дело, насколько он будет применим в реальной системе, но возможность эта вполне реальна.

    Что касается синглтонов, то правильно их вообще не использовать. Тем более, что если есть модуль, который собственно и есть синглтон, только без недостатков, то лучше наверное модуль и использовать.
    Ага, и при этом лучше использовать Oberon, а не Delphi ;-)


    № 447   03-06-2008 02:08 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 445« (panda)
    ___________________________

    type
      TAncestor = class;
      TAncestorClass = class of TAncestor;

      TAncestor = class
      protected
        class function GetClassType: TAncestorClass; virtual;
      public
        constructor Create; virtual;
        class function FactoryMethod: TAncestor;
      end;

      TDescendant = class(TAncestor)
      end;

    implementation

    { TAncestor }

    constructor TAncestor.Create;
    begin
      inherited Create;
    end;

    class function TAncestor.FactoryMethod: TAncestor;
    begin
      Result := GetClassType.Create;
    end;

    class function TAncestor.GetClassType: TAncestorClass;
    const
      ClsAr : array[1..7] of TAncestorClass = (TAncestor, TAncestor, TAncestor,
                                              TAncestor, TAncestor, TDescendant,
                                              TDescendant);
    begin
      Result := ClsAr[DayOfTheWeek(Now)];
    end;



    Я вообще что хотел сказать с самого начала. Вы утверждали, что паттерн factory method не реализуется с помощью классовых ссылок и виртуальных конструкторов, и что либо он будет кривым, либо это совсем другой паттерн. Посмотрите на метод TApplication.CreateForm. Если это не фабричный метод, то что тогда? ;-)

    Ответ на »сообщение 446« (Mirage)
    ___________________________
    Что касается синглтонов, то правильно их вообще не использовать. Тем более, что если есть модуль, который собственно и есть синглтон, только без недостатков, то лучше наверное модуль и использовать.

    Модуль тоже может рассматриваться как синглтон, но на мой взгляд - с недостатками :) Синглтон лично мне интересен тогда, когда я могу объявить базовый класс TSingletone, в котором раз и навсегда заложить поведение одиночки, а потом по мере необходимости просто создавать от класса потомков, наследующих поведение, и работа с которыми будет одинаковой и прозрачной для клиентов. Почему именно так? Для того, чтобы не дублировать код синглтона для каждого конкретного случая. Ну-ка, унаследуйте поведение от модуля ;-)
     Ins


    № 446   03-06-2008 01:20 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 443« (panda)
    ___________________________

    В некоторых частных случаях - конечно. В общем я все же стараюсь добиться того, чтобы решение было универсальным.

    Эдакий cross-language код? Занятно.:)

    Ответ на »сообщение 445« (panda)
    ___________________________

    дополнительных классов фабрик будет такой:

    Довольно неприятен на вид. Пусть метод, создающий экземпляр, его создает (раз уж по-вашему тут нужен целый метод), а решать какой именно класс создавать будет решать другой метод. Пусть даже классовый.
    Правда непонятно, почему классовый. Т.е. экземпляров TAncestor еще не существует, а фабрика уже вызывается? Криво как-то.

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


    № 445   02-06-2008 23:58 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 444« (Ins)
    ___________________________

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

    type
      TAncestor = class
      public
        class function FactoryMethod: TAncestor;
      end;

      TDescendant = class(TAncestor)
      end;

    class function TAncestor.FactoryMethod: TAncestor;
    type
      TDays = 1..7;
    const
      Weekend: set of TDays = [6, 7];
    begin
      if DayOfTheWeek(Now) in Weekend then
        Result := TDescendant.Create
      else
        Result := Self.Create;
    end;



    № 444   02-06-2008 07:48 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 443« (panda)
    ___________________________
    Э, нет, так не покатит :-)
    Связка фабрики и фабричного метода так решается идеально. Но что делать, если фабрики нет и фабричный метод располагается в общем предке? Именно здесь мы встречаем проблему ограничения гибкости.


    Давайте на примере, я что-то не улавливаю...
     Ins


    № 443   02-06-2008 07:46 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 442« (Ins)
    ___________________________

    Поверю. Вот только решение, в котором умышленно не используются особенности конкретного языка при реализации паттерна, зачастую уступает решению, в котором особенности языка используются. Поверите на слово? ;-)
    В некоторых частных случаях - конечно. В общем я все же стараюсь добиться того, чтобы решение было универсальным.

    Дано: у класса TApplication есть метод CreateDocument, который должен создавать и возвращать экземпляр конкретного класса документа в зависимости от конкретного класса TApplication.
    Э, нет, так не покатит :-)
    Связка фабрики и фабричного метода так решается идеально. Но что делать, если фабрики нет и фабричный метод располагается в общем предке? Именно здесь мы встречаем проблему ограничения гибкости.


    № 442   02-06-2008 07:03 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 441« (panda)
    ___________________________
    Сделайте public constructor без параметров и сгенерируйте в нем Assert/Exception. Настоящий конструктор будет private/protected и с параметрами.

    Ну, Вы же сами понимате, что такое решение - не от хорошей жизни :)

    Вам привести практически одинаковую реализацию (за исключением мелких аспектов синтаксиса) на C#, Java и Delphi или поверите на слово? ;-)

    Поверю. Вот только решение, в котором умышленно не используются особенности конкретного языка при реализации паттерна, зачастую уступает решению, в котором особенности языка используются. Поверите на слово? ;-)

    Нет. Вы получаете очень и очень ущербный "фабричный метод". По сути, это вообще другой паттерн, хоть и очень близкий к "фабричному методу".

    Давайте на конкретном примере посмотрим, а то действительно "сферические кони в вакууме" представляются трудно. Да вот, прямо из "учебника", чтобы долго не выдумывать :) Дано: у класса TApplication есть метод CreateDocument, который должен создавать и возвращать экземпляр конкретного класса документа в зависимости от конкретного класса TApplication.
    Вот два способа реализации, с использованием классовых ссылок и виртуальных конструкторов. Class static методы умышлено не использую (требования как я понимаю именно такие).
    Реализация номер раз:

    TDocument = class(...)
    public
      constructor Create; virtual;
    end;

    TDocumentClass = class of TDocument;

    TApplication = class(...)
    protected
      // Можно сделать просто function, а можно - class function. В зависимости от задачи может
      // быть удобным то либо другое. Но в любом случае - метод виртуальный.
      function DocumentClass: TDocumentClass; virtual; abstract;
    public
      function CreateDocument: TDocument;
    end;

    function TApplication.CreateDocument: TDocument;
    begin
      Result := DocumentClass.Create;
    end;


    Номер два:

    TDocument = class(...)
    public
      constructor Create; virtual;
    end;

    TDocumentClass = class of TDocument;

    TApplication = class(...)
    public
      function CreateDocument(DocType: TDocumentClass): TDocument;
    end;

    function TApplication.CreateDocument(DocType: TDocumentClass): TDocument;
    begin
      Result := DocType.Create;
    end;


    Во втором случае я имею возможность задавать класс необходимого документа извне. В первом - только изнутри. В зависимости от задачи может понадобится либо то, либо иное поведение. В чем ущербность?
     Ins


    № 441   02-06-2008 06:12 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 439« (Ins)
    ___________________________

    В языках Java, C#, C++ это не требуется, так как поведение синглтона как правило описывается в базовом классе, которое переносится в наследники сразу же самим фактом наследования. Реализуется с помощью статического полиморфизма - шаблоны, дженерики.
    Давайте не будем путать мягкое с теплым. Наследование и generics - это разные сущности. И не надо их перемешивать. Банда Четырех, кстати, умудрилась рассказать об "Одиночке" не применяя не наследования, ни generics.

    В Delphi же нет инструментов для реализации статического полиморфизма.
    Ну это смотря что называть статическим полиморфизмом :-)

    Пользователь класса по прежнему может создать любое количество экземпляров просто вызвав по ошибке конструктор.
    Сделайте public constructor без параметров и сгенерируйте в нем Assert/Exception. Настоящий конструктор будет private/protected и с параметрами.

    Так что говорить о безболезненном переносе реализации паттерна, по моему, неуместно. Это ведь шаблон дизайна, а не шаблон кода. Тут переносимым является лишь мотивация, поведение, но не реализация, которая по любому будет различной на языках с различными идеологиями.
    Вам привести практически одинаковую реализацию (за исключением мелких аспектов синтаксиса) на C#, Java и Delphi или поверите на слово? ;-)
    На Python - конечно, это я погорячился.

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


    Ответ на »сообщение 440« (Ins)
    ___________________________

    Кстати, в Delphi есть еще специфичные для языка реализации паттерна Singletone, построенная на все тех же классовых методах, которые плюс ко всему могут быть и виртуальными. Эта реализация основана на том, что сам класс может рассматриваться как единственный и неповторимый экземпляр, внутреннее состояние которого может быть описано, например, с помощью class var (хотя это не обязательно, есть и другие способы), а доступ к этому состоянию осуществляется через class methods. Гарантирована единственность "экземпляра" и точки доступа к нему.
    А вот здесь соглашусь на 100%. Но опять же с учетом того, что static-поля класса изобретены не в Delphi ;-)


    № 440   02-06-2008 03:40 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 436« (panda)
    ___________________________
    Кстати, в Delphi есть еще специфичные для языка реализации паттерна Singletone, построенная на все тех же классовых методах, которые плюс ко всему могут быть и виртуальными. Эта реализация основана на том, что сам класс может рассматриваться как единственный и неповторимый экземпляр, внутреннее состояние которого может быть описано, например, с помощью class var (хотя это не обязательно, есть и другие способы), а доступ к этому состоянию осуществляется через class methods. Гарантирована единственность "экземпляра" и точки доступа к нему.
     Ins


    № 439   02-06-2008 03:24 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 437« (panda)
    ___________________________
    Если Delphi - единственный возможный язык в вашей организации (или у вас, как индивидуального разработчика), то конечно.
    Просто мне бы хотелось видеть решения, которые без особых усилий можно переписать на C#, Java, Python.


    Т.е. Вы предлагаете реализацию синглтона вроде такой:

    TBar = class(...)
    public
      class function Instance: TBar;
    end;


    Так? А теперь смотрим на недостатки:
    1. Невозможно реализовать такой синглтон раз и навсегда. Если нам потребуется класс TFoo, тоже представляющий синглтон, придется дублировать весь код реализации данного паттерна. В языках Java, C#, C++ это не требуется, так как поведение синглтона как правило описывается в базовом классе, которое переносится в наследники сразу же самим фактом наследования. Реализуется с помощью статического полиморфизма - шаблоны, дженерики. В Delphi же нет инструментов для реализации статического полиморфизма.
    2. Пользователь класса по прежнему может создать любое количество экземпляров просто вызвав по ошибке конструктор. Это конечно можно рассматривать как "фичу", вот только смысл синглтона - гарантия существования только одного экземпляра и единственная точка доступа к нему - теряется полностью.

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

    Только сейчас заметил, что здесь ошибка. Factory Method предполагает, что реальный тип создаваемого объекта определяется внутри метода. А если вы уже вызвали виртуальный конструктор, то все, поздно. Тип объекта жестко определен и поменять его нельзя.

    Опять таки, вы смотрите со стороны реализации, а я - со стороны мотивации. Паттерн "фабричный метод" необходим для того, чтобы пользователь имел возможность инстанцировать экземпляры различных классов через интерфейс базового. В моем случае реализация полностью отвечает требованиям мотивации. Все остальное - вопрос реализации, которая в C++, скажем, просто не может быть такой, так как в C++ нет ни классовых ссылок, ни виртуальных конструкторов.
     Ins


    № 438   02-06-2008 03:08 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 435« (Ins)
    ___________________________

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

    Вы меня убедили... Вместо указания класса слева буду писать комментарий справа:

      with Create(nil) do  // Self - класс

    Чтобы не запутать тех, кто будет читать это потом...

    Ответ на »сообщение 436« (panda)
    ___________________________

    >>> Так вот вас и спрашивают: зачем вам пусть и неявный, но неиспользуемый параметр?

    Ну, вроде бы достигли консенсуса... :)


    <<<... | 537—488 | 487—438 | 437—388 | ...>>>
    Всего сообщений в теме: 737; страниц: 15; текущая страница: 6


    Добавить свое сообщение

    Отслеживать это обсуждение

    Дополнительная навигация:
    Количество сообщений на странице

    Порядок сортировки сообщений
    Новое сообщение вверху списка (сетевая хронология)
    Первое сообщение вверху списка (обычная хронология)

    Перейти на конкретную страницу по номеру
      
    Время на сайте: GMT минус 5 часов

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

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования