Java - Философия языка - О философии Java и многом другом

Java - статьи
Оглавление
Java - Философия языка - О философии Java и многом другом
Кроссплатформенность
Все страницы

Сразу хочу предупредить вот о чем. Здесь не будет криков "как все круто" или "как все плохо". Я отношусь к Java именно с точки зрения философской. Это – данность. Потому – рассуждать о том, хорош язык или плох, бессмысленно. Язык может удовлетворять предъявляемым требованиям, либо не удовлетворять им. Ежели удовлетворяет – прекрасно, пользуемся. Нет – выбираем другой. А то получается как в том анекдоте: "Мыши плакали, кололись, давились, но продолжали грызть кактус" . Если Java для вас – кактус, возможно, стоит задуматься о выборе другого языка. А если все-таки грызете, несмотря на то, что это кактус, – значит, плюсов в этом занятии для вас больше чем минусов. Тогда не жалуйтесь.

Итак, что можно упомянуть в качестве основных черт Java:

  • Java - полностью объектно-ориентированный язык. Что это значит? Это значит, что ВСЁ в языке является объектом. Исключение – 8 примитивных типов, хотя некоторые свойства объектов у них тоже присутствуют, в частности, у них есть класс.
  • В Java НЕТ множественного наследования в том виде, в котором оно есть в С++. Не было и, надеюсь, не будет. Грамотный дизайн приложения позволяет обойтись без множественного наследования реализации. Лично я за более чем 10 лет работы с Java ни разу не встретился с ситуацией, когда мне это понадобилось бы . Еще раз подчеркиваю – я говорю именно о множественном наследовании от классов, содержащих реализацию.
  • Java - кроссплатформенный язык. Это накладывает некоторые ограничения на дизайн, функциональность и применяемые средства, но переносимость, на мой взгляд, того стоит.

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

Объектная ориентация.

Это не так просто, как может показаться на первый взгляд. Многие, переходя на Java, начинают писать на нем в стиле "C with objects" – весь код в одном-двух методах и в одном классе. Это ни в коем случае не является объектно-ориентированным подходом. Потому как по определению,

Объект – совокупность данных и методов работы с ними.

Почему я так выделил, казалось бы, первое и основное определение ООД? Потому как в Java оно должно применяться как никогда часто, именно ввиду того, что объектом является всё. Практика показывает, что приучиться думать в терминах объектов весьма непросто. Мне приходилось напоминать это определение весьма и весьма опытным разработчикам, когда они пытались скрестить ежа с ужом. А именно – всунуть логику взаимодействия объектов одного типа в класс этого же типа. При том, что для этой логики объекты являются данными, а, значит, по определению они должны быть инкапсулированы в объекте более высокого уровня.

Возникает резонный вопрос: а что, собственно, должен содержать объект? Какие данные? Собственно, в умении это определять и состоит искусство проектирования. Это приходит только с опытом. Я лишь могу сказать, чего объект НЕ должен содержать: ничего лишнего. Объект должен описывать ОДНУ И ТОЛЬКО ОДНУ моделируемую сущность. Причем, как очень хорошо сказал один из участников форума на , Clifton Craig, – "если в описании назначения (responsibility) объекта вы используете 'И' (что-то И что-то), то вы допускаете ошибку." Объект должен быть максимально простым. А из этих простых объектов уже, как из кубиков, собираются более сложные.

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

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

Приведу пример. Допустим, у нас есть объект – дом. Из чего он состоит? Из стен, крыши, окон, дверей. Фундамент у него есть. Вроде все. Можно определить эти пять объектов и на этом успокоиться.

Однако. Если строить этот дом на песке – фундамент должен быть один. Если на камне – другой. На льду – третий. У дома может быть различно количество комнат. Разная крыша. Разные окна, двери. Если начать реализовывать объект дом для каждой комбинации – можно поседеть. И это при том, что формальную логику построения дома может описать даже ребенок. Сначала нужно сделать фундамент, потом построить стены, потом крышу, потом вставить окна и двери. Всё. И этот ребенок абсолютно прав, поскольку он оперирует абстрактными понятиями – теми самыми пятью объектами. Между тем, Java позволяет легко формализовать процесс построения дома. Нужно всего лишь ввести несколько дополнительных объектов.

Итак, начнем. Мы строим дом. Конкретный. У которого есть проект. Этот проект включает в себя все подробности – из чего сделаны стены, каково расположение комнат, сколько окон и дверей и т.п. Далее, мы определяем абстрактные понятия (объекты) – фундамент, стена, крыша, окно, дверь. У каждого из этих абстрактных понятий есть какие-то свойства – толщина, материал, размеры, местоположение и т.п. Логика, находящаяся в объекте дом, оперирует именно с этими понятиями – больше ей и не надо. Таким образом, мы получаем возможность построить дом из абстрактных кубиков.

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

Посмотрим, что у нас получилось. У нас есть абстрактные понятия, части дома: фундамент, стена, крыша, окно, дверь. . От конкретики они не зависят. У нас есть дом, который содержит логику построения себя (это не совсем корректно, но для простоты оставим так), причем эта логика оперирует абстрактными объектами, т.е. тоже не зависит от конкретики. У нас есть строитель, который умеет создавать те самые конкретные объекты. Его логика точно так же не зависит от конкретики, он берет все данные из проекта. Что у нас осталось? Один (ОДИН!!!) объект, который мы должны реализовать для построения любого дома – проект. Вся остальная логика у нас уже абстрагирована от конкретной реализации. Фактически мы этого добились введением всего двух дополнительных объектов по сравнению с первоначальным дизайном – строителя и проекта. Плюс еще выделили формальную логику построения дома, без которой обошлись сначала.

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

В качестве одной из самых значительных черт Java с самого начала называлась возможность написать код один раз, а потом использовать его всюду. Я неоднократно слышал от разных программистов, что это ерунда и не работает. Причем сопровождалось все это вопросом с этакой издевкой – "Ну скажи, ты сам много использовал без изменений из своего кода, написанного ранее?"

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

Хорошими примерами грамотно спроектированных систем является, как правило, библиотеки. Взять, к примеру, , библиотеку для вывода логов. Можно использовать предопределенные уровни лога, можно определять свои. Сообщения могут выводиться сразу, могут накапливаться и выводиться пакетами. Вывод может происходить десятком различных способов, вплоть до отправки писем или записи в базу данных. Не подходят существующие – можно реализовать свои. И все это при НЕИЗМЕННОМ ядре.

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

Итак, перейдем к следующему ключевому моменту Java, а именно –

Множественное наследование, вернее, его отсутствие.

Строго говоря, это не совсем так. В Java множественное наследование существует, правда, в сильно ограниченном виде. Я говорю об интерфейсах, которые, фактически, являются полностью абстрактными классами с некоторыми ограничениями (например, методы в интерфейсе всегда public, и т.п.)

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

Третий ключевой момент Java –


 

Добавить комментарий


Защитный код
Обновить

Меню