Яка точна проблема із дозволом набуття геттерів?


15

Я не шукаю думки про семантику, а просто на випадок, коли розумно використовуються геттери - це фактична перешкода. Можливо, це підштовхує мене до нескінченної спіралі, покладаючись на них, можливо, альтернатива є чистішою і автоматично обробляє геттери тощо. Щось конкретне.

Я чув усі аргументи, я чув, що вони погані, оскільки вони змушують вас ставитися до об'єктів як до джерел даних, що вони порушують "чистий стан" об'єкта ", не видайте занадто багато, але будьте готові багато приймай ".

Але абсолютно немає розумних причин, чому а getData- це погана річ, насправді, кілька людей стверджували, що це багато про семантику, про геттери як на самому себе, але просто не називайте їх getX, мені це принаймні смішно .

Що одного, без думок, що зламається, якщо я розумно використовую гетерів та для даних, які явно цілісність об'єкта не порушується, якщо він виводить його?

Зрозуміло, що дозволити геттеру для рядка, який використовується для шифрування чогось, - це не так глухо, але я говорю про дані, необхідні для роботи вашої системи. Можливо, ваші дані витягуються через Providerоб'єкт, але, все-таки, об'єкт все ще повинен дозволити Providerвиконувати завдання $provider[$object]->getData, його немає.


Чому я запитую: мені, коли геть, коли розумно використовуються дані та трактуються як "безпечні", надсилаються богом, 99% моїх гетерів використовуються для ідентифікації об'єкта, як, наприклад, я запитую, за допомогою коду Object, what is your name? Object, what is your identifier?, кожен, хто працює з об'єктом, повинен знати ці речі про об'єкт, тому що майже все про програмування - це ідентичність, а хто ще краще знає, що це таке, ніж сам об’єкт? Тож я не бачу жодних реальних проблем, якщо ви не пурист.

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

Сеттер скомпрометує особистість вашого об'єкта і зробить дуже важким налагодження того, хто змінює дані, але геттер нічого не робить.


2
Моя порада - забути більшу частину теорії ОО. Практика. Напишіть багато коду, а потім підтримуйте його. Ви дізнаєтесь далеко-далеко, набагато більше про те, що добре працює, а що не насправді щось робити, а потім повернетесь до нього через кілька місяців.
jpmc26

1
@ jpmc26 Що в матері .... Я ніколи насправді не усвідомлював, що ніхто з нас насправді не робить OOP правильно, у мене завжди було таке поняття інкапсуляції, яке суворо стосується полів об'єкта, але сам об'єкт є станом і існує вільно ділитися. Насправді всі роблять OOP неправильно, то, вірніше, OOP неможливий, якщо парадигма є об'єктами. Я використовую OOP строго, щоб висловити, як працює система, і ніколи не ставився до неї як до святого грааля, ні до твердого. Вони просто інструменти, які я використовую здебільшого для визначення досить добре розширеної (через впровадження) моєї концепції. Хтось читає, чи правильно це?
coolpasta

2
--cont, Чим більше я пишу, тим більше я усвідомлюю, що програмування - це те, що можна абстрагуватися стільки, скільки потрібно, щоб мати можливість міркувати перед іншими, а також про вашу базу даних коду. Звичайно, технічна сторона цього - переконайтеся, що ви виконуєте належні перевірки / встановлюєте правильні правила. По правді кажучи, той, хто зуміє змусити інших зрозуміти їх код, краще виграє. Переконайтесь, що він має сенс для кожного, хто читає його, а потім переконайтеся, що він не виходить з ладу, правильно сегментуючи об’єкти з інтерфейсами, перевіряючи та перемикаючись на інші парадигми, коли з ними легше міркувати: будьте гнучкими.
coolpasta

2
Мені це здається солом'яним. Я не вірю, що жоден серйозний розробник, який насправді пише корисний код, може стверджувати, що розумне використання геттерів є проблемою. Питання передбачає, що геттерів можна використовувати розумно, що надалі означає, що геттери можуть бути розумними. Ви шукаєте когось, хто скаже, що не має розумного використання гетерів? Ви будете чекати деякий час.
JimmyJames

2
@coolpasta Ви маєте рацію. Мені дуже не байдуже, чи це чисто OOP. Просто краще. Дайте мені вибір між розбитим кодом, який можна зрозуміти людям проти бездоганного кохаючого процесора коду, який є нерозбірливим, і я буду приймати людський код щоразу. OOP для мене ЛИШЕ корисний, коли він зменшує кількість речей, про які я повинен думати в будь-який момент. Це єдина причина, що мені це подобається через просту процедурну процедуру. Без цього ви просто змушуєте мене без жодної причини перескакувати декілька файлів вихідного коду.
candied_orange

Відповіді:


22

Ви не можете написати хороший код без геттерів.

Причина цього не відбувається через те, що геттери не порушують інкапсуляцію, вони це роблять. Це не тому, що мешканці не спокушають людей не турбуватись за OOP, що дозволить їм поставити методи з даними, на які вони діють. Вони роблять. Ні, вам потрібні жителі через межі.

Ідеї ​​інкапсуляції та збереження методів разом із даними, на які вони діють, просто не спрацьовують, коли ви стикаєтесь з межею, яка перешкоджає переміщенню методу і тим самим змушує вас переміщувати дані.

Це дійсно так просто. Якщо ви користуєтеся геттерами, коли немає меж, у вас виявляється відсутність реальних об'єктів. Все починає тяжіти до процесуального. Що працює так само добре, як і коли-небудь.

True OOP - це не те, що можна поширити скрізь. Це працює лише в тих межах.

Ці межі не є бритвою. У них є код. Цей код не може бути OOP. Він також не може бути функціональним. Жоден цей код не позбавлений наших ідеалів, щоб він міг боротися з суворою реальністю.

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

Це чудовий спосіб подумати над цим. Це пояснює, чому нормально обидва види коду в одній базі коду. Без цієї перспективи багато нових програмістів важко чіпляються за свої ідеали, а потім розбивають серце і відмовляються від цих ідеалів, коли вони потрапляють на свою першу межу.

Ідеали працюють лише на своєму місці. Не здавайся на них лише тому, що вони працюють не скрізь. Використовуйте їх там, де вони працюють. Це місце - соковита частина, яку захищає фасція.

Простий приклад межі - колекція. Це щось тримає і поняття не має, що це таке. Як дизайнер колекції міг би перенести функцію поведінки утримуваного об'єкта в колекцію, коли вони не мають уявлення про те, що це буде? Ви не можете. Ти проти межі. Саме тому в колекціях є геттери.

Тепер, якщо б ви знали, ви можете змінити таку поведінку і уникнути переходу в стан. Коли ти це знаєш, ти повинен. Ви просто не завжди знаєте.

Деякі люди просто називають це прагматичним. І воно є. Але приємно знати, чому ми повинні бути прагматичними.


Ви висловили, що не хочете чути смислові аргументи і, схоже, виступаєте за те, щоб скрізь ставити "розумних". Ви просите оскаржити цю ідею. Я думаю, що я можу показати, що ідея має проблеми з тим, як ви її оформили. Але він також вважає, що я знаю, звідки ти родом, бо я був там.

Якщо ви хочете, щоб гетері були скрізь, подивіться на Python. Приватного ключового слова немає. Але Python робить OOP просто чудовим. Як? Вони використовують смисловий трюк. Вони називають все, що означало б бути приватним, з головним підкресленням. Вам навіть дозволяється читати з нього, якщо ви берете на себе відповідальність за це. «Ми всі тут дорослі», - часто кажуть вони.

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

Отже, нам залишається завдання вирішити, де повісити знак "лише працівникам". Що слід вважати приватним? Ви називаєте це "розумними геттерами". Як я вже говорив, найкращим виправданням для геттера є межа, яка відштовхує нас від наших ідеалів. Це не повинно спричинити за собою все. Коли це призведе до отримання геттера, вам слід подумати про те, щоб перенести поведінку далі в соковитий шматочок, де ви можете захистити це.

Цей поділ породив кілька термінів. Об'єкт передачі даних або DTO не має поведінки. Єдині методи - це геттери, а іноді і сетери, іноді конструктори. Це ім'я прикро, тому що це зовсім не справжній об’єкт. Геттери і сетери - це просто код налагодження, який дає вам місце для встановлення точки перерви. Якби не ця потреба, вони просто були б купою громадських полів. У C ++ ми називали їх структурами. Єдина відмінність, яку вони мали від класу C ++, полягала в тому, що вони були дефолтними для загального користування.

DTO є приємними, тому що ви можете перекинути їх через прикордонну стіну і зберегти ваші інші методи безпечно у приємному соковитому об'єкті поведінки. Справжній об’єкт. Не маючи порушників, це порушує його інкапсуляцію. Мої об'єкти поведінки можуть їсти DTO, використовуючи їх як об'єкти параметрів . Іноді мені доводиться робити захисну копію, щоб запобігти спільному зміненному стану . Я не поширюю змінні DTO навколо всередині соковитої частини в межах. Я їх інкапсулюю. Я їх приховую. І коли я нарешті зіткнувся з новою межею, я закрутив новий DTO і кидаю його через стіну, роблячи це чиєюсь проблемою.

Але ви хочете надати геттерам, які виражають особу. Добре вітаю, ви знайшли межу. Суб'єкти мають ідентичність, яка виходить за межі їхньої довідки. Тобто, поза їхньою адресою пам'яті. Тому його треба десь зберігати. І щось має бути в змозі посилатися на цю річ за її особистістю. Геттер, що виражає ідентичність, цілком розумний. Купа коду, яка використовує цей гетьер для прийняття рішень, які Організація могла прийняти сама, це не так.

Зрештою, не існування геттерів є неправильним. Вони набагато кращі, ніж громадські поля. Погано, коли вони використовуються для того, щоб робити вигляд, що ви орієнтовані на об'єкт, коли ви цього не робите. Геттери хороші. Орієнтованість на об’єкти - це добре. Геттери не об'єктно орієнтовані. Використовуйте геттери, щоб вирізати безпечне місце для орієнтування на об'єкт.


Саме тому я запитав, і я не впевнений, чи бачите мою розмову з Робертом, я також намагався з’ясувати конкретний випадок, коли мені явно боляче користуватися «розумними людьми». Я не погоджуюся із сеттерами, тому що принаймні для себе дуже важко віднести право власності на подібну дію, я використовував сеттер у всьому і до того часу я зрозумів, що навіть 1 сетер, коли на нього впливає занадто багато об'єктів, вбиває я ... мені довелося все переписати. Розумне використання геттерів після вичерпного тестування протягом такого довгого часу серйозно не має жодних сторонах, якщо ви не пурист.
coolpasta

1
@coolpasta ви можете створювати об’єкти власника даних. Об'єкти власника даних є об'єктами даних, але вони розроблені та названі так, щоб вони (чітко) володіли даними. Звичайно, ці об’єкти матимуть жителів.
rwong

1
@rwong Що ти маєш на увазі під собою clearly? Якщо дані передаються мені з чогось, за значенням , зрозуміло, тепер моєму об'єкту належать дані, але за семантикою він поки що не робить, він просто отримав дані від когось іншого. Потім він повинен виконати операції з перетворення цих даних, зробивши їх своїми, в момент торкання даних, ви повинні внести смислові зміни: Ви отримали дані, названі як $data_from_requestі тепер ви працювали над ними? Назвіть це $changed_data. Ви хочете відкрити ці дані іншим? Створіть getChangedRequestData, таким чином, право власності чітко встановлено. Або це?
coolpasta

1
"Ви не можете написати хороший код без геттерів." Це абсолютно неправильно, як і думка про те, що кордони по суті потребують гетерів. Це не прагматизм, просто лінь. Це зовсім небагато легше просто викинути дані через паркан і зробити з неї, думаючи про споживчих випадках і проектування хороший поведінкової апі це важко.
Роберт

2
Відмінна відповідь!
cmaster - відновити

10

Геттери порушують Голлівудський принцип ("Не дзвоніть нам, ми зателефонуємо вам")

Голлівудський принцип (він же Інверсія контролю) стверджує, що ви не вимагаєте вводити код бібліотеки, щоб виконати справи; швидше, фреймворк називає ваш код. Оскільки рамка контролює речі, трансляція її внутрішнього стану своїм клієнтам не є необхідною. Вам не потрібно знати.

У самому підступному вигляді порушення Голлівудського принципу означає, що ви користуєтеся геттером для отримання інформації про стан класу, а потім приймаєте рішення про те, які способи зателефонувати на цей клас, виходячи з отриманого значення. це порушення інкапсуляції в його кращих випадках.

Використання геттера означає, що вам потрібно це значення, коли ви насправді цього не робите.

Насправді вам може знадобитися таке підвищення ефективності

У крайніх випадках легких предметів, які повинні мати максимально можливу продуктивність, можливо (хоча й вкрай малоймовірно), що ви не можете сплатити дуже малий штраф за продуктивність, який накладає геттер. Це не відбудеться в 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 , робити цілу математику, порівнюючи дати тощо. Коли ви зрозумієте, що вам потрібно довге , буде багато застарілого коду з проблемами. У світі Java ви додасте @deprecatedдо API, всі ігноруватимуть його, і ви затримуєтесь, підтримуючи застарілий, баггі-код. :-( (я припускаю, що інші мови схожі!)

У цьому конкретному випадку я не впевнений, що може бути кращим варіантом, і відповідь @candiedorange цілком суттєва, коли вам потрібно багато людей, але цей приклад ілюструє мінуси. Кожен громадський користувач прагне «зафіксувати» вас у певній реалізації. Використовуйте їх, якщо вам справді потрібно "перетнути межі", але використовуйте якомога менше і з обережністю та продуманістю.


Це правда, але що таке шаблонне рішення для застосування типу / структури даних до змінної об'єкта, а також до всього, що використовує getter для цієї змінної?
coolpasta

1
Цей приклад ілюструє інше явище, примітивну одержимість. В даний час більшість бібліотек і фреймворків мають класи, які представляють timepointі timespanвідповідно. ( epochє особливою цінністю timepoint.) На цих класах вони надають такі організації, як getIntабо getLongабо getDouble. Якщо класи, що маніпулюють часом, написані таким чином, що вони (1) делегують арифметику, пов'язану з часом, цим об'єктам і методам, і (2) забезпечують доступ до цих часових об'єктів за допомогою геттерів, тоді проблема вирішується, не потрібно позбавлятися від гетерів .
rwong

1
Підводячи підсумок, геттери є частиною API, і тому геттери повинні бути розроблені з достатнім врахуванням усіх наслідків, включаючи минулі, поточні та майбутні. Але це не призводить до того, щоб уникнути чи мінімізувати кількість діток. Насправді, якщо в майбутньому виникне потреба в доступі до певної інформації, для якої геть був пропущений, потрібно було б змінити API і зміни коду на стороні бібліотеки. Таким чином, рішення про те, чи слід застосовувати чи уникати певного суб'єкта господарювання, має ґрунтуватися на домені та намірі, а не з профілактичних причин.
rwong

1
"МілісекундиSince1970" перестали працювати на 32 біт-інти до кінця січня 1970 року, тому я сумніваюся, що буде багато коду, використовуючи його :-)
gnasher729

1
@rwong Дещо правильно, але ви припускаєте, що бажані бібліотеки, які представляють часові точки, стабільні. Що вони не є. Напр. Moment.js
користувач949300

1

Я думаю, що перший ключ - пам’ятати, що абсолюти завжди помиляються.

Розглянемо програму адресної книги, яка просто зберігає контактну інформацію людей. Але давайте зробимо це правильно і розділимо його на шари контролер / сервіс / репозиторій.

Там буде Personклас, у якому є фактичні дані: ім'я, адреса, номер телефону тощо. AddressІ теж Phoneє класи, тому згодом ми можемо використовувати поліморфізм для підтримки не-американських схем. Усі три класи - це об'єкти передачі даних , тому вони не будуть не що інше, як геттери та сетери. І це має сенс: вони не матимуть ніякої логіки в них, окрім переважних equalsі getHashcode; просити їх представити інформацію про повну особу не має сенсу: це для презентації HTML, спеціального додатку GUI, консольного додатка, кінцевої точки HTTP тощо?

Ось тут надходять контролер, сервіс та сховище. Усі ці класи стануть важкими для логіки та легкістю, завдяки введенню залежності.

Контролер збирається ввести службу, яка викриє такі методи, як, getі saveобидва будуть приймати обґрунтовані аргументи (наприклад, getможуть мати відміни для пошуку по імені, пошуку за поштовим індексом або просто отримати все; saveможливо, це займе сингл Personі збережіть його). Які геттери матиме контролер? Можливість отримати ім'я конкретного класу може бути корисною для ведення журналів, але який стан він буде мати, крім стану, який вводиться в нього?

Аналогічно, сервісному шару буде введено сховище, тому воно може фактично отримати та зберегти Person, і воно може мати деяку "бізнес-логіку" (наприклад, можливо, ми вимагатимемо, щоб усі Personоб'єкти мали хоча б одну адресу чи телефон число). Але, знову ж таки: який стан має цей об’єкт, крім того, що вводиться? Знову жодного.

У шарі репозиторію є дещо цікавіше: він встановить з'єднання з місцем зберігання, наприклад. файл, база даних SQL або сховище пам'яті. Тут заманливо додати getter, щоб отримати ім'я файлу або рядок з'єднання SQL, але це стан, який було введено в клас. Чи повинен репозиторій мати геттер, який повідомляє, чи успішно він підключений до свого сховища даних? Ну, можливо, але в чому полягає ця інформація за межами самого класу сховищ? Сам клас сховища повинен мати можливість намагатися знову підключитися до сховища даних, якщо це необхідно, що говорить про те, що isConnectedвластивість вже має сумнівне значення. Крім того, isConnectedвластивість, ймовірно, буде помилятися саме тоді, коли воно найбільше потребує права: перевіркаisConnectedперед спробою отримати / зберегти дані не гарантує, що сховище все ще буде підключено, коли "справжній" дзвінок зроблений, тому він не знімає потреби в обробці винятків десь (є аргументи, куди це повинно йти, крім обсяг цього питання).

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

TL; DR

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


Мені здається, що цей напрямок мислення дуже схожий на дискусію щодо правильного використання властивостей C #. Коротше кажучи, очікується, що властивості (які можуть бути лише для геттера або пари, що встановлюють пару) підтримують певний контракт, наприклад "те, що ви встановите, те, що отримуєте", "геттер повинен бути в основному без побічних ефектів", "getter повинен уникати помилок кидання" і т. д. Всупереч вашому висновку, існує багато станів об'єктів, які вигідні, щоб їх було викрито як властивості (або getters). Прикладів тут занадто багато, щоб цитувати їх.
rwong

2
@rwong Мені буде цікаво знати кілька прикладів, скажімо, для "нормального" "корпоративного" додатку, реалізованого однією командою. Припустимо також, що для простоти немає жодних сторонніх сторін. Ви знаєте, автономна система, як-от Календар, Зоомагазин, що завгодно.
Роберт

1

Що одного, без думок, що зламається, якщо я розумно використовую гетерів та для даних, які явно цілісність об'єкта не порушується, якщо він виводить його?

Члени, що змінюються.

Якщо у вас є колекція речей в об'єкті, який ви виставляєте за допомогою геттера, ви, можливо, піддаєтеся помилкам, пов’язаним з неправильними речами, що додаються до колекції.

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

Дійсно поганим прикладом може бути об'єкт, який рахує від 1 до 100, виставляючи його Поточне значення як змінне посилання. Це дозволяє сторонній об'єкт змінити значення Current таким чином, щоб значення могло лежати за межами очікуваних меж.

Це здебільшого проблема викриття змінних об'єктів. Викриття конструкцій чи незмінних об'єктів взагалі не є проблемою, оскільки будь-які зміни в них замість цього змінять копію (як правило, або неявну копію у випадку структури, або явну копію у випадку незмінного об'єкта).

Використовувати метафору, яка може полегшити бачення різниці.

У квітки є ряд унікальних речей. Він має Colorі має ряд пелюсток (NumPetals). Якщо я спостерігаю за цією квіткою, у реальному світі я можу чітко бачити її колір. Тоді я можу приймати рішення, виходячи з цього кольору. Наприклад, якщо колір чорний, не даруйте дівчині, але якщо колір червоний, подаруйте подрузі. У нашій об’єктній моделі забарвлення квітки було б викрито як геттер на квітковому об’єкті. Моє спостереження за цим кольором важливе для дій, які я буду виконувати, але це зовсім не впливає на квітковий предмет. Я не міг би змінити колір цієї квітки. Так само не має сенсу приховувати властивість кольору. Квітка взагалі не може завадити людям спостерігати за його кольором.

Якщо я фарбую квітку, я повинен викликати метод квітки ReactToDye (Color dyeColor), який змінить квітку відповідно до її внутрішніх правил. Потім я можу запитувати Colorвластивість ще раз і реагувати на будь-які зміни в ньому після виклику методу ReactToDye. Мені було б неправильно безпосередньо змінювати Colorквітку, і якщо я міг би, то абстракція зламалася.

Інколи (рідше, але все ще досить часто, що це варто згадати) сетери є цілком правильним дизайном ОО. Якщо у мене є об’єкт «Клієнт», цілком справедливо виставити сетер для їх адреси. Незалежно від того, називаєте ви це setAddress(string address)чи ChangeMyAddressBecauseIMoved(string newAddress)просто string Address { get; set; }, це питання семантики. Внутрішній стан цього об'єкта потрібно змінити, а відповідний спосіб зробити це - встановити внутрішній стан цього об'єкта. Навіть якщо мені потрібен історичний запис адрес, у Customerяких жив, я можу використовувати сеттер, щоб відповідним чином змінити свій внутрішній стан. У цьому випадку немає сенсу Customerбути непорушним, і немає кращого способу змінити адресу, ніж надати сетеру це зробити.

Я не впевнений, хто припускає, що Геттери та сетери погані або порушують об'єктно-орієнтовані парадигми, але якщо вони є, вони, ймовірно, роблять це у відповідь на певну мовну особливість мови, якою вони користуються. Я відчуваю, що це виросло з культури культури "все є об'єктом" (і, можливо, поширилося і на деякі інші мови). У світі .NET ця дискусія взагалі не ведеться. Getters and Setters - це першокласна мовна функція, яку використовують не тільки люди, які пишуть додатки мовою, але й сам API мови.

Слід бути обережними під час використання геттерів. Ви не хочете виставляти неправильні фрагменти даних і не хочете виставляти дані неправильно (тобто об'єкти, що змінюються, посилання на структури, які можуть дозволити споживачеві змінювати внутрішній стан). Але ви хочете моделювати свої об'єкти так, щоб дані були інкапсульовані таким чином, щоб ваші об'єкти могли бути використані зовнішніми споживачами та захищені від неправомірного використання тими ж споживачами. Часто для цього знадобляться жителі.

Підводячи підсумок: Getters і Setters є дійсним об'єктно-орієнтованим інструментом проектування. Вони не повинні використовуватися настільки вільно, що кожна деталь реалізації піддається викриттю, але і ви не бажаєте використовувати їх настільки щадно, що споживачі об'єкта не можуть використовувати об'єкт ефективно.


-1

Яка річ, без думок, що зламається, якщо я використовую гетерів ...

Технічне обслуговування порушиться.

У будь-який час (я повинен сказати майже завжди) ви пропонуєте геттеру, в основному віддаєте більше, ніж просили від вас. Це також означає, що вам потрібно підтримувати більше, ніж просили, ерго ви знижуєте ремонтопридатність без реальних причин.

Походимо з @ candied_orange's Collection прикладу . Всупереч тому, що він пише, Collection не повинно бути геттера. Існують колекції за дуже конкретних причин, в першу чергу , щоб ітерація за всіма пунктами. Цей функціонал ні для кого не є сюрпризом, тому його слід реалізовувати в Collection, замість того , щоб натискати на цей очевидний випадок використання користувачем, використовуючи для циклів та getters чи що.

Якщо бути справедливим, деякі межі роблять необхідність видобувачів. Це трапляється, якщо ви дійсно не знаєте, для чого вони будуть використовуватися. Наприклад, ви можете програмно отримати стек-трек з Exceptionкласу Java в наш час, тому що люди хотіли використовувати його з усіляких цікавих причин, які письменники не могли або не могли передбачити.


1
Контрприклад. Розглянемо функцію, яка повинна повторювати два Collections одночасно, як у (A1, B1), (A2, B2), .... Для цього потрібна реалізація "zip". Як ви реалізуєте "zip", якщо функція повторення реалізована на одному з двох Collection- як ви отримуєте доступ до відповідного елемента в іншому?
rwong

@rwong Доводиться Collectionреалізовувати zipіз собою, залежно від того, як записана бібліотека. Якщо цього не відбувається, ви реалізуєте його та надішліть запит на виклик автору бібліотеки. Зауважте, що я погодився з тим, що деякі кордони іноді потребують заготівельників, моя справжня проблема - це те, що сьогодні є всюди
Роберт

У цьому випадку це означає, що бібліотека повинна мати на Collectionоб'єкті геттери , принаймні, для її власної реалізації zip. (Тобто, геттер повинен мати принаймні видимість пакету.) А тепер ви
залежаєте

Я вас не дуже розумію. Collection, Очевидно , має доступ до свого внутрішнього стану, або бути більш точними будь Collectionекземпляр може отримати доступ до внутрішнього стану будь-якого іншого. Це той самий тип, не потрібні жовніри.
Роберт

Я теж чую вас, але знову ж таки, що саме є кращим рішенням для жителів? Я знаю, що це поза питанням.
coolpasta
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.