Показаны сообщения с ярлыком Принципы разработки. Показать все сообщения
Показаны сообщения с ярлыком Принципы разработки. Показать все сообщения

понедельник, 5 сентября 2016 г.

Инкапсуляция и сокрытие информации

В области проектирования существует два понятия, которые часто используются совместно – инкапсуляция (encapsulation) и сокрытие информации (information hiding).

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

(*) – иногда понятие инкапсуляции применяется в более широком смысле. Например, говорят, что фабрика «инкапсулирует» информацию о конкретном типе создаваемого объекта. В этом контексте инкапсуляция является синонимом сокрытия информации.

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

вторник, 23 августа 2016 г.

Принцип YAGNI

На ru.stackoverflow.com недавно был задан вопрос, который, ИМХО, стоит вашего внимания: Нарушает ли OCP и DIP (из SOLID) принцип YAGNI?. Ниже представлен немного более развернутая версия моего ответа.

Разные принципы проектирования направлены на решение противоречащих друг другу задач проектирования. Можно сказать, что разные принципы «тянут» дизайн в разные стороны и нужно найти правильный вектор, наиболее полезный в данном конкретном случае. SRP толкает в стороны простого решения, а OCP – в сторону изоляции компонентов, а DIP – направлен на построение правильных отношений между типами.

Следование одному принципу может привести к нарушению другого. Так, например, любое наследование *можно* рассматривать как нарушение SPR, поскольку теперь за одну ответственность (рисование фигур) отвечает целая группа классов. Принципы DIP и OCP, которые часто требуют наследования, могут привести к появлению дополнительных «швов», т.е. интерфейсов/базовых классов в системе, что, опять-таки, приведет к нарушению SRP и/или ISP.

четверг, 28 февраля 2013 г.

Аксиома управления зависимостями

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

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

вторник, 29 января 2013 г.

Критерии плохого дизайна

Наверняка многие слышали о принципе инверсии зависимостей, букве D из аббревиатуры SOLID. Изначально этот принцип был описан Бобом Мартином еще в 1996 году в статье для C++ Report. Затем эта же статья в расширенном виде вошла в книги «дядюшки» Боба “Agile Software Development, Principles, Patterns and Practices” и затем в “Agile Principles, Patterns and Practices in C#”.

В исходной статье Боба Мартина есть 3 части: философские размышления о хорошем и плохом дизайне, описание принципа инверсии зависимости и «простой пример» с лампочками и кнопками. Вторая часть статьи весьма известна, последняя – малоинтересна, а вот первую часть, ИМХО, незаслуженно обходят вниманием.

суббота, 28 июля 2012 г.

О дизайне. Часть 2. Практические примеры

Как мы обсудили в прошлый раз, дизайн штука не простая; постоянно приходится держать в голове кучу всяких вариантов и стараться найти компромисс среди множества разных требований, раздирающих ваше элегантное решение на части. С одной стороны, хочется, чтобы решение было простым в сопровождении, хорошо расширяемым, с высокой производительностью, при этом оно должно быть понятным не только его автору, но еще как минимум одному человеку; хочется, чтобы решение ело мало памяти и не нарушало ни одного из 100 500 принципов ООП, ну и, самое главное, мы хотим его закончить хотя бы в этом году, хотя менеджер постоянно твердит, что оно должно было быть готово еще месяц назад.

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

понедельник, 16 июля 2012 г.

О дизайне

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

Отношение к этапу проектирования (дизайна) может быть самым разным, начиная от подхода, принятого на ранних этапах развития методологии XP, когда считалось, что дизайн и архитектура – это динозавры, которым нет места в динамично развивающемся мире agile разработки. Многие и сейчас не задумываются о дизайне решения, считая, что итеративный процесс разработки + рефакторинг сделают все за нас и хороший дизайн появится сам собой.

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

четверг, 19 апреля 2012 г.

О повторном использовании кода

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

Причин у подобных разочарований тоже несколько. Во-первых, такое отношение к ООП может быть следствием завышенных ожиданий, а ведь Фред Брукс еще двадцать лет назад писал о том, что не стоит ждать «серебряных пуль», способных на порядок увеличить продуктивность труда программиста. Во-вторых, никто из серьезных сторонников ООП (типа Гради Буча или Бертрана Мейера) не обещали, что все будет просто. ООП – это не волшебная палочка, которая сделает из любого УГ конфетку, даже обертку которой можно будет использовать повторно.

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

вторник, 28 февраля 2012 г.

Принцип замещения Лисков и контракты

Идея этой заметки навеяна статьей Александра Бындю “Дополнение к LSP” и может рассматриваться, как развернутый комментарий к статье Александра.

Итак, вопрос следующий, предположим, один из членов команды пытается реализовать интерфейс IList of T в классе DoubleList of T таким образом, чтобы при добавлении элемента с помощью метода Add, добавлялся бы не один, а два одинаковых элемента. Поскольку класс List of T всегда добавляет только один элемент, то можно считать, что данное поведение нарушает принцип замещения Лисков (LSP – Liskov Substitution Principle).

среда, 23 ноября 2011 г.

Идеальная архитектура

Существует много разных взглядов на разработку архитектуры и дизайна современных приложений. Некоторые архитекторы стремятся продумать все до мелочей, разрисовать use case-ы всех классов и модулей, проанализировать миллион возможных способов их использования, все их обязательно задокументировать и уже потом приступить к этапу кодирования.

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

вторник, 13 сентября 2011 г.

Принцип самурая

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

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