LINUX.ORG.RU

1. сейчас Вам объяснят что не для каждого, а только там где нужно, и здесь я, в принципе, соглашусь
2. есть всевозможне property, но в builder свои, в visual studio свои, etc. короче непереносимо и коряво
3. можно реализовать черезкостыльное решение на стандартном C++, если интересно можно развить;
4. можно используя C++0x через variadic templates (где доступно) и функторы

shty ★★★★★
()

и да, прежде чем properties писать рекомендую ознакомиться с: Why getter and setter methods are evil

//да, статья многобуквенная, Java-ориентрованная, но концепция там рассмотрена с правильной точки зрения

shty ★★★★★
()

visual имеет подобное расширение, но только он, остальные пишут обертки для эмуляции property, которые легко гуглятся по «C++ property»

aho
()
Ответ на: комментарий от shty

> но в builder свои

а, ну и в нем видимо тоже есть, никогда просто с ним не работал

aho
()

каждый раз, когда ты думаешь «а не приделать ли мне к этому полю геттер/сеттер?», бог убивает котёнка

а может быть даже двух

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

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

VladimirMalyk ★★★★★
() автор топика
Ответ на: комментарий от jtootf

а вот это, к сожалению, типично

к сожалению типично не только это

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

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

aho
()
Ответ на: комментарий от aho

фетишизмом своих инструментов разработки

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

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

jtootf ★★★★★
()

геттеры и сеттеры в общем случае грубо нарушают инкапсуляцию

Yareg ★★★
()
Ответ на: комментарий от VladimirMalyk

>статью не читал, но уверен что публичные атрибуты лучше делать через геттер/сеттер. по той причине что внутри класса пляски вокруг атрибута могут стать нетривиальными - поэтому лучше сразу обернуть это в методы

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

yoghurt ★★★★★
()
Ответ на: комментарий от jtootf

Есть класс Point { int x; int y; }. Как не нарушать инкапсуляцию, не пользоваться геттерами/сеттерами и спасти котят?

anonymous
()
Ответ на: комментарий от anonymous

а какую Вы реализацию хотите тут скрывать? :)

в приведённом случае вместо класса идеально подойдёт структура

shty ★★★★★
()
Ответ на: комментарий от shty

>в приведённом случае вместо класса идеально подойдёт структура

А если я захочу две координаты сразу изменить? p.x=, p.y=? А если мне надо, чтобы по умолчанию объект инициализирован был? memset? А если захочу контроллировать координаты, например, мои точки могут жить только в первом квадранте. По коду искать все присваивания и размазывать if( p.x < 0 ) ...? Список можно до бесконечности продолжить.

anonymous
()
Ответ на: комментарий от anonymous

>в приведённом случае вместо класса идеально подойдёт структура

А если я захочу две координаты сразу изменить? p.x=, p.y=? А если мне надо, чтобы по умолчанию объект инициализирован был? memset? А если захочу контроллировать координаты, например, мои точки могут жить только в первом квадранте. По коду искать все присваивания и размазывать if( p.x < 0 ) ...? Список можно до бесконечности продолжить.

а если произойдёт землетрясение? да покласть тебе будет на реализацию этой точки - нет универсального решения на все случаи жизни

shty ★★★★★
()
Ответ на: комментарий от anonymous

>А если мне надо, чтобы по умолчанию объект инициализирован был? memset?

В плюсах у структур есть конструкторы, в общем-то

А если захочу контроллировать координаты, например, мои точки могут жить только в первом квадранте

Тогда закрой прямой доступ к полям

yoghurt ★★★★★
()
Ответ на: комментарий от shty

>а если произойдёт землетрясение? да покласть тебе будет на реализацию этой точки - нет универсального решения на все случаи жизни

На все случаи жизни - нет. Но есть на 80% не форсмажоров. Если оставить эту структуру в виде POD-типа - со временем будет макаронный код. Если оформить в виде класса даже с простейшими геттерами/сеттерами - можно избежать множества проблем в будущем.

anonymous
()
Ответ на: комментарий от anonymous

Если оставить эту структуру в виде POD-типа - со временем будет макаронный код. Если оформить в виде класса даже с простейшими геттерами/сеттерами - можно избежать множества проблем в будущем.

термин «spaghetti code» относится к наличию многочисленных ветвлений и переходов, затрудняющих чтение и понимание кода, не понимаю откуда они возьмутся в рассматриваемом примере и как использование аксессоров может предотвратить это

shty ★★★★★
()
Ответ на: комментарий от yoghurt

>В плюсах у структур есть конструкторы, в общем-то

Если я обвешаю структуру конструкторами и методами - это будет полноценный класс. Я как раз за это и агитирую, а не за использование POD-типов.

Тогда закрой прямой доступ к полям

А как к ним достучаться потом, ведь геттеры/сеттеры - зло?

anonymous
()
Ответ на: комментарий от shty

>термин «spaghetti code» относится к наличию многочисленных ветвлений и переходов, затрудняющих чтение и понимание кода, не понимаю откуда они возьмутся в рассматриваемом примере и как использование аксессоров может предотвратить это

Привел же пример. Пусть надо добавить контроль корректности данных, которые в точку кладутся. В случае, если доступ идет через сеттер, ветвление надо будет поставить в одном месте, если напрямую к полям - найти в коде все присваивания и размазать if'ы по всему коду.

anonymous
()
Ответ на: комментарий от yoghurt

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

Статья - бред. Как поймешь это - приходи.

anonymous
()
Ответ на: комментарий от anonymous

> Пусть надо добавить контроль корректности данных, которые в точку кладутся

если напрямую к полям - найти в коде все присваивания и размазать if'ы по всему коду


А зачем твоей программе по всему коду пытаться класть в точку некорректные данные?

fang
()
Ответ на: комментарий от fang

>А зачем твоей программе по всему коду пытаться класть в точку некорректные данные?

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

anonymous
()
Ответ на: комментарий от fang

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

VladimirMalyk ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Пусть надо добавить контроль корректности данных, которые в точку кладутся.

что за данные? почему они кладутся «в точку»? похоже тут у Вас вырисовывается ошибка проектирования, либо Вы неточно описали задачу

shty ★★★★★
()
Ответ на: комментарий от anonymous

Пожалуйста, излагай свои домыслы на тему, кто что делал или не делал и с кем/чем работал, в другом месте. Для отслеживания внутренних ошибок нормальные люди используют ассерты в наиболее замысловатых участках кода, а не if'ы лепят.

fang
()
Ответ на: комментарий от shty

>что за данные? почему они кладутся «в точку»? похоже тут у Вас вырисовывается ошибка проектирования, либо Вы неточно описали задачу

При создании типа данных «точка» - это вообще не должно тебя интересовать: что, откуда. Твоя задача, как проектировщика, обеспечить такой интерфейс, чтобы клиент (тот, кто им пользуется) не мог привести объект в некорректное состояние. Если ты говоришь, что вот вы там все просто не умеете использовать мою замечательную структуру, надо было документацию читать, и не пришлось бы пару дней искать баг - то вот это и есть ошибка проектирования.

anonymous
()
Ответ на: комментарий от VladimirMalyk

Это обычная проверка валидности введённых пользователем данных. Делается в одном месте, и сразу же выводится сообщение об ошибке. Зачем такую проверку надо вглубь запихивать, не очень понятно.

fang
()
Ответ на: комментарий от fang

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

Ты вообще понимаешь о чем речь? Какая разница, как ты контролируешь корректность - if/return, if/throw, assert. Вопрос - размазать проверки по всему коду или вставить в единственный сеттер. «Замысловатые участки кода» - это для тех, кто научился ошибаться только в строго отведенных местах, а в остальной части программы усилием воли заставляет себя не делать их. И других заставляет так. И за изменениями в коде следит постоянно, чтобы отслеживать «замысловатости».

anonymous
()
Ответ на: комментарий от fang

>Это обычная проверка валидности введённых пользователем данных. Делается в одном месте, и сразу же выводится сообщение об ошибке. Зачем такую проверку надо вглубь запихивать, не очень понятно.

Ты что, математически доказываешь корректность всех своих вычислений и поэтому проверки не ставишь? Или надеешься, что «уж дальше-то я не напартачу».

anonymous
()
Ответ на: комментарий от fang

хм, и придется в каждой экранной форме каждый раз заново писать валидаторы для этого типа данных. не проще сделать это один раз в правильном месте?

VladimirMalyk ★★★★★
() автор топика
Ответ на: комментарий от VladimirMalyk

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

bool Warehouse::post(const goods& g) {

    if ( !guard_positive(g->weight()) ) {
        return false;
    }

    this->accept(g);
    return true;
}

ну и нафиг тут аксессоры?

shty ★★★★★
()
Ответ на: комментарий от anonymous

При создании типа данных «точка» - это вообще не должно тебя интересовать: что, откуда.

что, правда что-ли? :)

Твоя задача, как проектировщика, обеспечить такой интерфейс, чтобы клиент (тот, кто им пользуется) не мог привести объект в некорректное состояние.

1. защиты от дурака всё равно не существует
2. как можно испортить:

struct point {

    point(int x_, int y_) 
        : x(x_), y(y_) { }

    int x; 
    int y;

};

ответ - никак

shty ★★★★★
()
Ответ на: комментарий от VladimirMalyk

А если поля хитро связаны, и валидность проверяется для всего объекта целиком? А если из за этого невозможно независимо задать поля корректным образом (пытаешь менять одно поле, другое еще некорректно и получаешь через сеттер отлуп)? А как эти проперти работают во всяких выражениях (там из за них бывает мноооого глюков)?

Для проверки валидности тупо заводится метод bool check()

Если поля так уж нужно закрывать, закрываешь и вешаешь на каждое методы чтения/записи. Как вариант - открываешь поле для чтения через const reference и делаешь метод init согласованно устанавливающий нужные поля.

AIv ★★★★★
()
Ответ на: комментарий от yoghurt

>Может аргументируешь столь многозначительный вывод? Мне очень интересно послушать!

Свойство объекта - это нормальное и естественное понятие в ООП, оно нисколько ни evil. Другое дело, что его можно употребить во зло и вместо улучшения инкапсуляции - понизить ее, вывернув кишки объекта, когда это совершенно не нужно. А в статье идет надуманное противопоставление интерфейса и свойств объекта. Огульный совет ОПу - «не используй аксессоры - оно инкапсуляцию нарушает» так же бесполезен, как и «не используй наследование - оно связность повышает».

anonymous
()
Ответ на: комментарий от shty

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

VladimirMalyk ★★★★★
() автор топика
Ответ на: комментарий от AIv

> А если поля хитро связаны, и валидность проверяется для всего объекта целиком?

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

Если поля так уж нужно закрывать, закрываешь и вешаешь на каждое методы чтения/записи


собственно, геттеры и сеттеры это и есть

VladimirMalyk ★★★★★
() автор топика
Ответ на: комментарий от VladimirMalyk

этот guard_positive придется описать для любых операций со складом

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

shty ★★★★★
()
Ответ на: комментарий от shty

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

VladimirMalyk ★★★★★
() автор топика
Ответ на: комментарий от anonymous

> Есть класс Point { int x; int y; }. Как не нарушать инкапсуляцию, не пользоваться геттерами/сеттерами

Если класс Point представляет абстракцию точки в декартовых координатах, то методы int x(), void set_x(int) не нарушают инкапсуляцию и в принципе геттерами/сеттерами не являются - это часть абстракции декартовой точки.

В свою очередь реализация класса Point может использовать для представления, например, радиус и угол, а методы int x(), void set_x(int) останутся.

-- another anonymous

anonymous
()
Ответ на: комментарий от shty

> ну и нафиг тут аксессоры?

Нафиг тут вообще проверка? goods сам должен не допускать отрицательного веса.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.