LINUX.ORG.RU

Структура vs класс


0

0

Часто замечаю вот такое. Вместо

struct Name { int param1; int param2; }

используют класс с доступом к переменным через функции (set, get). В той же Qt я вообще ни разу не видел «прямой» доступ к переменным. Чем это объясняется? Почему использование функций предпочтительнее? Всё таки количества кода во втором случае явно больше.

Ответ на: комментарий от kemm

> Да, вменяемый программист сообразит

А не будет тупо менять геттер,


Ты читать не умеешь? По-русски написано трижды (видимо, специально для тебя) «нормальный» программист.

как ты тут радостно рассуждал.


Пруфлинк на «тупо» в студию, ага. Или гтфо, детка.

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

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

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

Знание того, что объект в своем интерфейсе предоставляет доступ к country не равно знанию о внтуренней структуре объекта

то есть ты можешь свободно убрать у объекта поле country и ничего не поломается?

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

>> Да, вменяемый программист сообразит, что «последствия замены File.new.each_line на DB.Connect.Request (кто все эти люди, кстати?!)» *могут* вылиться в регрессии и тормоза. И да, он сделает code review в момент изменения, прикинь? А не будет тупо менять геттер, как ты тут радостно рассуждал.

Пруфлинк на «тупо» в студию, ага. Или гтфо, детка.


Это я писал, наверное:

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

Внимание! *** мигает красная лампочка ****


*************Ни Крон73, ни его коллеги не занимались полным коде-ревью проекта ради этой фичи*************.



Иди обратно в песочницу. Вечером попроси родителей научить тебя читать.

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

> это достаточно простой пример, чтобы ты его понял?

Это достаточно простой пример, чтобы я его понял, но это не достаточно простой пример, чтобы я понял, что ты пытаешься им сказать.

Давай я расширю этот пример - мы имеем стек с заявленным размером, который хотим менять в динамике. Размер должен быть представлен геттером/сеттером?

то есть ты можешь свободно убрать у объекта поле country и ничего не поломается?


Похерить интерфейс и ожидать, что всё будет пучком? Очевидно, что нет. Какой глубокий вывод я должен сделать на основании этого риторического вопроса? Что контракты не нужны?

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

> Это я писал, наверное:

Ну и где слово «тупо»?

Твой мозг перегрелся от подсчета тактов на строку кода. Иди подыши свежим воздухом.

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

> Ну и где слово «тупо»?

Иди читать учись, не отлынивай. Если ты не способен понять, что «тупо поменял геттер» использовалось как противопоставление «проведя code review мест, где использовались данные», то мне тебя искренне жаль. Да, ник поменяй, ты себе льстишь.

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

Расслабся. Все уже поняли, что ты не понял, о чём шла речь, и сорвался на красную тряпочку «эффективности».

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

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

>«проведя code review мест, где использовались данные»

Жалостливый ты наш, сжалься ещё чуток да расскажи-ка нам, что же именно ты ожидаешь зименить на этом твоём тотальном code review? Только помни, что нормальные программисты не вызывают геттеры (и свойства) в циклах почём зря.

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

Какой глубокий вывод я должен сделать на основании этого риторического вопроса?

что геттеры не скрывают внутреннего устройства класса

Давай я расширю этот пример - мы имеем стек с заявленным размером, который хотим менять в динамике. Размер должен быть представлен геттером/сеттером?

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

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

>>> Нужна функция «загрузить объекты ХЗ откуда».

Это и называется геттером

petrosyan.svgz

А ты думаешь, геттеры - это всегда и только `getFoo() { return foo; }` ?

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

А ты думаешь, геттеры - это всегда и только

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

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

>But whenever you find yourself calling myVariable = myObject.getSomeAttribute() in order to perform some operation with that variable think if it wouldn't be better if you place that operation inside myObject's class

Тебе и автору процитированного тобой высера:

1. см вопрос для тэйлганнера

2. ты считаешь, что каждый класс, содержащий некое свойство (не о конструкции языка речь) должен уметь выполнять весь спектр операций с его (свойства) значением? И печать тоже?

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

Тебе и автору процитированного тобой высера

свободен

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

> А ты думаешь, геттеры - это всегда и только `getFoo() { return foo; }` ?

Да (впрочем, определение в студию). А еще я думаю, что геттер - это для одного объекта, а «загрузить объекты ХЗ откуда» - это для набора объектов. Разница понятна?

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

>кстати, был бы не против услышать определение. если можно

с помощью геттера получают значение свойства, с помощью сеттера устанавливают. Значение это тем или иным способом хранится.

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

>«загрузить объекты ХЗ откуда» - это для набора объектов

А если мне надо для одного объекта загрузить ХЗ откуда?

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

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

Спасибо, хоть что-то ты сделал, о чём тебя просили. Если ещё не понял — ты только что признался, что ни разу в глаза не видел хоть сколь-нибудь серьёзного проекта. Свободен.

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

> что геттеры не скрывают внутреннего устройства класса

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


Отлично!! Остался последний рывок! Надо всего лишь понять, что геттеры/сеттеры - это заявленный интерфейс. Который может быть «тупым» геттером/сеттером, но в любой момент превратиться в «умный».

Для объекта важно есть или нет геттер/сеттер. И не имеет никакого значения, что у него внутри, пусть даже он выглядит как this.field = param или return field.

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

Геттеры-сеттеры - это часть публичного интерфейса. Это в них ключевое. Всё остальное - вторично.

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

Геттер - метод, получающий данные из объекта, не изменяя его состояния. Это может быть не только getA() { return a;}

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

>> «загрузить объекты ХЗ откуда» - это для набора объектов

А если мне надо для одного объекта загрузить ХЗ откуда?

Загрузи набор из единственного объекта // К.О.

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

«Серьезный проект» - это скорость разработки которого 10 слок в неделю? Да, таких не видел. Нет, спасибо, не надо.

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

>«Серьезный проект» - это скорость разработки которого 10 слок в неделю?

Ты что, там трафик будет тыщ на десять, ведь на каждый чих нужно ревью, рефакторинг и рефинансирование.

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

> Жалостливый ты наш, сжалься ещё чуток да расскажи-ка нам, что же именно ты ожидаешь зименить на этом твоём тотальном code review?

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

Только помни, что нормальные программисты не вызывают геттеры (и свойства) в циклах почём зря.

Ты тоже жаждешь отправиться вслед за ламерками? В коде, прожившем достаточное время, порой встречаются удивительные вещи...

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

>Геттер - метод, получающий данные из объекта, не изменяя его состояния

может быть кеширование. Технически это смена состояния.

Это может быть не только getA() { return a;}

Я об этом же.

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

>Так как ни Крон73, ни его коллеги не озаботились коде-ревью и написанием тестов после кардинального изменения способа хранения данных, выясняется, что вместо 2к запросов в секунду проект способен обработать только 750

http://img7.imageshost.ru/imgs/090624/812ddeee6c/dff1a.jpg

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

>Зависит от того, что я там увижу.

и что и в каком количестве проглядишь...

Например, геттер в цикле

Уж сколько раз твердили миру: не оптимизируйте то, что не тормозит. Раз не написали сразу оптимально, то не расходуйте ресурс глаз на просмотр гектар кода, воспользуйтесь профайлером.

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

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

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

>> Загрузи набор из единственного объекта // К.О.

Почему это нельзя прозрачно сделать в геттере?

Можно, не вопрос. Только зачем? А если выгодно загрузить сразу кучу объектов - тоже в геттере будешь делать?

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

Надо всего лишь понять, что геттеры/сеттеры - это заявленный интерфейс

геттеры оправданно являются частью интерфейса (как в приведённом примере с ограниченным стеком) крайне редко, и никогда - от данных к интерфейсу; не в направлении «у нас есть поле X, надо сделать геттер getX», а в направлении «нам в интерфейсе нужен такой метод»

Который может быть «тупым» геттером/сеттером, но в любой момент превратиться в «умный».

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

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

если все примитивные значения структуры затребованы извне - то наша структура является простым аггрегатором данных (структурой, кортежом, списком, объединением). геттер в таком случае будет overdesign'ом (излишне гибкая система)

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

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

Кеш к состоянию не относится. Ты ведь не будешь его сохранять в БД при сериализации?

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

>Тяжелый случай. Чтобы оценить последствия замены File.new.each_line на DB.Connect.Request тебе необходимо засунуть в голову _весь_ проект? Сочувствую.

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

Соционика намекает, что те, кто базируется на первом подходе, одновременно должны любить с геттеры/сеттеры (склонность к БЛ). Те, кто больше любит второй вариант, любят прямое залезание в потроха (ЧЛ). В итоге у первых обычно на практике выходят надёжные и расширяемые проекты, у вторых - красивые и функциональные.

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

>Можно, не вопрос. Только зачем? А если выгодно загрузить сразу кучу объектов

Если бы было выгодно кучу - сделал бы кучу, так или иначе. О чем разговор? Но вот не выгодно кучу. По одному надо и обязательно лениво. И притом скрыть эту всю реализацию.

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

>геттеры оправданно являются частью интерфейса (как в приведённом примере с ограниченным стеком) крайне редко

ЩИТО? Т.е. stack::peek() и stack::size() - не оправдано?

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

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

Почему? Часто значение поля можно вычислить. Напрмер, реализация плюсового std::string может как иметь поле «длина», так и не иметь, но геттер size() должен быть обязательно.

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

Почему простым? Может быть сложным и даже очень сложным.

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

>> Можно, не вопрос. Только зачем? А если выгодно загрузить сразу кучу объектов

Если бы было выгодно кучу - сделал бы кучу, так или иначе.

И зачем геттер в таком случае?

О чем разговор?

О том, что геттер нужно лепить только тогда, когда он необходим.

По одному надо и обязательно лениво. И притом скрыть эту всю реализацию.

В условии задачи нет «по одному и обязательно лениво». И кстати, «по одному и лениво» можно делать и без геттера.

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

ЩИТО?

у тебя проблемы с чтением или с ЦНС?

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

Почему? Часто значение поля можно вычислить

ну и на основании чего ты будешь вычислять значение поля country? генерировать из /dev/urandom?

Может быть сложным и даже очень сложным.

в таком случае и интерфейс будет соответствующий

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

>Именно. Признайся наконец, что ты никогда не видел проектов, написанных не двумя программистами максимум, размером в сотни тысяч и миллионы LOC
[code]
# find L2J_Fortress -name '*.java' -exec cat {} \;|wc -l
254900

# find L2J_Fortress -name '*.py' -exec cat {} \;|wc -l
38882

# find L2J_Fortress -name '*.xml' -exec cat {} \;|wc -l
40842

...
[/code]

Это, конечно, не миллионы, но уже сотни тысяч. И до дюжины программеров.

с далеко ненулевым количеством legacy и костылей в целях сохранения совместимости?


И огромное количество костылей.

вылиться в регрессии и тормоза


И ко всему этому - реалтаймовость, ибо MMORPG, и невысокие требования к ресурсам, ибо говёные машинки у большинства участников.

И всё это - более двух лет.

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

> геттеры оправданно являются частью интерфейса (как в приведённом примере с ограниченным стеком) крайне редко

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

никогда - от данных к интерфейсу; не в направлении «у нас есть поле X, надо сделать геттер getX», а в направлении «нам в интерфейсе нужен такой метод»


А где я (или кто-то другой) утверждал или пропагандировал обратное? Я весь тред пытаюсь тебе (и другим) показать, что геттеры-сеттеры - удобнейший концепт _интерфейса_. Ты дискутируешь не со мной, а с кем-то еще.


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


Спасибо, кэп! Лично я к плюсатым конструкциям типа some_stuct.field++ отношусь крайне позитивно, при условии, что в структуру не засовывают методы, а поля не связаны между собой. Ты опять разговариваешь не со мной.

если же наша структура предоставляет наружу некоторый нетривиальный интерфейс (...), то при грамотном построении этого интерфейса, геттеров он содержать не будет вообще


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


Короче, ты весь тред дискутировал с собственной геттеро-сеттеро-боязнью. )))

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

>В условии задачи нет «по одному и обязательно лениво»

Условие задачи растёт отсюда: http://www.linux.org.ru/jump-message.jsp?msgid=4464779&cid=4467536

А здесь: http://www.linux.org.ru/jump-message.jsp?msgid=4464779&cid=4469229 сказано, что значение свойства нужно для отдельного объекта и само по себе, без всякой лишней хрени типа getReport()

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

> Условие задачи растёт отсюда: http://www.linux.org.ru/jump-message.jsp?msgid=4464779&cid=4467536

http://www.linux.org.ru/jump-message.jsp?msgid=4464779&cid=4472237

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

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

Ты опять разговариваешь не со мной.

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

ты весь тред дискутировал с собственной геттеро-сеттеро-боязнью

а вот это уже вряд ли. впрочем, продолжать дискуссию мне откровенно надоело, повторять по пять раз одни и те же очевидные мысли - утомляет :)

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

>А где я (или кто-то другой) утверждал или пропагандировал обратное? ... Ты дискутируешь не со мной, а с кем-то еще.

А jtootf в лучших традициях ЛОРа спорит сам с собой. Вот тут http://www.linux.org.ru/jump-message.jsp?msgid=4464779&cid=4467529 он описал на удивление маразматичный интерфейс стека и теперь его критикует.

Лично я к плюсатым конструкциям типа some_stuct.field++ отношусь крайне позитивно, при условии, что в структуру не засовывают методы, а поля не связаны между собой.

Кстати, изначально тема этой дискуссии была о том, как же выявить простые не требующие методов структуры. И если с QPoint всё ясно (геттеры сеттеры как дань унификации в рамках тулкита), то что делать с каким нибудь vector_3d, который, как мы все знаем из курса математики, может быть задан (реализован) разными способами?

Наоборот.

Похоже, что он не считает геттером/сеттером ничего кроме тупо this.field=val и return val.

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

>Первая задача сформулирована так, чтобы сделать необходимым использование геттера.

Эта формулировка, фактически, вытекает не только из ТЗ, но и даже из общей практики MVC-программирования.

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

А jtootf в лучших традициях ЛОРа спорит сам с собой

а legolegs в лучших традициях ЛОРа отыгрывает клоуна. что ж, традиции - это хорошо

Похоже

право слово, сходи к окулисту. я за тебя беспокоюсь

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

> Эта формулировка, фактически, вытекает не только из ТЗ, но и даже из общей практики MVC-программирования.

ТЗ я не читал, а из практики MVC вытекает только то, что у объекта должен быть country_code. Геттер или поле - MVC безразлично.

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

> Это, конечно, не миллионы, но уже сотни тысяч. И до дюжины программеров.

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

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

>а из практики MVC вытекает только то, что у объекта должен быть country_code. Геттер или поле - MVC безразлично

Пардон, в задаче никакого country_code не было.

Хорошо, попробуем пойти сверху, от самой задачи.

Для объектов, для использования в шаблонах, требуется возвращать название страны.

Объекты разного калибра. Сейчас у нас название страны - простая строка. Для скорости запуска раздела. Но завтра, когда будет время и когда накопится база уже введённых названий, можно будет хранить только ID страны. Ты предлагаешь делать сейчас прямое обращение к public-полю класса, а завтра переписать всё на использование метода? А если объектов в шаблон подаётся более одного вида и часть может возвращать строку как есть, а часть - генерировать? Не замучаешься переписывать? Особенно, учитывая, что, насколько я знаю, нет нормальных средств рефакторинга шаблонов? :)

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

>в геттере было изменена отдача члена класса (или что там было?) на загрузку из базы и оно всё сразу взлетело?

Бывало и такое. И нужно быть совершенно клиническим идиотом, чтобы не видеть последствий от замены прямого вывода на тяжёлый запрос и не заметить такой особенности. Нет, была у меня практика пересечения с одним таким кодом, но там, как раз, никаких геттеров/сеттеров не было. Там, вообще объектов не было :)

Или это была какая-нибудь статистика лучших игроков для веба, где этот геттер полтора раза использовался?


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

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

>геттере было изменена отдача члена класса (или что там было?) на загрузку из базы и оно всё сразу взлетело

Вспомнилось:

— Итак! — воодушевился профессор и простер руку к небесам. — Неприятности улажены! Посмотрите на слайд! На слайде мы видим так называемую вилку — металлический гарпун с четырьмя заостренными лезвиями. Хоминоиды используют его в быту для перемещения пищи в ротовое отверстие. Казалось бы, одно неловкое движение, и ротовое отверстие порвано! Распороты ткани, идет заражение! Вы же знаете, что многоклеточные организмы не восстанавливаются... Но этого не происходит! Хоминоиды хранят вилки в своих жилищах, бросают их где попало, казалось, наступи случайно... Но ни одного смертельного случая! Давайте следующий слайд!

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