понедельник, 11 июля 2011 г.

Объектно Ориентированное Программирование

Всем привет. Давненько я хотел написать об этой теме, но все никак не доходили руки, а вот сегодня эта тема была как-никак показана в jabber-конференции ресурса gcup.ru. О чем был там разговор? Об ООП.Эта парадигма не всех устраивает, и некоторые думают, что иногда от нее  можно отказаться, и использовать более простую парадигму. И для начала я расскажу о мнении каждой стороны, начнем с меня. Я программист, и использую ООП, везде, всегда, и где только можно. Почему? Это долгая история, но придется ее рассказать. В 8 классе у меня случился переходной период, и все мои предпочтения поменялись, и в один прекрасный момент я захотел стать программистом, и пошел на местный книжный рынок. Не знаю почему, но я выбрал именно книгу по Java. Придя домой, я начал читать ее, в то время у меня не было компьютера, и я просто учил Java в теории, а вот в 9 классе у меня появился компьютер и я начал уже практиковаться в java. Так было еще 2 года, а потом я пошел в колледж, там мы начали изучать основы программирования, с начала с Паскаля, а потом перешли на с++. В паскале мне было не удобно работать, я 2 года учил язык, который полностью построен на ООП, а тут ооп вообще не было, но потом я нашел выход и начал использовать ключевое слово object. На третьем курсе у нас появился предмет ООП и там я уже на конец-то  чувствовал себя в своей тарелке. Потом в конце третьего курса, я попал на «Республиканскую олимпиаду по программированию  среди колледжей» и занял там второе место, из за того что не успел решить 5 заданий, но я тогда не расстроился, я был очень рад, хотя я и не думал что займу хоть какое то место, потом я понял почему я занял второе место. Дело в том, что в одном из заданий надо было описать в виде данных точку и функции для работы с этой точкой, но я не стал описывать структуру и функции для работы над этой точкой, а описал класс точки, и методы этого класса, вот за такой оригинальных ход я и получил второе место. На четвертом курсе я опять участвовал в олимпиаде, но получил уже первое место, хотя вместе  со мной первое место получил еще и мой однокурсник. На том же 4 курсе я познакомился с ActionScript3.0 и этот язык мне очень понравился, и с тех времен я считаю его одним из лучших в мире. Почему? Об этом расскажу тоже попозже, а сейчас скажу, что только в колледже я занимался процедурным программированием, до него и после - нет, хорошо ли это? Об этом тоже далее в посте.
Ну, а теперь о самом ООП. В чем же я вижу его силу? Во многом. Начнем с простого, с основ ООП. С классов. Класс-  это базовая структура ООП, по сути это обычная структура процедурного языка программирования, вот только теперь полями этой структуры управляют ее методы, а не функции программы. Простой пример, машина, это объект, у нее есть свойства (цвет, макс. Скорость, количество колес, и т.д) и методы (повернуть руль, поехать, включить двигатель и т.д). Разве это плохое звено? Да нет, все хорошо. А что было раньше, в процедурных языках программирования? Раньше были структуры данных, вот только этими данными управляла не сама структура, а функции программы, тоесть у машины так и были свойства, а вот методы были не ее, если так представить, то свойствами машины управлял мир, а не она сама. А представьте что у нас в программе (на процедурном языке программирования) есть несколько различных объектов, например машина, собака, магнитофон, то тогда программа будет включать в себя функции, которые управляют этими объектами. Разве это хорошо? Хорошо что функции программы управляют собакой? Мне кажется, что нет, в этом случае лучше вывести собаку в отдельный класс, и пусть ее методы управляют ею сами.
Следующий элемент ООП, это Инкапсуляция. Что это такое? Это самое важное понятие в ООП. Звучит оно так – «Инкапсуляция — это свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе и скрыть детали реализации от пользователя», тоесть, есть свойства и методы, на примере той же машины, свойства у нее это цвет, количество колес, макс.скорость, и т.д, методы – это запуск двигателя, поворот руля, нажатие на акселератор, нажатие на педаль газа. Но как написано в определении, реализация скрыта от нас, опять же, пример с машиной, мы не знаем, как реализован метод запуска двигателя, или как реализован метод открытия дверей, единственное, что мы знаем, так это то, что они есть, и у нас есть возможность им пользоваться. Другими словами, инкапсуляция дает нам свойства и методы объекта, при этом мы не знаем, как реализован сам объект.
Следующий кит ООП, это Полиморфизм. Это свойство дает нам расширять объекты, вернее использовать свойства и методы объекта в решении схожих задач, но технически очень разных. Как это? Да просто, опять же машина, например, у нее есть метод запуска двигателя, но не один, а несколько: с помощью ключа, с помощью голоса, и с помощью бортового компьютера. Все три метода называются одинаково – «запуск двигателя», но в тоже время все методы технически разные, но дают одинаковый результат. Как видно, ничего сложного нет, хоть и название очень странное, но с греческого языка - это множество всех форм, что отлично описывает его функциональность.
Последний главный кит – это Наследование. Тут вообще все просто, у любого объекта может быть предок, как это? Ну, вот возьмите себя, вы являетесь предком своего отца, вы наследуете некоторые свойства и методы своего отца, но и тоже время у вас могут быть другие свойства и методы которых нет у вашего отца, уникальные свойства. Зачем это надо? Да просто посмотрите на дерево эволюции, наследники наследовали с многие элементы своих предков, но в тоже время у них появлялись свойства, которых нет у их предков, благодаря Наследованию, из простой клетки появился человек.
Вот главные понятия в ООП, есть еще другие, но они связаны с этими тремя понятиями, да и этих трех понятий спокойно хватает для понятия, что такое ООП. Именно в этих понятиях я вижу силу ООП, мне не надо из одной программы управлять свойствами объектов, пусть лучше сами объекты управляют своими свойствами. Если представить что весь мир это программа, а каждый объект – это машина, то разве не глупо, что мир управляет свойствами машины, разве не глупо то, что мир знает, как реализован какой-то из методов машины? Мир должен только знать свойства и методы, и не более.
Ну, а теперь о моих оппонентах, первый это программист на ПХП, второй – программист на с++ (но кроме с++ он знает многие языки программирования, но это не главное). Не знаю как первый, но второй один раз сказал одну интересную фразу, звучала она примерно так – «я не люблю java за то, что в ней приходится создавать объекты там, где это не надо». На самом деле он прав и неправ одновременно, базовые типы в java (числа, бул значения, символы) это не классы, но в тоже время другие типы данных – это объекты. Второй оппонент – это очень сильный нелюбитель java и c#, почему? Много объясняет его фраза, а многого я не знаю, может какая то обида, а может быть другая причина, ну а может он берет пример с шарп ненавистников, их ненависть к шарпу заключается в том, что он (шарп) привязан к фраемворку. Этого я не могу понять, тут все нормально, ну создан язык для фраемворка, что тут плохого? Некоторые утверждают что шарп без дотНета – это фуфел, я с ними соглашусь, но в тоже время всегда говорю им – «зачем использовать яп не в тех целях для которых он разрабатывался», зачем использовать вилку для поедания супа? Лично я не могу толком понять их рассуждения. Но что-то я отошел от темы разговора. В следующем «батле» я дал промашку, промашка связана с описанием в одном файле более чем двух классов, да, тут я что то сглупил, и сейчас расскажу почему. В АС3 и Шарпе для юнити, имя класса соответствует файлу в котором описан класс, с дуру я прилепил туда и джаву, почему? Да просто привык описывать каждый класс в разных файлах, я просто банально забыл, а моя привычка не дала мне это вспомнить. Оппоненты не поняли, почему каждому классу нужно присваивать отдельный файл, им это показалось очень странным. Лично я не вижу в этом ничего плохого. А вот ПХПешник наоборот, сказал что это тупизм, и легче все хранить в одном большем файле, из за этого большего файла у нас начался второй батл, батл насчет неймспейсов. К сожалению я не знаком с неймспейсами в с++ или шарп, по этому я не знаю что это такое именно в этих языках, но я знаком с пакетами, а как написано в вики, пакеты сделаны для того, чтобы организовать классы в пространства имен. Но в тоже время, пакеты зависят он файловой, и виртуальной файловой системы (jar). А вот пространства имен в с++ не зависят, меня это сбило с толку, ведь это не очень удобно, именно для меня. Ну, и на последок, был последний батл, второй программер спросил меня, можно ли в джаве описать функцию вне класса, тоесть не описывать класс. Я не понял вопроса, так как это противоречит всем принципам ООП, а в частности инкапсуляции, не долго думая я ответил что нет, и сказал что в этом смысле лучшим вариантом будет создать закрытый локальный метод, который и будет использоваться как функция. Но они начали говорит о том, что это все фигня, и почему в джаве нельзя так делать:
void a(){};
Main(){
    a();
}
Я привел им этот код:
public class Hello()
{
    private function a(){};
    Public static void main()
    {
        a();
    }
}
Их не устроил этот вариант, видимо из-за их незнания ООП и Java в целом. Но насчет первого я сомневаюсь. Но если честно, то я не понял их, не понял что именно их не устраивает, поэтому я спросил что их не устраивает. Они мне начали говорить про то, что для реализации такого банального кода, надо описать класс, создать пакет и отдельный файл, к счастью создание пакета можно выкинуть, так как у нас есть только 1 файл с кодом, и в этом случае не обязательно создание пакета. Я спросил, что в этом плохого. И они мне начали рассказывать про оптимизацию, про то, что в данном моменте этот объект жрет твою память, о том, что программеры делавшие квейк использовали си, а не джаву и шарп. Далее последовало обливание меня поносом со стороны ПХПешника, в этом поносе были различные выражения типа «Хватит думать ООП», «Java забила тебе все мозги» и подобный треп, который часто разводят на холливарах. На чем мы остановили? Да не на чем, я так и не понял, что они хотят, и единственное что я им твердил – такое нет в принципах ООП, и так продолжалось до конца моего рабочего дня.
Ну, и в конце поста я отвечу на его сообщение «Ну почему программа должна строится полностью на ООП структурах? В чём от этого профит? Неужели в скорости? Нет? А может быть в размере исполняемого файла? Тоже нет? Нуу, ещё есть потребление памяти! Ох и тут тоже нет... Тогда какой толк от этого? Так удобнее скажите вы? Чем?». Отвечу маленьким сообщением. Первое – очень простое маштабирования приложения, все организованно на объектах, посмотри на наш мир, все - это объекты. Второе – наследование, сама программа это тоже объект, ее можно наследовать и вводить новые компоненты. Третье – полиморфизм, но это свойство есть во всех языках программирования, даже в процедурных. Четвертое – инкапсуляция, мы получаем только интерфейс класса/объекта, мы получаем только свойства и методы, мы не знаем, как эти методы реализованы, по тому такая скрытость очень удобна. Пятая – само понятие класс и объект, Намного легче и удобнее определить простой класс со свойствами и методами, чем управлять данными через функции программы.
На самом деле можно об этом спорить бесконечно, у ООП есть недостатки, но они не относятся к тем высказываниям, которые я услышал. Самые известные недостатки – скорость и потребление ресурсов, но в наше время это вообще не критические параметры, и они спокойно закрываются «быстротой разработки». Так что не вижу проблем в ООП. Я не везде прошу использовать ООП, но я просто ни разу не сталкивался с ситуацией, где бы ООП было плохим решением. Почему? Да наверное потому что я никогда не занимался системным программированием…..
Ну, вот и все, всем пока…. Удачи…