Re[2]: DAG
От: Qbit86 Кипр
Дата: 15.03.11 16:19
Оценка: 15 (2) +1
Здравствуйте, barn_czn, Вы писали:

_>А самая удобная модель структуры — дерево.


А самая естественная — даг (directed acyclic graph), т.е. граф без циклов но, возможно, с контурами (т.е. как дерево, но у каждого узла может быть несколько родителей). Все эти ваши теги, грани или фасеты какие-то — суть завуалированные даги.

_>А самая удобная модель структуры — дерево.


Рассмотрим другой пример. Как организовать структуру файлов проекта?
Первый вариант:
/Bin
  /Project1
  /Project2
/Doc
  /Project1
  /Project2
Src/
  /Project1
  /Project2

Второй вариант:
/Project1
  /Bin
  /Doc
  /Src
/Project2
  /Bin
  /Doc
  /Src


И то, и другое — дерево, но какое предпочесть? Второй вариант — это транспонированный первый, вывернутый наизнанку. Такая ситуация возникает (как и у топик-стартера), когда есть независимые критерии (аспекты), по которым стоит разделять сущности (антивир/антиспам, скачивалка/интероп). Эти признаки образуют n-мерный параллелепипед. Чтобы зафиксировать иерархическую структуру, надо умостить параллелепипед в плоскость, т.е. упорядочить критерии, произвольно выбрать порядок в котором расслаиваем параллелепипед. Таким образом, попытка умостить набор сущностей в прокрустово ложе дерева, на самом деле, приводит к потере информации об исходной структуре.
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: Namespaces vs. Tags (Facets)
От: x-code  
Дата: 17.03.11 11:03
Оценка: +1
Здравствуйте, barn_czn, Вы писали:

_>Даже в примеры не хочу вникать . Ересь эта фасеточная ваша модель.

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

Не ересь, а весьма перспективное направление. Парадигма АОП кстати в некотором роде близка этой модели, только там речь идет о сквозной функциональности внутри функций, а здесь — о сквозной группировке единиц кода более высокого уровня.
Я лично думаю над тем, как можно такую фасеточную модель внедрить в язык программирования.
Дерево конечно удобно, но задача — сделать удобным использование таких моделей. Очевидно, что пользоваться произвольными графами менее удобно, чем деревьями, но вот теги по уровню удобства сравнимы с деревьями, так что думать надо в направлении "как использовать теги вместо namespaces".
Re[3]: Namespaces vs. Tags (Facets)
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.03.11 07:03
Оценка:
Здравствуйте, x-code, Вы писали:

XC>Не ересь, а весьма перспективное направление. Парадигма АОП кстати в некотором роде близка этой модели, только там речь идет о сквозной функциональности внутри функций, а здесь — о сквозной группировке единиц кода более высокого уровня.

XC>Я лично думаю над тем, как можно такую фасеточную модель внедрить в язык программирования.
XC>Дерево конечно удобно, но задача — сделать удобным использование таких моделей. Очевидно, что пользоваться произвольными графами менее удобно, чем деревьями, но вот теги по уровню удобства сравнимы с деревьями, так что думать надо в направлении "как использовать теги вместо namespaces".
Вижу два аспекта:
1. Объявления. Как объяснить компилятору, в каких фасетах присутствует описываемый класс.
2. Доступ. Как объяснить компилятору, из какого фасета брать классы. Тем более, что не очень понятно, то ли имеется в виду "всё из antivirus, плюс всё из db", или "всё из пересечения antivirus и bd".
3. Как избежать взрыва мозга.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Namespaces vs. Tags (Facets)
От: jazzer Россия Skype: enerjazzer
Дата: 25.03.11 08:45
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вижу два аспекта:

S>1. Объявления. Как объяснить компилятору, в каких фасетах присутствует описываемый класс.
В C++ для этого используется техника traits.

S>2. Доступ. Как объяснить компилятору, из какого фасета брать классы. Тем более, что не очень понятно, то ли имеется в виду "всё из antivirus, плюс всё из db", или "всё из пересечения antivirus и bd".

Что значит — брать? Опять же, это можно сделать через шаблоны и traits, благо в классах могут быть члены-типы (те самые классы, которые нужно "брать").

S>3. Как избежать взрыва мозга.

jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Namespaces vs. Tags (Facets)
От: SV.  
Дата: 25.03.11 09:33
Оценка:
Здравствуйте, 0x7be, Вы писали:

0>Сейчас для логической организации во "мэйнстримовых" языках применяется иерархическая организация — пространства имен, пакеты и т.п. Однако жизнь штука сложная и не всегда хорошо вписывается в иерархическую схему. У меня часто возникали ситуации, когда более естественным способом организовать типы и функции в программе была бы фасеточная классификация, где гранями являются функциональные аспекты системы. Но фасеточная классификация неоднозначно отображается в иерархическую, что порождает некоторые проблемы, особенно если над проектом работает несколько людей.


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

Как правильно написали выше, без примеров это обсуждать бессмысленно. Нужен класс, который с равным основанием можно отнести к двум неймспейсам сразу. Не обязательно ваш пример, любой другой пойдет. Берусь показать, что это в каждом случае плохая декомпозиция.
Re[2]: Азбука ООП
От: Qbit86 Кипр
Дата: 25.03.11 09:40
Оценка:
Здравствуйте, SV., Вы писали:

SV.>Класс не должен выполнять несколько контрактов, это азбука ООП.


Это не азбука ООП, это ваши досужие заключения.
Глаза у меня добрые, но рубашка — смирительная!
Re[3]: Азбука ООП
От: SV.  
Дата: 25.03.11 09:52
Оценка:
Здравствуйте, Qbit86, Вы писали:

SV.>>Класс не должен выполнять несколько контрактов, это азбука ООП.

Q>Это не азбука ООП, это ваши досужие заключения.

Беру это утверждение назад: некорректно сформулировал. Если каждый интерфейс считать за контракт, то, конечно, это глупость. Я имел в виду, что класс должен решать одну четко определенную функциональную задачу, в противном случае его надо разбить. Если и с этм несогласны, то сразу приводите контрпример.
Re[2]: Namespaces vs. Tags (Facets)
От: 0x7be СССР  
Дата: 25.03.11 10:15
Оценка:
Здравствуйте, SV., Вы писали:

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

Посмотрите здесь
Автор: 0x7be
Дата: 13.03.11
в конце сообщения.
Интересны Ваши комментарии.
Re[9]: Примеры
От: jazzer Россия Skype: enerjazzer
Дата: 25.03.11 10:38
Оценка:
Здравствуйте, 0x7be, Вы писали:

S>>Пока что не увидел — почему.

0>Ок, второй заход. Опишу минимальный набор компонентов, пригодный для иллюстрации идеи:
0>Есть следующие компоненты:
0>Updater — реализует в себе общую для всех часть функционала обновления.
0>AntivirusScanner — антивирусный сканер, использует Updater.
0>AntispamScanner — антиспамовый сканер, использует Updater.
0>AntivirusUpdater — антивирусный обновитель.
0>AntispamUpdater — антиспамовый обновитель.

0>Тут мы наблюдаем 4 фасета: Updater, Antivirus, Antispam, Scanner.

0>Фишка в том, что, например, AntivirusUpdater может быть расположен пространстве имен двумя РАВНОПРАВНЫМИ способами:
0>1. Antivirus.Updater.AntivirusUpdater.
0>2. Updater.Antivirus.AntivirusUpdater.
0>(ПРИМЕЧАНИЕ: порядок слов в самом идентификаторе AntivirusUpdater следует из правил английского языка )
0>Сейчас волевым решением выбран первый вариант, но объективно он ничем не лучше.
0>Это исключительно соглашение, что бы было "безобразно, но единообразно".

0>Далее, если мы захотим заиметь ещё один вид сканера, то у нас добавляется ещё один фасет.

0>Пусть это будет какая-нибудь порнорезалка. Естественным образом у нас появляется фасет Pornbuster, и компоненты PornbusterScanner и PornbusterUpdater.
0>Никаких "криминальных" зависимостей между компонентами, которые бы зарубили нам расширяемость, тут не наблюдается.

0>Так лучше понятно?


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

Да, а язык какой?
Если это С++, в котором можно иметь члены-типы, то можно писать так:
// пусть мы стартуем от более-менее "главных" вещей
class Antivirus {
  class Scanner;
  class Updater;
};

class Antispam {
  class Scanner;
  class Updater;
};

class Pornbuster {
  class Scanner;
  class Updater;
};

// теперь грани
struct Updater {
  typedef Antivirus::Updater Antivirus;
  typedef Antispam::Updater Antispam;
  typedef Pornbuster::Updater Pornbuster;
};

struct Scanner {
  typedef Antivirus::Scanner Antivirus;
  typedef Antispam::Scanner Antispam;
  typedef Pornbuster::Scanner Pornbuster;
};


так как в С++ typedef — это не новый тип, а алиас на уже существующий тип, то ты теперь можешь писать как угодно, хоть Antivirus::Updater, хоть Updater::Antivirus — это будет один и тот же класс.

Из этого можно извлечь немалый профит, кстати, так как Updater — это сам по себе тип, которым можно, например, параметризовать какой-нть шаблон, и он автоматом подхватит именно то, что нужно.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Namespaces vs. Tags (Facets)
От: SV.  
Дата: 25.03.11 10:38
Оценка:
Здравствуйте, 0x7be, Вы писали:

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

0>Посмотрите здесь
Автор: 0x7be
Дата: 13.03.11
в конце сообщения.

0>Интересны Ваши комментарии.

Тут мы наблюдаем 4 фасета: Updater, Antivirus, Antispam, Scanner.
Фишка в том, что, например, AntivirusUpdater может быть расположен пространстве имен двумя РАВНОПРАВНЫМИ способами:
1. Antivirus.Updater.AntivirusUpdater.
2. Updater.Antivirus.AntivirusUpdater.
(ПРИМЕЧАНИЕ: порядок слов в самом идентификаторе AntivirusUpdater следует из правил английского языка )
Сейчас волевым решением выбран первый вариант, но объективно он ничем не лучше.
Это исключительно соглашение, что бы было "безобразно, но единообразно".


Это? AntivirusUpdater — класс? Я вижу два варианта:

1. На самом деле класс НЕ AntivirusUpdater. То есть, он может использоваться для обновления чего угодно, может взаимозаменяться с BITS, а написан просто потому, чтоб не привязываться к конкретным платформам типа COM. В этом случае класс надо переименовать в SoftwareUpdater, а неймспейс под него завести типа ServerIO, Updating или Steam

2. Это в самом деле AntivirusUpdater. Ваше приложение-антивирус должно обновляться не так, как другой софт. Есть какие-то очень важные нюансы. (Допустим даже, что AntivirusUpdater использует SoftwareUpdater). В этом случае Antivirus.Updater.AntivirusUpdater не равноправен Updater.Antivirus.AntivirusUpdater, поскольку Updater — компонент антивируса, а не наоборот.
Re[4]: Namespaces vs. Tags (Facets)
От: mrTwister Россия  
Дата: 25.03.11 20:47
Оценка:
Здравствуйте, SV., Вы писали:

SV.>2. Это в самом деле AntivirusUpdater. Ваше приложение-антивирус должно обновляться не так, как другой софт. Есть какие-то очень важные нюансы. (Допустим даже, что AntivirusUpdater использует SoftwareUpdater). В этом случае Antivirus.Updater.AntivirusUpdater не равноправен Updater.Antivirus.AntivirusUpdater, поскольку Updater — компонент антивируса, а не наоборот.


А как на счет сфокусированности (cohesion) кода? Например, если антивирус — это независимый компонент, который вообще ничего не знает об апдейтере? При этом есть апдейтер антивируса, который умеет апдейтить именно антивирус (специфичная логика) и тесно связан с общим кодом обновления вместе с другими апдейтерами. То, что ты предлагаешь — это по сути когда мы нечто делаем составной частью некоторого другого компонента, при том, что сам этот компонент вообще ничего не знает о своей "составной части". Это нормально? Ну то есть примерно как автомобильную заправку назвать составной частью автомобиля.
лэт ми спик фром май харт
Re[5]: Namespaces vs. Tags (Facets)
От: SV.  
Дата: 26.03.11 12:03
Оценка:
Здравствуйте, mrTwister, Вы писали:

SV.>>2. Это в самом деле AntivirusUpdater. Ваше приложение-антивирус должно обновляться не так, как другой софт. Есть какие-то очень важные нюансы. (Допустим даже, что AntivirusUpdater использует SoftwareUpdater). В этом случае Antivirus.Updater.AntivirusUpdater не равноправен Updater.Antivirus.AntivirusUpdater, поскольку Updater — компонент антивируса, а не наоборот.


T>А как на счет сфокусированности (cohesion) кода? Например, если антивирус — это независимый компонент, который вообще ничего не знает об апдейтере? При этом есть апдейтер антивируса, который умеет апдейтить именно антивирус (специфичная логика) и тесно связан с общим кодом обновления вместе с другими апдейтерами. То, что ты предлагаешь — это по сути когда мы нечто делаем составной частью некоторого другого компонента, при том, что сам этот компонент вообще ничего не знает о своей "составной части". Это нормально? Ну то есть примерно как автомобильную заправку назвать составной частью автомобиля.


Вообще-то, я предполагал, что антивирус — это приложение, которое дергает апдейтер по команде из GUI. Если нет, и общение приложения и апдейтера происходит только через конфиги, то это другой случай. Вот такой:

class Antivirus.Updater.AntivirusUpdaterService; // Класс апдейтера
class Antivirus.Core.Application; // Класс "независимого компонента, который вообще ничего не знает об апдейтере".


Еще раз, я полагаю, что в функциональном аспекте иерархии ВСЕГДА годятся. Иерархическая неоднозначность идет уровнем ниже (то есть, на уровне атрибутов). Если кто-то приведет контрпример, это будет весьма интересно.
Re[6]: Namespaces vs. Tags (Facets)
От: mrTwister Россия  
Дата: 26.03.11 12:27
Оценка:
Здравствуйте, SV., Вы писали:

SV.>
SV.>class Antivirus.Updater.AntivirusUpdaterService; // Класс апдейтера
SV.>class Antivirus.Core.Application; // Класс "независимого компонента, который вообще ничего не знает об апдейтере".
SV.>


Прекрасно, а теперь посмотрим на все это с несколько другой точки зрения, а именно с кода апдейтера. Допусти есть не только апдейтер антивируса, но и апдейтер чего-то еще, есть базовый функционал для всех апдейтеров, есть планировщик задач апдейтера — то есть куча классов, у которых друг с другом довольно высокие cohesion и coupling. В предложенном тобой решении эти классы оказываются сильно разбросаны по иерархии и находятся друг от друга далеко. В этом и проблема. Если я правильно понял топик стартера, то он бы хотел в одном случае посмотреть на иерархию кода, который так или иначе связан с обновлением (какие есть классы, какие зависимости между ними, у кого какая ответственность и так далее), а в другом случае он бы хотел посмотреть на иерархию кода, который так или иначе связан с антивирусом. И в обоих случаях ему было бы удобно работать с разными иерархиями.
лэт ми спик фром май харт
Re[7]: Namespaces vs. Tags (Facets)
От: SV.  
Дата: 26.03.11 14:14
Оценка:
Здравствуйте, mrTwister, Вы писали:

SV.>>
SV.>>class Antivirus.Updater.AntivirusUpdaterService; // Класс апдейтера
SV.>>class Antivirus.Core.Application; // Класс "независимого компонента, который вообще ничего не знает об апдейтере".
SV.>>


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


Как раз про это я хотел написать, и даже начал:

T>и тесно связан с общим кодом обновления вместе с другими апдейтерами
Забыл добавить. Вот эта тесная связь для меня не является основанием помещать наш апдейтер в неймспейс "с другими апдейтерами".


В википедии написано, что неймспейс — это контекст для идентификаторов, и я с этим горячо согласен. Контекст, как я понимаю, служит для разрешения конфликтов и для функциональной классификации (апдейтер в контексте антивируса — функциональная часть антивируса). Спрашивается, причем здесь cohesion и coupling? Давайте рассуждать методом доведения до абсурда. string используется во множестве классов. Лежит, однако, в System. В этом тоже какая-то проблема? Допустим, вы делаете свой string, какой-нибудь... ммм... с автопереводом. Он активно использует System.String для хранения и обработки. Будете ли вы помещать его тоже в System? Технических препятствий-то нет. Студия по рукам не надает.

Апдейтер антивируса, не смотря на связность и связанность с другими апдейтерами, имеет антивирусный контекст.

Что касается связности и связанности. Это метрики, которые существуют объективно. Чтобы смотреть на них, можно использовать тул, который строит диаграммы, таблицы и пр. Объективные метрики не должны быть продублированы субъективными маркерами во имя непротиворечивости. Функциональная классификация, напротив — исключительно субъективна. Из кода ее не вывести.

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


Это решительно невозможно обсуждать без примеров. То, что было приведено — не примеры, а так, заготовка для болтологии. Если у нас три класса — базовый универсальный Updater, специализированный AntivirusUpdater, и Application, я уже написал, как бы я сделал:

class System.Updating.BaseUpdaterService; // Базовый класс апдейтера из какого-то фреймворка.
class Antivirus.Updater.AntivirusUpdaterService : System.Updating.BaseUpdaterService; // Специализированный класс апдейтера.
class Antivirus.Core.Application : System.Application; // Класс "независимого компонента, который вообще ничего не знает об апдейтере".


Соответственно, если вы не согласны, или покажите перепаковку этих трех классов, или добавьте в пример новые классы, которые покажут не... кузявость единственной неймспейсовской иерархии.
Re[5]: Namespaces vs. Tags (Facets)
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.03.11 07:59
Оценка:
Здравствуйте, jazzer, Вы писали:

S>>2. Доступ. Как объяснить компилятору, из какого фасета брать классы. Тем более, что не очень понятно, то ли имеется в виду "всё из antivirus, плюс всё из db", или "всё из пересечения antivirus и bd".

J>Что значит — брать?
Значит выполнять name lookup. Вот я пишу Console.WriteLine(). Какой Console имеется в виду? Из System.*?

S>>3. Как избежать взрыва мозга.

J>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Примеры
От: jazzer Россия Skype: enerjazzer
Дата: 27.03.11 13:44
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Мне неизвестен язык программирования, который бы позволил задать правило "в функциональном неймспейсе могут быть только поднеймспейсы bl, db, и ui". Или хоть как-то гарантировать, что вместо antispam.db не появится какой-нибудь antispam.database, сломав стройную структуру таблички.


В С++ можно вместо неймспейсов пользоваться просто структурами и членами-типами в них. А в структурах как раз можно все это гарантировать.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Namespaces vs. Tags (Facets)
От: jazzer Россия Skype: enerjazzer
Дата: 27.03.11 13:46
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>>>2. Доступ. Как объяснить компилятору, из какого фасета брать классы. Тем более, что не очень понятно, то ли имеется в виду "всё из antivirus, плюс всё из db", или "всё из пересечения antivirus и bd".

J>>Что значит — брать?
S>Значит выполнять name lookup. Вот я пишу Console.WriteLine(). Какой Console имеется в виду? Из System.*?
Ну информация же о фасете/ах откуда-то все же доступна? Или вообще все с потолка?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[7]: Namespaces vs. Tags (Facets)
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.03.11 16:22
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Ну информация же о фасете/ах откуда-то все же доступна? Или вообще все с потолка?

Понятно, что доступна. Как ей пользоваться?
В случае плоского дерева я пишу
using Namespace.Subnamespace;

и в область видимости влетает всё, что нужно.
В случае фасетов что будет происходить если я пишу
using Updater;
using Antivirus;

? Войдут ли в область видимости все классы из Updater (включая AntispamUpdater), все классы из Antivirus (включая AntivirusChecker) или только AntivirusUpdater и все остальные из обоих фасетов?
Или надо писать

using Updater & Antivirus;
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[8]: Namespaces vs. Tags (Facets)
От: jazzer Россия Skype: enerjazzer
Дата: 28.03.11 11:09
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, jazzer, Вы писали:


J>>Ну информация же о фасете/ах откуда-то все же доступна? Или вообще все с потолка?

S>Понятно, что доступна. Как ей пользоваться?
S>В случае плоского дерева я пишу
S>
S>using Namespace.Subnamespace;
S>

S>и в область видимости влетает всё, что нужно.
А, так тебе нужно, чтоб именно using работал
Мне вот вполне явного указания фасета хватит.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[9]: Namespaces vs. Tags (Facets)
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.03.11 22:07
Оценка:
Здравствуйте, jazzer, Вы писали:

S>>и в область видимости влетает всё, что нужно.

J>А, так тебе нужно, чтоб именно using работал
J>Мне вот вполне явного указания фасета хватит.
И как именно это будет выглядеть?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.