мая 13

TList

Последние 2 часа меня мучает один вопрос... Вот код, который обчно пишу я:

type

  TMyClass = class

  private

    FList: TList;

  public

    constructor Create; override;

    destructor Destroy; override;

 

    function Add(AData: TData): Integer;

  end;

 

Т.е., в программе я использую уже не наследник TList, а обертку для TList. В принципе, я понимаю почему так делаю:

1. Нет лишних методов и параметров.

2. Удобный, для меня, вид и код.

3. Что-то еще, уже не помню 🙂

 

В то же время можно все сделать проще:

type

  TMyClass2 = class(TList);

 

Но, во втором случае вижу только один плюс - меньше кода. И один весомый минус - лишние методы, открывающие внутреннее устройство класса, например Count, который часто и не нужен.

 

Может подскажите, какие еще есть плюсы/минусы у обоих подходов?


  1. Мохов Михаил
     Add karma Subtract karma  +2
    Цитировать.

    Хотя это – вопрос риторический, поскольку зависит от конкретной задачи, он мучает многих разработчиков, размышляющих об архитектуре приложения. Думаю, надо обратиться к теории – она даст однозначный ответ на то, как правильно поступить. В первом случае мы видим типичную агрегацию или композицию (к сожалению, в исходном коде не видно реализации), во втором – наследование. А раз так, то в первом случае мы получаем некий класс, в котором есть возможность оперировать стандартным списком указателей, а во втором – класс – список с расширенной функциональностью. Понятно, что если наша задача – реализовать список объектов некого типа, выгоднее использовать наследование. Если же речь идет о моделировании объекта предметной области, играющего не только роль списка, но и другие роли, то следует избрать первый вариант. Можно также для этих целей воспользоваться паттерном «Фасад» или «Посредник». Что же касается плюсов и минусов, то они при правильном выборе подхода очевидны. Чем точнее будет выбрана реализация для моделируемого факта, тем проще будет манипулировать его экземпляром в нашей модели. Наличие дополнительного кода я бы не счел существенным недостатком, потому что количество кода не есть однозначное мерило правильной организации приложения. К тому же, для удобного пользования списком все равно придется перекрывать часть методов и свойств, если планируется использовать нечто отличное от пойнтеров. Но вот, например, сокрытие приватных свойств и методов списка за фасадом враппера, как Вы верно отметили, является, на мой взгляд, гораздо большим преимуществом. В целом, тема списков уже набила оскомину многим дельфи – разработчикам, потому что постоянно приходится писать одно и тоже. Надеюсь, появление дженериков в Win32 как-то решит эту проблему.

    1
  2. Мохов Михаил
     Add karma Subtract karma  +0
    Цитировать.

    PS. Написал, перечитал и ужаснулся. =) Сорри за сумбур.

    2
  3. Nikitos
     Add karma Subtract karma  +0
    Цитировать.

    Класс TList, особенности работы с ним и отличия его реализации в разных версиях Delphi, разобран как раз в книге, которую Вы представили тут 😉 – ночью об этом читал. Цитата оттуда:
    Денни Торп (Denny Thorpe), один из самых толковых разработчиков в отделе научных исследований компании Borland, в своей книге “Разработка компонент Delphi” (Delphi Component Design) [23] сказал следующее:
    “TList – это рабочая лошадка, а не порождающий класс… При необходимости использования списка создайте простой интерфейсный класс (порожденный от TObject, а не от TList), который будет иметь только нужные вам эквиваленты свойств и функций TList, и возвращаемые типы значений функций и параметров методов которого соответствуют типу хранящихся в списке данных. В таком случае интерфейсный класс будет содержать в себе класс TList и использовать его для хранения данных. Реализуйте функции и методы доступа к свойствам этого интерфейсного класса в виде однострочных вызовов соответствующих методов или свойств внутреннего класса TList с применением соответствующих преобразований типов”.

    3
  4. aktuba
     Add karma Subtract karma  --1
    Цитировать.
    Комментарий автора

    Nikitos, я бы советовал аккуратнее относится к этой книге. Там есть много вещей, которые очень устарели.

    4
  5. Nikitos
     Add karma Subtract karma  --1
    Цитировать.

    Ну, там прямо написано, где имеется в виду совсем старые версии Delphi, а где – Delphi 5 или иные. Я пишу на 7 second edition, поэтому для меня почти всё актуально, ведь она не так отличается от 5-ки, как, скажем, 8-ка или последние версии, 2007 например. Хотя спасибо за совет 😉

    5
  6. VicTor
     Add karma Subtract karma  +0
    Цитировать.

    Считаю, что первый вариант таки правильней – поскольку в этом случае TMyClass “автоматически” получается наиболее соответствующим некоторой абстракции предметной области – в нем есть только те методы, которые нужны в работе, и нет остального опубликованного “мусора”, который только сбивает с толку.
    К тому же, вариант с наследованием плох в смысле безопасности использвания, поскольку, например, если функция Add реализует еще какую-нибудь бизнес-логику, отличную от стандартной Add, то для обеспечения безопасного использования класса остальным кодом (который, возможно, будет писать _другой_ человек), придется перекрывать ВСЕ методы с похожей функциональностью, дабы не оставить дыры. И не важно, будут эти методы использоваться, или нет. И, кстати, при выходе следующей версии VCL вовсе не факт, что не добавится еще методов и потенциальных дыр…
    Еще один довод за использование первого варианта – при необходимости легко переопределить FList не как TList, а как любой другой контейнер с нужными фичами, и при этом придется поменять только внутренности класса и гарантировано не придется править все остальное, что использует TMyClass. Про вариант с наследованием в этом случае я даже подумать боюсь.
    Резюме: я всецело за первый вариант. Аргументированные возражения приветствуются.

    6
  7. aktuba
     Add karma Subtract karma  --1
    Цитировать.
    Комментарий автора

    Вот именно с такими-же мыслями и я пришел к первому варианту.

    7
  8. Bonart
     Add karma Subtract karma  --1
    Цитировать.

    Вариант выбора зависит от того, что главное для нового класса: если ЧТО хранить то первый вариант, если КАК хранить – второй.

    8
  9. AnTe
     Add karma Subtract karma  --1
    Цитировать.

    у меня написан шаблон, в смысле, текст модуля, который является копией TObjectList и изменяет его на TObjectMyType, где MyType, как и понятно из контекста, мой тип.

    вот таких вот потомков Tlist у меня уже добрый десяток.

    9

Поделитесь вашими мыслями



Ссылки в комментариях будут свободны от nofollow.

Поддерживаемые теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

Ссылки в комментариях будут свободны от nofollow.

Краска для осб для наружных работ. Как и чем покрасить плиты осб holzer-msk.ru. http://koonka.shop/ коврики 27 хабаровск. Купить коврики в хабаровске.
-->