Удаление динамических потомков

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Skwoogey
Сообщения: 65
Зарегистрирован: 11 янв 2016, 02:25

Ну бОльшую часть принципов SOLID могу понять и понять, почему их стоит соблюдать, тоже могу. Но вот с инкапсуляцией и сокрытием проблемы. Начнем с того, что я вообще не понимаю почему эти 2 термина в с++ отождествляют, а в других языках - нет. И как сокрытие улучшает код? Я только вижу минус, что надо дописывать функции для чтения и изменения переменных. Понимаю, что сокрытие в коммерческих делах может быть полезно, но в моей ситуации не вижу никаких плюсов.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

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

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

Дальше – больше. Уже то, что нам выдали такое задание, указывает на то, что начальник понимает, какая серьёзная ошибка была допущена программистом, который первоначально проектировал класс. Если у нас есть требование, что перед проставлением значения в поле должна отрабатывать определённая логика (как правило, это логика по проверке корректности значения), то это сразу же нас должно заставить задуматься о сеттере. Такой логике место именно в нём! Во-первых, в таком случае мы избегаем дублирования кода. Во-вторых (что куда более важно) мы получаем гарантии того, что логика отработает ВСЕГДА. Людям свойственно ошибаться, поэтому хороший программист обязан писать код, при использовании которого ошибиться нельзя.

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

Вообще, как по мне, создавая новый класс, все поля сразу нужно делать private, и добавлять геттеры для полей лишь по мере необходимости. Добавление же сеттера для некого поля должно быть серьёзным испытанием для программиста. Он должен быть крайне щепетилен и даже болеть манией преследования как минимум в лёгкой форме, так что перед добавлением сеттера он должен подумать три раза и пойти на этот шаг только в случае безвыходности. Всё, что не нужно внешнему коду, должно быть скрыто. Это и есть принцип минимальных привилегий в действии.

Что касается заявления о том, что в маленьком проекте сокрытие - это просто лишний код - в этом я не согласен в корне. Где, как не в тренировочных задачах оттачивать правильность стиля? Хороший программист пишет одинаково хороший код, как для маленьких программ, так и для больших программных комплексов. Лениться и делать маленькую программу на "ляп-тяп" - не уважать себя. Не изменяй себе, пиши всегда хороший код, и тогда тебя будут ценить.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Skwoogey
Сообщения: 65
Зарегистрирован: 11 янв 2016, 02:25

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

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

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

И последнее, я понимаю, что надо оттачивать стиль на тренировочных проектах, но я не хочу следовать шаблонам, пока не увидел в них смысла. Я понимаю, что могу не видеть смысла в силу своей неопытности, и я понимаю, что мне это потом может выйти боком, но мне очень не нравится следовать устоям просто, потому что так принято. Я предпочту налететь на грабли, увидеть смысл в устоях, которые спасают от этих граблей, согласится с ними и следовать им с пониманием.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Ок, моё дело лишь дать совет. А будешь ты ему следовать или нет - это уже твоё дело :)
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить