Какова точная проблема с разрешением добытчиков?

15

Я не ищу мнение о семантике, а просто для случая, когда разумно использовать геттеры - это реальное препятствие. Может быть, это бросает меня в бесконечную спираль доверия к ним, может быть, альтернатива чище и автоматически обрабатывает добытчики, и т.д. Что-то конкретное.

Я слышал все аргументы, я слышал, что они плохие, потому что они заставляют вас рассматривать объекты как источники данных, что они нарушают «чистое состояние» объекта «не выдавайте слишком много, но будьте готовы принять много ".

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

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

Конечно, использование геттера для строки, которая используется для шифрования чего-либо, выходит за рамки глупости, но я говорю о данных, которые необходимы для работы вашей системы. Возможно, ваши данные извлекаются через объект Providerиз объекта, но, тем не менее, объекту все еще нужно разрешить, Providerчтобы сделать это $provider[$object]->getData, нет никакого способа обойти это.


Почему я спрашиваю: для меня геттеры, когда они используются разумно и на данных, которые рассматриваются как «безопасные», отправляются богом, 99% моих геттеров используются для идентификации объекта, как, я спрашиваю, с помощью кода Object, what is your name? Object, what is your identifier?, любой, кто работает с объектом, должен знать эти вещи об объекте, потому что почти все в программировании - это личность, а кто еще знает, что это такое, чем сам объект? Поэтому я не вижу никаких реальных проблем, если вы не пурист.

Я рассмотрел все вопросы StackOverflow о том, «почему геттеры / сеттеры» плохи, и хотя я согласен, что сеттеры действительно плохи в 99% случаев, геттеры не должны рассматриваться одинаково только потому, что они рифмуются.

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

coolpasta
источник
2
Мой совет - забудьте большую часть теории ОО. Практика. Написать много кода, а затем поддерживать его. Вы узнаете намного, намного, гораздо больше о том, что работает хорошо, а что нет, если вы действительно что-то делаете, а потом вернетесь к этому через несколько месяцев.
jpmc26
1
@ jpmc26 Что в матери .... Я никогда не осознавал, что никто из нас на самом деле не делает ООП правильно, у меня всегда было это понятие инкапсуляции, строго относящееся к полям объекта, но сам объект является состоянием и находится в процессе свободно распространяются Подлинно все делают ООП неправильно, то есть, скорее, ООП невозможно, если парадигма - объекты. Я использую ООП строго, чтобы выразить, как работает система, и никогда не рассматривал ее как святой Грааль или как ТВЕРДЫЙ. Это всего лишь инструменты, которые я использую в основном для определения достаточно хорошо разработанной (посредством реализации) моей концепции. Кто-нибудь читает, если это правильно?
coolpasta
2
--cont, Чем больше я пишу, тем больше я понимаю, что программирование - это возможность абстрагироваться настолько, насколько это необходимо, чтобы рассуждать другим, а также вам о вашей кодовой базе. Конечно, техническая сторона этого - убедиться, что вы делаете правильные проверки / устанавливаете правильные правила. По правде говоря, тот, кому удастся заставить других лучше понять их код, побеждает. Убедитесь, что это имеет смысл для любого, кто читает его, а затем убедитесь, что он не потерпит неудачу, правильно сегментируя объекты с интерфейсами, проверяет и переключается на другие парадигмы, когда с ними легче рассуждать: будьте гибкими.
coolpasta
2
Это похоже на трубочиста для меня. Я не верю, что какой-либо серьезный разработчик, который на самом деле пишет полезный код, будет утверждать, что разумное использование геттеров - проблема Вопрос подразумевает, что геттеры могут использоваться разумно, что также подразумевает, что геттеры могут быть разумными. Вы ищете кого-то, чтобы сказать, что нет разумного использования добытчиков? Вы будете ждать некоторое время.
JimmyJames
2
@coolpasta Ты прав. Мне все равно, если это чистый ООП. Просто лучше Дайте мне выбор между испорченным кодом, который может понять человек, и безупречным кодом, который не поддается шифрованию, и который я не буду расшифровывать, и я буду каждый раз принимать удобный для человека код. ООП полезен ТОЛЬКО для меня, когда он уменьшает количество вещей, о которых я должен думать в любой момент. Это единственная причина, по которой мне это нравится по сравнению с простой процедурной процедурой. Без этого вы просто заставляете меня без причины прыгать через несколько файлов исходного кода.
candied_orange

Ответы:

22

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

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

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

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

Настоящий ООП - это не то, что вы можете распространять повсюду Это работает только в этих границах.

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

Майкл Феттерс назвал этот код фасции в честь этой белой соединительной ткани, которая скрепляет участки апельсина.

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

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

Простой пример границы - это коллекция. Это что-то держит и понятия не имеет, что это такое. Как дизайнер коллекции мог бы перемещать поведенческую функциональность удерживаемого объекта в коллекцию, когда он не знает, что он будет держать? Ты не можешь Ты против границы. Именно поэтому в коллекциях есть геттеры.

Теперь, если бы вы знали, вы могли бы изменить это поведение и избежать изменения состояния. Когда вы знаете, вы должны. Ты просто не всегда знаешь.

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


Вы заявили, что не хотите слышать семантические аргументы и, похоже, отстаиваете повсеместное использование «разумных добытчиков». Вы просите, чтобы эта идея была оспорена. Я думаю, что могу показать, что у идеи есть проблемы с тем, как вы ее сформулировали. Но мне кажется, я знаю, откуда ты, потому что я был там.

Если вы хотите, чтобы получатели везде смотрели на Python. Частного ключевого слова нет. Тем не менее, Python прекрасно работает. Как? Они используют смысловой трюк. Они называют все, что должно быть частным, с ведущим подчеркиванием. Вам даже разрешают читать, если вы берете на себя ответственность за это. «Мы все здесь взрослые», - часто говорят они.

Так в чем же разница и просто помещать геттеры на все в Java или C #? Извините, но это семантика. Согласие Питона подчеркивает, что вы ясно видите, что вы ковыряетесь за дверью сотрудников. Хлопайте добытчики на все, и вы теряете этот сигнал. С отражением вы могли бы в любом случае лишиться частного и все же не потерять смысловой сигнал. Здесь просто нет структурного аргумента.

Так что нам остается решить, куда повесить табличку «только для сотрудников». Что следует считать приватным? Вы называете это "разумными добытчиками". Как я уже сказал, лучшее оправдание для добытчика - это граница, которая отталкивает нас от наших идеалов. Это не должно привести к получению на все. Когда это приводит к получению, вы должны подумать о том, чтобы продвинуть поведение дальше в область, где вы можете его защитить.

Это разделение породило несколько условий. Объект передачи данных или DTO не содержит поведения. Единственными методами являются методы получения, а иногда и установки, иногда конструктора. Это имя неудачное, потому что это совсем не настоящий объект. Получатели и установщики на самом деле являются просто отладочным кодом, который дает вам возможность установить точку останова. Если бы не было этой необходимости, они были бы просто кучей публичных полей. В C ++ мы называли их структурами. Единственное отличие, которое они имели от класса C ++, заключалось в том, что они по умолчанию были общедоступными.

DTO хороши тем, что вы можете перебросить их через граничную стену и сохранить другие ваши методы безопасно в приятном сочном объекте поведения. Настоящий объект. Без получателей, чтобы нарушить его инкапсуляцию. Мои объекты поведения могут есть DTO, используя их в качестве объектов параметров . Иногда мне приходится делать защитную копию, чтобы предотвратить общее изменяемое состояние . Я не распространяю изменяемые DTO внутри сочной части внутри границы. Я заключаю их в капсулу. Я их скрываю И когда я, наконец, сталкиваюсь с новой границей, я раскручиваю новый DTO и бросаю его через стену, создавая, таким образом, чужую проблему.

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

В конце концов, это не существование добытчиков, что неправильно. Они намного лучше, чем публичные поля. Что плохо, когда они используются, чтобы притворяться, что вы объектно-ориентированы, а вы нет. Геттерс это хорошо. Быть объектно-ориентированным - это хорошо. Получатели не являются объектно-ориентированными. Используйте добытчики, чтобы вырезать безопасное место, чтобы быть объектно-ориентированным.

candied_orange
источник
Именно поэтому я спросил, и я не уверен, что мой разговор виден с Робертом, я также пытался выяснить конкретный случай, когда мне явно больно использовать «разумных добытчиков». Я для себя не согласен с сеттерами, потому что, по крайней мере, для себя очень сложно приписать владение таким действиям, я привык использовать сеттеры во всем, и к тому времени я понял, что даже один сеттер, когда на него воздействует слишком много объектов, убивает я ... Я должен был переписать все. Разумное использование геттеров, после исчерпывающего тестирования в течение столь длительного времени, серьезно не имеет недостатков, если вы не пурист.
coolpasta
1
@coolpasta вы можете создавать объекты владельца данных. Объекты-владельцы данных являются объектами данных, но они разработаны и названы так, что они (ясно) владеют данными. Конечно, эти объекты будут иметь добытчики.
Руонг
1
@ rwong Что ты имеешь в виду clearly? Если данные передаются мне от чего-то, по значению , ясно, что мой объект теперь владеет данными, но по семантике он еще не, на данный момент он просто получил данные от кого-то другого. Затем он должен выполнить операции для преобразования этих данных, сделав их своими собственными, в момент касания данных вы должны внести семантические изменения: у вас есть данные, названные как, $data_from_requestи теперь вы оперировали с ними? Назовите это $changed_data. Вы хотите раскрыть эти данные другим? Создайте геттер getChangedRequestData, тогда право собственности четко установлено. Или это?
coolpasta
1
«Вы не можете написать хороший код без получателей». Это совершенно неправильно, как и представление о том, что границы по своей природе нужны добытчики. Это не прагматизм, просто лень. Это совсем немного легче просто выбросить данные через забор и сделать с ней, думая о потребительных случаях и проектирование хороший поведенческой апи это трудно.
Роберт
2
Отличный ответ!
cmaster - восстановить
10

Сборщики нарушают Голливудский принцип («Не звоните нам, мы вам позвоним»)

Голливудский принцип (он же Inversion of Control) гласит, что вы не вызываете библиотечный код для достижения цели; скорее, фреймворк вызывает ваш код. Поскольку среда управляет вещами, передача своего внутреннего состояния своим клиентам не требуется. Вам не нужно знать.

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

Использование геттера подразумевает, что вам нужно это значение, а на самом деле это не так.

Возможно, вам действительно нужно это улучшение производительности

В крайних случаях легких объектов, которые должны иметь максимально возможную производительность, возможно (хотя и крайне маловероятно), что вы не сможете заплатить очень маленькое снижение производительности, налагаемое геттером. Это не произойдет в 99,9% случаев.

Роберт Харви
источник
1
Я понимаю и буду летать с твоей правдой, которую мне не нужно знать. , Но я достиг места, где мне нужно. У меня есть Generatorобъект, который проходит через все мои Itemsобъекты, а затем вызывает getNameкаждый из них, Itemчтобы сделать что-то еще. В чем проблема с этим? Затем, в ответ, Generatorвыплевывает отформатированные строки. Это в моей структуре, для которой у меня тогда есть API, который люди могут использовать для запуска всего, что предоставляют пользователи, но не касаясь структуры.
coolpasta
3
What is the issue with this?Ничего такого, что я вижу. По сути, это то, что mapделает функция. Но это не тот вопрос, который вы задали. Вы по существу спросили: «Существуют ли условия, при которых добытчик может быть нежелательным». Я ответил двумя, но это не значит, что вы вообще отказываетесь от сеттеров.
Роберт Харви
1
Вы задаете этот вопрос не тому парню. Я прагматик; Я делаю все, что лучше всего подходит для моих конкретных программ, и не ставлю много на «принципы», если они не служат моим целям.
Роберт Харви
2
@ jpmc26: рамки. Не библиотеки.
Роберт Харви
2
Фреймворк - это попытка превратить язык общего назначения в предметно-ориентированный. Библиотека - это коллекция многократно используемых алгоритмов. Любой из них попросит вас зависеть от этого. Вам решать, хотите ли вы жестко кодировать зависимость или сделать ее легко заменяемой.
candied_orange
2

Детали реализации утечки геттеров и абстракция разрыва

Рассмотреть возможность public int millisecondsSince1970()

Ваши клиенты будут думать: «О, это int», и будет раздача кол-ва вызовов, предполагающих, что это int , выполнение целочисленных математических сравнений дат и т. Д. Когда вы поймете, что вам нужно long , будет много устаревшего кода с проблемами. В мире Java вы добавляете @deprecatedAPI, все его игнорируют, и вы застряли в поддержке устаревшего, глючного кода. :-( (я предполагаю, что другие языки похожи!)

В этом конкретном случае я не уверен, что может быть лучшим вариантом, и ответ @candiedorange полностью уместен, во многих случаях вам нужны геттеры, но этот пример иллюстрирует недостатки. Каждый публичный получатель стремится «запереть» вас в определенной реализации. Используйте их, если вам действительно нужно «пересечь границы», но используйте как можно меньше, с осторожностью и предусмотрительностью.

user949300
источник
Это правда, но каково шаблонное решение для принудительного применения типа / структуры данных к переменной объекта, а также ко всему, что использует геттер для этой переменной?
coolpasta
1
Этот пример иллюстрирует другое явление, примитивную одержимость. В настоящее время большинство библиотек и фреймворков имеют классы, которые представляют timepointи timespanсоответственно. ( epochявляется конкретным значением timepoint.) В этих классах они предоставляют методы получения, такие как getIntили getLongили getDouble. Если классы, которые манипулируют временем, написаны так, что они (1) делегируют арифметику, связанную со временем, этим объектам и методам и (2) предоставляют доступ к этим объектам времени через геттеры, тогда проблема решается без необходимости избавления от геттеров. ,
Rwong
1
Подводя итог, геттеры являются частью API, и поэтому геттеры должны разрабатываться с учетом всех последствий, включая прошлые, текущие и будущие. Но это не приводит к выводу об избежании или минимизации количества получателей. Фактически, если в будущем потребуется доступ к определенной части информации, для которой опущен метод получения, это потребовало бы изменения API на стороне библиотеки и изменения кода. Таким образом, решение о том, следует ли реализовывать или избегать конкретного получателя, должно основываться на области и намерении, а не на превентивной причине.
Rwong
1
"millisecondsSince1970" перестал работать для 32-битных целых до конца января 1970 года, поэтому я сомневаюсь, что будет много кода, использующего его :-)
gnasher729
1
@ rwong В некоторой степени правильно, но вы предполагаете, что предпочтительные библиотеки, представляющие временные точки, стабильны. Которые они не. Например, moment.js
user949300
1

Я думаю, что первый ключ - помнить, что абсолюты всегда неправы.

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

Будет Personкласс, который содержит фактические данные: имя, адрес, номер телефона и т. Д., AddressИ Phoneтоже классы, поэтому мы можем использовать полиморфизм позже для поддержки неамериканских схем. Все три из этих классов являются объектами передачи данных , поэтому они будут не более чем геттерами и сеттерами. И это имеет смысл: в них не будет никакой логики, кроме переопределения equalsи getHashcode; просить их представить вам полную информацию о человеке не имеет смысла: для HTML-презентации, пользовательского приложения с графическим интерфейсом, консольного приложения, конечной точки HTTP и т. д.?

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

Контроллер собирается внедрить сервис, который будет предоставлять такие методы, как getи save, оба из которых будут принимать некоторые разумные аргументы (например, getмогут иметь переопределения для поиска по имени, поиска по почтовому индексу или просто получить все; saveвероятно, потребуется один Personи сохранить его). Какие геттеры будут иметь контроллер? Возможность получения имени конкретного класса может быть полезна для ведения журнала, но какое состояние он будет содержать, кроме состояния, которое было введено в него?

Точно так же сервисный уровень получит встроенный репозиторий, поэтому он может получать и сохранять данные Person, и у него может быть некоторая «бизнес-логика» (например, возможно, мы собираемся требовать, чтобы у всех Personобъектов был хотя бы один адрес или телефон число). Но опять же: в каком состоянии находится этот объект, кроме того, что вводится? Опять нет.

На уровне хранилища все становится немного интереснее: он собирается установить соединение с хранилищем, например. файл, база данных SQL или хранилище в памяти. Здесь соблазнительно добавить геттер для получения имени файла или строки соединения SQL, но это состояние, которое было введено в класс. Должен ли репозиторий иметь геттер, чтобы определить, успешно ли он подключен к своему хранилищу данных? Ну, может быть, но какая польза от этой информации вне самого класса репозитория? Сам класс репозитория должен быть в состоянии попытаться переподключиться к своему хранилищу данных, если это необходимо, что говорит о том, что isConnectedсвойство уже имеет сомнительную ценность. Кроме того, isConnectedсвойство, вероятно, будет неправильным именно тогда, когда оно наиболее необходимо: проверкаisConnectedпрежде чем пытаться получить / сохранить данные, не гарантирует, что хранилище все еще будет подключено, когда будет выполнен «настоящий» вызов, поэтому это не устраняет необходимость обработки исключений где-то (есть аргументы для того, куда это должно идти, помимо объем этого вопроса).

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

TL; DR

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

minnmass
источник
Я нахожу эту линию мышления очень похожей на дискуссию о правильном использовании свойств C #. Короче говоря, свойства (которые могут быть только getter или getter-setter-pair) должны поддерживать определенный контракт, такой как «то, что вы устанавливаете - это то, что вы получаете», «getter должен быть в основном без побочных эффектов», «метод получения должен избегать ошибок» и т. д. Вопреки вашему заключению, существует много состояний объектов, которые выгодно представлять как свойства (или методы получения). Примеров слишком много, чтобы цитировать здесь.
Rwong
2
@ rwong Мне было бы интересно узнать некоторые примеры, скажем, для «нормального» «корпоративного» приложения, реализуемого одной командой. Предположим также, что для простоты не задействованы третьи стороны. Вы знаете, автономная система, как календарь, зоомагазин, все, что вы хотите.
Роберт
1

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

Изменчивые участники.

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

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

Действительно плохим примером будет объект, который считает от 1 до 100, выставляя свое Текущее значение в качестве изменяемой ссылки. Это позволяет стороннему объекту изменять значение Current таким образом, чтобы значение могло лежать за пределами ожидаемых границ.

Это в основном проблема с отображением изменчивых объектов. Разоблачение структур или неизменяемых объектов не является проблемой вообще, поскольку любые изменения в них изменят вместо этого копию (обычно либо неявной копией в случае структуры, либо явной копией в случае неизменяемого объекта).

Использовать метафору, которая может помочь увидеть разницу.

У цветка есть несколько уникальных вещей. Он имеет Colorи имеет несколько лепестков (NumPetals). Если я наблюдаю за этим цветком в реальном мире, я ясно вижу его цвет. Затем я могу принимать решения на основе этого цвета. Например, если цвет черный, не дайте подруге, но если цвет красный, дайте подруге. В нашей объектной модели цвет цветка будет выставлен как получатель на объекте цветка. Мои наблюдения за этим цветом важны для действий, которые я буду выполнять, но это никак не влияет на объект цветка. Я не должен быть в состоянии изменить цвет этого цветка. Точно так же не имеет смысла скрывать свойство color. Цветок, как правило, не может помешать людям наблюдать его цвет.

Если я окрашиваю цветок, я должен вызвать метод ReactToDye (Color dyeColor) для цветка, который изменит цветок в соответствии с его внутренними правилами. Затем я могу снова запросить Colorсвойство и отреагировать на любое изменение в нем после вызова метода ReactToDye. Было бы неправильно для меня напрямую модифицировать Colorцветок, и если бы я мог, тогда абстракция сломалась.

Иногда (реже, но все же достаточно часто, что стоит упомянуть) сеттеры являются вполне допустимым ОО-дизайном. Если у меня есть объект Customer, вполне допустимо выставить сеттер для их адреса. Называете ли вы это setAddress(string address)или ChangeMyAddressBecauseIMoved(string newAddress)просто string Address { get; set; }вопрос семантики. Внутреннее состояние этого объекта должно измениться, и соответствующий способ сделать это - установить внутреннее состояние этого объекта. Даже если мне потребуется историческая запись адресов, в которых Customerон жил, я могу использовать установщик, чтобы соответствующим образом изменить свое внутреннее состояние. В этом случае не имеет смысла Customerбыть неизменным, и нет лучшего способа изменить адрес, чем предоставить установщик для этого.

Я не уверен, кто предполагает, что геттеры и сеттеры являются плохими или нарушают объектно-ориентированные парадигмы, но если они это делают, они, вероятно, делают это в ответ на специфическую языковую функцию языка, который они используют. У меня возникает ощущение, что это выросло из Java-культуры "все является объектом" (и, возможно, распространялось на некоторые другие языки). Мир .NET вообще не обсуждает это. Методы получения и установки - это первоклассная языковая функция, которая используется не только людьми, пишущими приложения на этом языке, но и самим языковым API.

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

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

Стивен
источник
-1

Какая вещь, без мнений, сломается, если я использую добытчики ...

Ремонтопригодность сломается.

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

Давайте рассмотрим Collectionпример @ candied_orange . Вопреки тому, что он пишет, Collection не должно быть добытчика. Коллекции существуют по очень конкретным причинам, прежде всего для перебора всех элементов. Эта функциональность ни для кого не является неожиданностью, поэтому она должна быть реализована Collectionвместо того, чтобы навязывать пользователю этот очевидный вариант использования, используя циклы for и методы получения или чего-либо еще.

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

Роберт Бройтигам
источник
1
Контрпример. Рассмотрим функцию, которая должна повторять две Collections одновременно, как в (A1, B1), (A2, B2), .... Это требует реализации "почтового индекса". Как вы реализуете «zip», если на одном из двух реализована функция повторного наложения Collection- как получить доступ к соответствующему элементу в другом?
rwong
@rwong CollectionРеализует zipсам с собой, в зависимости от того, как написана библиотека. Если этого не произойдет, вы реализуете его и отправляете запрос на извлечение создателю библиотеки. Обратите внимание, что я согласился, что некоторым границам иногда нужны геттеры, моя настоящая проблема в том, что геттеры сейчас везде.
Роберт
В этом случае это означает, что библиотека должна иметь геттеры на Collectionобъекте, по крайней мере, для собственной реализации zip. (То есть получатель должен как минимум иметь видимость пакета.) И теперь вы зависите от того, будет ли создатель библиотеки принять ваш запрос на извлечение ...
rwong
Я не совсем тебя понимаю. Collection, Очевидно , имеет доступ к своему внутреннему состоянию, или быть более точными любой Collectionэкземпляр может получить доступ к внутреннему состоянию любому другому. Это тот же тип, не нужны добытчики.
Роберт
Я тоже вас слышу, но опять же, что именно является лучшим решением для добытчиков? Я знаю, что это выходит за рамки вопроса.
coolpasta