Здравствуйте, jazzer, Вы писали:
V>>>Во-вторых, я в своей жизни повидал аксессоров (и нахлебался с ними) — и ни разу еще не видел, чтобы они реализовывали эти самые "сайд-эффекты". Тупое присваивание. К>>А как именно нахлебался? J>Геморрой с изменением: J>1. Операторы использовать нельзя (прощайте ++, +=, >> и т.д.).
Тут есть два выхода. Можно разрешить любые неописанные операции через get-modify-set, а можно какие-то операции явно определить с реализующим их кодом, а не только get и set. Можно использовать оба.
J>2. Функции и функции-члены использовать нельзя (прощайте resize(), reserve(), sort() и т.д.).
Именно для этого случая их вообще-то и не положено использовать. Хотя, с другой стороны, механизм, позволяющий делать что-то вроде
спокойно бы закрыл эту проблему, позволив определять методы для свойств как алиасы для методов класса-хозяина.
J>3. Всегда надо заводить лишний объект. J>4. Всё делается только через присваивание этого лишнего объекта, которое крайне редко может сравниться по оптимальности с прямой работой с объектом.
Эти пункты являются следствием нерешённости пунктов 1 и 2. Если их решить, этих проблем не будет.
J>5. Даже в случае тривиальных геттеров-сеттеров компилятор не будет достаточно умным, чтобы переписать код изменения третьего объекта на прямую работу с объектом-членом.
Компиляторы сейчас умеют и значительно более умные вещи, а эта будет для них тривиальщиной.
K>почему ни в одном стандарте с++ до сих пор не предложили нормальные пропертя?
Отвечу коротко и надеюсь ясно: потому что нахрен они никому не нужны.
K>разве не лучше писать Core->SystemA->Manager->Call(); K>чем GetCore()->GetSystemA()->GetManager()->Call(); K>?
Здравствуйте, Kingofastellarwar, Вы писали:
K>почему ни в одном стандарте с++ до сих пор не предложили нормальные пропертя?
Потомучто это удел скриптов
K>разве не лучше писать Core->SystemA->Manager->Call(); K>чем GetCore()->GetSystemA()->GetManager()->Call(); K>?
Писать несколько гетов в одной строчке? у вас гавно-архитектура, отсюда все эти выдуманые проблемы.
K>я из за этого уродства забил на изоляцию мемберов от внешнего мира и использую паблик мемберы по полной.
Перейди на скрипты, С++ для тебя противопоказан. Даже С для тебя будет противопоказан.
K>почему в 11-м стандарте предложена куча всякой ультраспецифичной лабуды, а такого ништяка до сих пор там нет?
В 11 стандарте нет концептов, вот это действительно беда — а проперти это паталогия скриптеров
Если по существу, то проектируются всегда от интерфейсов
любое изменение таких данных влечет за собой измененние состояния,
как минимум выставить флаг инвалидации, и в get она проверяется (так называемая линивый пересчет)
например setPosition, getMatrix
setPosition выставит флаг инвалидации
getMatrix пересчитает матрицу только в том случае если данные изменились, в противном вернет as is
Здравствуйте, netch80, Вы писали: N>Здравствуйте, jazzer, Вы писали: V>>>>Во-вторых, я в своей жизни повидал аксессоров (и нахлебался с ними) — и ни разу еще не видел, чтобы они реализовывали эти самые "сайд-эффекты". Тупое присваивание. К>>>А как именно нахлебался? J>>Геморрой с изменением: J>>1. Операторы использовать нельзя (прощайте ++, +=, >> и т.д.). N>Тут есть два выхода. Можно разрешить любые неописанные операции через get-modify-set, а можно какие-то операции явно определить с реализующим их кодом, а не только get и set. Можно использовать оба.
Ага. Сколько у нас там операторов? С десяток наберется ведь?
И вся эта карусель лишь ради того, что "Вдруг Когда-то Где-то Кому-то" (tm) могут потребоваться сайд-эффекты. J>>2. Функции и функции-члены использовать нельзя (прощайте resize(), reserve(), sort() и т.д.). N>Именно для этого случая их вообще-то и не положено использовать. Хотя, с другой стороны, механизм, позволяющий делать что-то вроде N>
N>спокойно бы закрыл эту проблему, позволив определять методы для свойств как алиасы для методов класса-хозяина.
Те же проблемы, что и с операторами, только еще хуже. Это ж для всех функций-членов всех классов придется подобное писать, и для каждого свое, так что даже в макрос не упрячешь. А попробуй-ка воспроизведи интерфейс std::string, ага. Лучше сразу застрелиться.
Так что овчинка выделки не стоит совершенно. J>>3. Всегда надо заводить лишний объект. J>>4. Всё делается только через присваивание этого лишнего объекта, которое крайне редко может сравниться по оптимальности с прямой работой с объектом. N>Эти пункты являются следствием нерешённости пунктов 1 и 2. Если их решить, этих проблем не будет.
Одна беда — что их решить вменяемым способом нельзя. А так оно конечно. J>>5. Даже в случае тривиальных геттеров-сеттеров компилятор не будет достаточно умным, чтобы переписать код изменения третьего объекта на прямую работу с объектом-членом. N>Компиляторы сейчас умеют и значительно более умные вещи, а эта будет для них тривиальщиной.
Доверяй, но проверяй.
На сцене компилятор GCC4.4.4 (нынешний стандартный RedHat-овский), с оптимизацией -О3 (в продакшен-коде пользуются оптимизацией не выше -О2, к слову).
Исходный код:
Скрытый текст
#include <string>
// открытый классclass A
{
public:
int x;
double d;
std::string s;
};
//класс с геттерами-сеттерамиclass B
{
public:
int getX() const { return x_; }
void setX(int x) { x_ = x; }
double getD() const { return d_; }
void setD(const double& d) { d_ = d; }
std::string getS() const { return s_; }
void setS(const std::string& s) { s_ = s; }
private:
int x_;
double d_;
std::string s_;
};
// работаем с переменной типа intvoid fiA(A& a)
{
++a.x;
}
void fiB(B& b)
{
int x = b.getX();
++x;
b.setX(x);
}
// работаем с переменной типа doublevoid fdA(A& a)
{
a.d += 100;
}
void fdB(B& b)
{
double d = b.getD();
d += 100;
b.setD(d);
}
// работаем с переменной типа std::stringvoid fsA(A& a)
{
a.s.resize(100);
}
void fsB(B& b)
{
std::string s = b.getS();
s.resize(100);
b.setS(s);
}
// введем еще один (тривиальный) уровень сеттеров-геттеровclass A0
{
public:
A a;
};
class B0
{
public:
B getB() const { return b_; }
void setB(const B& b) { b_ = b; }
private:
B b_;
};
// поехалиvoid fAA(A0& a0)
{
++a0.a.x;
a0.a.d += 100;
a0.a.s.resize(100);
}
void fBB(B0& b0)
{
B b = b0.getB();
int x = b.getX();
++x;
b.setX(x);
double d = b.getD();
d += 100;
b.setD(d);
std::string s = b.getS();
s.resize(100);
b.setS(s);
b0.setB(b);
}
это я еще по-божески обошелся с геттеро-сеттерным кодом — переменную создал только один раз в начале и присвоил обратно только один раз в конце.
Хотя, чтоб делать эквивалентно, надо бы звать get/set на каждый чих (потому что в промежутках могут зваться функции, которым требуется измененное состояние полного объекта).
Но и без этого читабельность кода где-то в районе плинтуса.
к слову, std::string используется из поставки компилятора, а не какой-нть из STLPort с оптимизацией коротких строк, который компилятор не сможет соптимизировать с вероятностью 99.94%.
Здравствуйте, о_О, Вы писали:
о_О>Здравствуйте, jazzer, Вы писали:
J>>И как, часто в твоей жизни наступало такое вот "завтра"? Только честно. J>>У меня вот чуть чаще чем никогда.
о_О>возникает постоянно при проектировании с нуля, из-за неопытности не всегда получается сделать сразу хорошо. абстрагировался, а там хоть потоп
При проектировании c нуля всегда получается не очень хорошо, поэтому первый вариант называется прототипом и выбрасывается на свалку, а в пользование идет второй, а то и третий, в котором недостатки первого устранены. И неопытность тут совершенно ни при чем — предусмотреть все с самого начала невозможно в принципе. А абстрагировать неудачный первый вариант и потом за фасадом сложных геттеров-сеттеров пытаться перерефакторить все к нормальному виду — путь к тому самому потопу.
Здравствуйте, jazzer, Вы писали:
J>И вся эта карусель лишь ради того, что "Вдруг Когда-то Где-то Кому-то" (tm) могут потребоваться сайд-эффекты.
Да кто ж заставляет-то? Весь разговор пошел с заявления, что геттеры-сеттеры вообще не нужны. Но ведь их вполне можно использовать, когда они облегчают жизнь, а не лепить везде, где не попадя.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Здравствуйте, Ops, Вы писали:
Ops>Здравствуйте, jazzer, Вы писали:
J>>И вся эта карусель лишь ради того, что "Вдруг Когда-то Где-то Кому-то" (tm) могут потребоваться сайд-эффекты.
Ops>Да кто ж заставляет-то? Весь разговор пошел с заявления, что геттеры-сеттеры вообще не нужны. Но ведь их вполне можно использовать, когда они облегчают жизнь, а не лепить везде, где не попадя.
не просто геттеры-сеттеры, а "пропертя" и их реализация через геттеры-сеттеры как альтернатива простым публичным членам.
Здравствуйте, MasterZiv, Вы писали:
>> MZ>КЫВТ УГ >> возвращайся на исходнечки.ру
MZ>А это оно само пишет. Я ОДИН раз это написал, оно теперь САМО это посылаяет MZ>Это если через Web писать. Так что все вопросы к программистам RSDN.
Я думаю, что все вопросы к твоей настройке твоего браузера, который один раз запомнил содержимое полей формы и теперь все время одно и то же туда лепит.
У меня FF, никаких "автозаполнятелей" форм нету — полет нормальный.
> Я думаю, что все вопросы к твоей настройке твоего браузера, который один раз > запомнил содержимое полей формы и теперь все время одно и то же туда лепит.
Безусловно. Только как их поменять я лично не имею ни малейшего представления.
А удалить их из этих полей не имею возможности -- они там все слепляются
на телефоне в такую кашу, что я имею возможность ткнуть только в ОДНО
поле, самое большое -- собственно текст сообщения, набрать его там, и потом
нажать "послать".
Я об этом всём писал в отдельном топике, но народ с RSDN-а и его Web-морды
прётся, и ничего слышать не хочет.
Здравствуйте, jazzer, Вы писали:
J>не просто геттеры-сеттеры, а "пропертя" и их реализация через геттеры-сеттеры как альтернатива простым публичным членам.
Имена функций (любых, членов и свободных) должны сводиться к ГЛАГОЛУ — этот глагол не должен быть set или get. А когда я вижу аксессоры, я хватаюсь за пистолет.
Ops>Имена функций (любых, членов и свободных) должны сводиться к ГЛАГОЛУ — этот глагол не должен быть set или get. А когда я вижу аксессоры, я хватаюсь за пистолет.
Здравствуйте, IROV.., Вы писали:
IRO>Если по существу, то проектируются всегда от интерфейсов IRO>любое изменение таких данных влечет за собой измененние состояния, IRO>как минимум выставить флаг инвалидации, и в get она проверяется (так называемая линивый пересчет)
IRO>например setPosition, getMatrix IRO>setPosition выставит флаг инвалидации IRO>getMatrix пересчитает матрицу только в том случае если данные изменились, в противном вернет as is
ну и я про это, я просто не хочу писать то, что и так очевидно: set, get и эти, мать их, скобочки.
так я не против изоляции, но я ее намеренно нарушаю потому что меня раздражает писать гет, сет, скобочку сюда, скобочку туда
не тока потому что я не люблю писть то что и так очевидно, а еще потому что этот хлам мешает читать код
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Здравствуйте, MasterZiv, Вы писали:
MZ>А это оно само пишет. Я ОДИН раз это написал, оно теперь САМО это посылаяет MZ>Это если через Web писать. Так что все вопросы к программистам RSDN.
Ops>>Имена функций (любых, членов и свободных) должны сводиться к ГЛАГОЛУ — этот глагол не должен быть set или get. А когда я вижу аксессоры, я хватаюсь за пистолет.
Здравствуйте, jazzer, Вы писали:
N>>Тут есть два выхода. Можно разрешить любые неописанные операции через get-modify-set, а можно какие-то операции явно определить с реализующим их кодом, а не только get и set. Можно использовать оба. J>Ага. Сколько у нас там операторов? С десяток наберется ведь?
Ну вообще-то больше, а что?
J>И вся эта карусель лишь ради того, что "Вдруг Когда-то Где-то Кому-то" (tm) могут потребоваться сайд-эффекты.
Не "где-то кому-то могут потребоваться", а вообще принципиальная (и очень полезная) концепция представления действий с объектом через привычные действия через его именованные члены.
N>> property foo { N>> void resize(size_t newsize) { this->resize_foo(newsize); } N>> }; J>Те же проблемы, что и с операторами, только еще хуже. Это ж для всех функций-членов всех классов придется подобное писать, и для каждого свое, так что даже в макрос не упрячешь.
Почему *придётся*? Это пишется только там, где оно такое действительно запрошено. Никто не мешает совмещать этот механизм и с открытыми членами, и с геттерами, где надо.
J>Так что овчинка выделки не стоит совершенно.
В варианте, доведённом до абсурда — да, не стоит. В нормальном — не доказано.
<...> J>std::string — туши свет
Конечно, это уже за пределами их понимания, потому что ты делаешь везде копии и не подсказал компилятору никакой оптимизации.
(С другой стороны, вполне возможно, оптимизации тут есть в реализации, за счёт сохранения общего буфера строки и COW на модификации. Поэтому остаются только несколько вызовов функций, которые относительно дёшевы. Но это за пределами темы properties.)
J>// введем еще один (тривиальный) уровень сеттеров-геттеров
И тут, когда не добрались до std::string, проблем нет — всё аккуратно вычитывается напрямую по смещениям и не создаются никакие getB().
J>к слову, std::string используется из поставки компилятора, а не какой-нть из STLPort с оптимизацией коротких строк, который компилятор не сможет соптимизировать с вероятностью 99.94%.
Я не изучал разницу, но не вижу тут принципиальной проблемы. std::string сам по себе достаточно сложный зверь. Никто не обещал тотального упрощения всего и везде. Но вот сделать удобный для человека сахар для важного случая — почему бы и нет?
Ops>>Имена функций (любых, членов и свободных) должны сводиться к ГЛАГОЛУ — этот глагол не должен быть set или get. А когда я вижу аксессоры, я хватаюсь за пистолет.