почему ни в одном стандарте с++ до сих пор не предложили нормальные пропертя?
разве не лучше писать Core->SystemA->Manager->Call();
чем GetCore()->GetSystemA()->GetManager()->Call();
?
или еще хуже с разными с порнонотациями типа :
getCore()->getSystemA()->getManager()->Call();
или полные дрова:
get_Core()->get_SystemA()->get_Manager()->Call();
я из за этого уродства забил на изоляцию мемберов от внешнего мира и использую паблик мемберы по полной.
почему в 11-м стандарте предложена куча всякой ультраспецифичной лабуды, а такого ништяка до сих пор там нет?
(костыли и мс-специфичные прагмы не предлагать, пробовал уже)
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Здравствуйте, Kingofastellarwar, Вы писали:
K>я из за этого уродства забил на изоляцию мемберов от внешнего мира и использую паблик мемберы по полной.
Фигасе.
Я, проектируя класс, сразу закладываюсь на то, что его будет использовать полный баран и гадить везде, где только можно (даже если это мой собственный проект).
А ты молодец, я погляжу
K>почему ни в одном стандарте с++ до сих пор не предложили нормальные пропертя?
Потому, что они НЕ НУЖНЫ.
K>разве не лучше писать Core->SystemA->Manager->Call(); K>чем GetCore()->GetSystemA()->GetManager()->Call();
Оба хуже.
K>я из за этого уродства забил на изоляцию мемберов от внешнего мира и использую паблик мемберы по полной.
Просто некоторые люди неправильно понимают идею изоляции. Ничего плохого в открытой переменной нет. С точки зрения инкапсуляции вариант
public: Type a;
НИЧЕМ не отличается от
public:
Type getA() {return a;}
void setA(const Type& a_) { a = a_;}
private:
A a;
Но первый вариант нагляден, прост, поддерживает любую семантику, которая определена для Type (например, попробуй во втором варианте вызвать над а инкремент) и позволяет компилятору оптимизировать оптимизируемое.
У второго варианта никаих достоинств, одни недостатки.
Имена функций (любых, членов и свободных) должны сводиться к ГЛАГОЛУ — этот глагол не должен быть set или get. А когда я вижу аксессоры, я хватаюсь за пистолет.
K>почему в 11-м стандарте предложена куча всякой ультраспецифичной лабуды, а такого ништяка до сих пор там нет?
Вот потому.
Здравствуйте, Vamp, Вы писали:
V>Имена функций (любых, членов и свободных) должны сводиться к ГЛАГОЛУ — этот глагол не должен быть set или get. А когда я вижу аксессоры, я хватаюсь за пистолет.
Кроме доступа там могут быть какие-то сайд-эффекты прикручены, уведомить кого-то об изменении переменной, например. Так что ничего плохого в set/get нет.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Ops, Вы писали:
Ops>Здравствуйте, Vamp, Вы писали:
V>>Имена функций (любых, членов и свободных) должны сводиться к ГЛАГОЛУ — этот глагол не должен быть set или get. А когда я вижу аксессоры, я хватаюсь за пистолет.
Ops>Кроме доступа там могут быть какие-то сайд-эффекты прикручены, уведомить кого-то об изменении переменной, например. Так что ничего плохого в set/get нет.
эти рекламируемые сайд-эффекты я видел полраза в жизни на тысячи раз, когда я видел пустые сеттеры-геттеры безо всяких сайд-эффектов.
Так что делать код нечитаемым ради мифических ништяков смысла я лично не вижу, а те полраза, когда это вдруг понадобится, меня не напряжет пройтись по местам использования и преобразовать прямой доступ в методы.
Тем более что сайд-эффекты сами по себе возникают редко, обычно они являются частью какой-то более сложной функциональности, достойной внятного именования, и "пропертя" опять же оказываются не у дел.
Ops>Кроме доступа там могут быть какие-то сайд-эффекты прикручены, уведомить кого-то об изменении переменной, например. Так что ничего плохого в set/get нет.
Нет. По двум причинам.
Во-первых, переменная — либо внутреннее дело класса, либо внешнее. Если она внешнее — например, это элемент массива, в классе, инкапсулирующем массив — то уведомлять никого ни о чем не надо.
Если эта переменная внутренняя — как, например, в том же классе размер массива — то наружу от нее вообще ничего не торчит, а вместо этого есть метод-глагол resize, и, так уж и быть, рид-аксессор length(). Кстати, я просто забыл про такие случаи в своем посте выше, "полузакрытым" переменным, запись в которые происходит "глаголом", а чтение доступно свободно, разрешается иметь рид-аксессор.
Во-вторых, я в своей жизни повидал аксессоров (и нахлебался с ними) — и ни разу еще не видел, чтобы они реализовывали эти самые "сайд-эффекты". Тупое присваивание.
J>эти рекламируемые сайд-эффекты я видел полраза в жизни на тысячи раз, когда я видел пустые сеттеры-геттеры безо всяких сайд-эффектов.
Я надеялся на твою поддержку!
J>Так что делать код нечитаемым ради мифических ништяков смысла я лично не вижу,
Да не только нечитаемым! Это половина синтаксиса сразу коту под хвост. Ни инкремента, ни декремента, ни += (и все остальные *=), ни экстракции из потока, ни сдвигов, НИЧЕГО!
А вместо
А = B + C;
изволь писать
setA(getB() + getC());
И все только потому, что кто-то когда-то придумал понятие propery для Delphi — потому что так удобно было организовывать визуальное программирование!
Здравствуйте, Kingofastellarwar, Вы писали:
K>почему ни в одном стандарте с++ до сих пор не предложили нормальные пропертя?
K>разве не лучше писать Core->SystemA->Manager->Call(); K>чем GetCore()->GetSystemA()->GetManager()->Call(); K>? K>или еще хуже с разными с порнонотациями типа : K>getCore()->getSystemA()->getManager()->Call(); K>или полные дрова: K>get_Core()->get_SystemA()->get_Manager()->Call();
K>я из за этого уродства забил на изоляцию мемберов от внешнего мира и использую паблик мемберы по полной.
K>почему в 11-м стандарте предложена куча всякой ультраспецифичной лабуды, а такого ништяка до сих пор там нет?
K>(костыли и мс-специфичные прагмы не предлагать, пробовал уже)
Один вопрос. Зачем?!
Здравствуйте, Vamp, Вы писали:
V>Если эта переменная внутренняя — как, например, в том же классе размер массива — то наружу от нее вообще ничего не торчит, а вместо этого есть метод-глагол resize, и, так уж и быть, рид-аксессор length(). Кстати, я просто забыл про такие случаи в своем посте выше, "полузакрытым" переменным, запись в которые происходит "глаголом", а чтение доступно свободно, разрешается иметь рид-аксессор.
Отчасти это стилистический вопрос. Как красивее писать:
length() / resize(n) — разные корни; пример — std::string
size() / resize(n) — существительное и глагол от существительного; пример — std::vector
size() / size(n) — омонимы (существительное и глагол пишутся одинаково); пример: std::stream::rdbuf()
getsize() / setsize(n); getSize() / setSize(n); get_size() / set_size(n) — разные конвенции приставок get- и set-
Ещё бывает пара get/put, а не только get/set.
Проперти, будучи в языке, внесли бы строгость. Но их нет, и они не внесли.
V>Во-вторых, я в своей жизни повидал аксессоров (и нахлебался с ними) — и ни разу еще не видел, чтобы они реализовывали эти самые "сайд-эффекты". Тупое присваивание.
А как именно нахлебался?
Я в одном проекте вполне себе пользовался пропертями и находил их удобными. Сейчас уже всех подробностей не помню, кроме того, что
1) в макросах — не надо писать разные макросы, отдельно для функций, отдельно для переменных
2) нетупое присваивание — валидация; установка обратного указателя
V>>Во-вторых, я в своей жизни повидал аксессоров (и нахлебался с ними) — и ни разу еще не видел, чтобы они реализовывали эти самые "сайд-эффекты". Тупое присваивание.
К>А как именно нахлебался?
Геморрой с изменением:
1. Операторы использовать нельзя (прощайте ++, +=, >> и т.д.).
2. Функции и функции-члены использовать нельзя (прощайте resize(), reserve(), sort() и т.д.).
3. Всегда надо заводить лишний объект.
4. Всё делается только через присваивание этого лишнего объекта, которое крайне редко может сравниться по оптимальности с прямой работой с объектом.
5. Даже в случае тривиальных геттеров-сеттеров компилятор не будет достаточно умным, чтобы переписать код изменения третьего объекта на прямую работу с объектом-членом.
Здравствуйте, Kingofastellarwar, Вы писали:
K>почему ни в одном стандарте с++ до сих пор не предложили нормальные пропертя?
K>разве не лучше писать Core->SystemA->Manager->Call(); K>чем GetCore()->GetSystemA()->GetManager()->Call(); K>? K>или еще хуже с разными с порнонотациями типа : K>getCore()->getSystemA()->getManager()->Call(); K>или полные дрова: K>get_Core()->get_SystemA()->get_Manager()->Call();
Всё это туфта. Писать только так:
assert(NULL != GetCoreSystemAManager());
GetCoreSystemAManager()->Call();
А все эти ваши макароны кушайте сами.
K>я из за этого уродства забил на изоляцию мемберов от внешнего мира и использую паблик мемберы по полной.
С-style?
K>почему в 11-м стандарте предложена куча всякой ультраспецифичной лабуды, а такого ништяка до сих пор там нет?
Проперти не нужны
Здравствуйте, Vamp, Вы писали:
V>А вместо V>А = B + C; V>изволь писать V>setA(getB() + getC());
V>И все только потому, что кто-то когда-то придумал понятие propery для Delphi — потому что так удобно было организовывать визуальное программирование!
Это случилось чуть раньше — в OLE/COM.
Там надо было.
А на них уже соорудили Дельфу.
К>length() / resize(n) — разные корни; пример — std::string К>size() / resize(n) — существительное и глагол от существительного; пример — std::vector
Зависит от. Просто для строки понятие length более применимо (на мой вкус), чем size. А глагола relength нет.
К>size() / size(n) — омонимы (существительное и глагол пишутся одинаково); пример: std::stream::rdbuf()
Size — не глагол. Так что мне не нравится. Впрочем, это не единственная странная вещь в стримах.
К>getsize() / setsize(n); getSize() / setSize(n); get_size() / set_size(n) — разные конвенции приставок get- и set- К>Ещё бывает пара get/put, а не только get/set.
Дело не в том, какая приставка, а в том, что они мешают в целом.
К>Проперти, будучи в языке, внесли бы строгость. Но их нет, и они не внесли.
Я так и не вижу их преимуществ. Все это неизжитый дельфизм.
К>А как именно нахлебался?
Да по-всякому. Я тут уже два раза писал, как половина полезного синтаксиса закрывается. См. выше.
Кроме этого, усложняется косвенная адресация. Например, есть желание универсально обращаться к полю. Если член — открытая переменная, то это делается просто:
Ну и какой код нагляднее? Я уже не говорю, что пока сигнатуру функции правильно напишешь — семь потов сойдет. Особенно если там их несколько в зависимости от константности.
К>2) нетупое присваивание — валидация;
И что ты делал, если валидация обламывалась?
Здравствуйте, Vamp, Вы писали:
K>>почему ни в одном стандарте с++ до сих пор не предложили нормальные пропертя? V>Потому, что они НЕ НУЖНЫ.
нужны.
кроме написания хорошего кода с нуля, есть еще работа с legacy кодом.
например, имеем код
struct Foo
{
int state;
};
и пару сотен использований токена "state" в исходниках.
VisualAssistX выдает неправильный список использований, или вообще отказывается его выдавать.
надо понять где, как и зачем state меняется, и например добавить туда новый код (в setter)
пишем
struct Foo
{
__declspec(property(get=get_state)) int state;
int m_state;
int get_state() const { return m_state; }
};
компилируем, и в ошибках компиляции видим где state меняется.
если таких мест мало, можно добавить всякие set_default_state(), change_state(x), и т.п.
если изменения получаются очень сложными, в качестве временной меры можно добавить set=set_state, и не трогать существующий код,
позже, после десятка-другого итераций рефакторинга, когда код улушится, можно будет убрать __declspec(property()).
------
Типичный пример добавления кода в сеттер:
было:
struct GodStructure
{
// ...
// очень много полейint state;
};
Здравствуйте, Vamp, Вы писали:
V>Но первый вариант нагляден, прост, поддерживает любую семантику, которая определена для Type (например, попробуй во втором варианте вызвать над а инкремент) и позволяет компилятору оптимизировать оптимизируемое. V>У второго варианта никаих достоинств, одни недостатки.
Инкремент — раскладывается в get(), прибавление 1 и set().
Оптимизация — нет сейчас настолько тупого компилятора в майнстриме, чтобы не смог оптимизировать такой случай, заметив, что get() это чтение значения, а set() — присвоение. Компиляторы справляются и со значительно более сложными случаями.
А вот преимущество пропертей, которое ты не сделаешь никакой заменой на открытый член — это то, что, например, для отладки ты в set() делаешь контроль, кто ставит значение и почему, и компилируешь такой код без проблем, а при открытом члене ты должен расставлять watchpoints или форсировать замену во всём коде прямого присвоения на явный set().
Итого — у первого варианта сплошные недостатки, а у второго (property) — сплошные достоинства.
V>Имена функций (любых, членов и свободных) должны сводиться к ГЛАГОЛУ — этот глагол не должен быть set или get. А когда я вижу аксессоры, я хватаюсь за пистолет.
Правильно — property как механизм значительно удобнее.
K>>почему в 11-м стандарте предложена куча всякой ультраспецифичной лабуды, а такого ништяка до сих пор там нет? V>Вот потому.
Я использовал properties в Питоне. Очень таки удобно.