У каждого явления существует «плохая» и «хорошая» сторона. При этом абсолютного зла не существует. Также как и абсолютного добра.
Догмой (применительно к разработке) является утверждение о том, что некоторая технология (или технологическое решение) является абсолютным добром, то есть обладает преимуществами, не имея недостатков.
Основная мысль этой статьи — подобное догматическое мышление весьма распространено в индустрии, но оно вредно и ведет к печальным результатам.
Начнем с того, что программирование — это плохо. Почему?
Потому что оно сложное. Что лучше? Конструирование.
Ошибки конструирования видны сразу. Ошибки программирования незаметны.
Программирование — трудоемкий процесс, требующий массы знаний и умений. Конструирование требует низкой квалификации.
Представьте, что 25 лет назад вам поставили задачу — запрограммировать «динамическую страницу с картинками и текстом», которая высвечивает ссылки, при нажатии на них высвечивает другую «динамическую страницу» и так далее.
Представьте себе трудности, связанные с реализацией такой программы. На разных платформах.
А сейчас? А сейчас любой ботаник за день сконструирует такую страницу из HTML и CSS. Причем ошибки при конструировании такой страницы, как правило, видны сразу и легко исправляются.
Итак, программирование — это сложно. То есть трудоемко, требует высокой квалификации и большой команды, содержит неочевидные «подводные камни», нуждается в выработке архитектуры и т.д.
Сложность присуща программированию по его природе. Она неизбежна. Это «темная сторона» программирования.
Но есть и «светлая сторона». Программирование дает и неоспоримо хорошее — программы, поведение которых позволяет решать разнообразные задачи, операционные системы, драйвера и пр.
Догматический взгляд на программирование (как процесс в целом) часто сводится к отрицанию его сложности.
Но этот взгляд не всегда высказывается явно. Например, некоторые апологеты, евангелисты и другие пациенты любят утверждать, что программирование «пока еще является сложным». Но вот с появлением «вот этой вот штуки все изменится».
Давайте рассмотрим далее догму о том, что…
«автоматическое управление памятью (java) лучше (проще) ручного (C++) и, вообще, Java (C#) лучше C++»
Ручное выделение и освобождение памяти — это сложность.
Однако, есть определенные техники, которые позволяют управлять этой сложностью, то есть держать под контролем.
Например. Любой ресурс (который нуждается в явном освобождении) всегда принадлежит какому-то объекту. Он выделяется при создании объекта и возвращается системе при уничтожении объекта. Любой объект всегда принадлежит другому объекту. На самом верху этой иерархии находится главный владелец всех объектов — приложение.
Если требуется разделить владение объектом, вводим владельцев со счетчиком. Последний владелец (который установил счетчик в ноль) освобождает объект. Владение объектом можно явно передать.
Зачем пишу это здесь? Чтобы стал понятен уровень сложности.
Из своей практики могу сказать, что эти приемы решают 99% проблем ручного управления памятью. Никаких больше настроек или хитростей не требуется; только внимательность.
И вот приходит автоматическое управление памятью. И «упрощает» эту сложность.
Ушла ли сложность? Нет, конечно. Она трансформировалась.
Появился сборщик мусора. Это отдельная задача, которая требует ресурсов в непредсказуемые моменты времени (приостанавливая ваше приложение). Его требуется настраивать, то есть сборщик привносит свою (дополнительную) сложность.
Из языка ушел автоматический деструктор и простейшая задача — закрыть файл в том же месте кода, где он был открыт — превратилась в сложность. Финалайзер не решает эту сложность.
Самое интересно — нехватка памяти. Оказывается, в java она теперь стала _разной_. Если в C++ нехватка памяти означала нехватку памяти, то в Java нехватка памяти означает… Да непонятно что! Еще одна сложность.
Уф. Ну, хорошо, меня загрузили по уши новой сложностью. Но взамен? Взамен-то я избавлен, наконец, от утечек памяти, если у меня есть автоматическая сборка мусора?
НЕТ.
В чем тут был догматизм? И почему так вышло? Попробую объяснить.
Сложность требует высокой квалификации.
Программирование — как сложный процесс — требует высокой квалификации. Это дорого.
Взрывной рост IT привел к взрывному повышению спроса на разработчиков.
Нашлась умная голова, которая решила, что можно сделать программирование простым, то есть возможным с помощью разработчиков низкой квалификации.
Java — это и есть одна из таких попыток. Java задумывалась как средство разработки для программиста невысокой квалификации (да простят меня сейчас Java-гуру :-) ).
Java осталась жить по определенным причинам; у нее есть определенные преимущества, которые компенсируют ее недостатки.
Но можно ли однозначно утверждать, что автоматическое управление памятью _лучше_ ручного?
Оставляю этот вопрос на ваше усмотрение.
А можно ли однозначно сказать, что Java проще C++?
Вот пример. Заменить непечатные символы в строке на пробел.
Эта задача в C++ _не является задачей_. Вообще. Почему я так уверен? Потому что Гугл!
Гугл не может найти топика «C++ fastest replacing non-printable characters». Такой темы не существует.
А в Java — это задача. Требуется поиск решения. Требуется копание внутренностей Java.
Постойте, как же так?! Ведь Java это же «слошное хорошее»?! Это же стандартная библиотека, абстракция за абстракцией, ООП везде инужно печтать очень много букф знакомый синтаксис!
Байты спрятались за классами. Это хорошо. И это плохо.
Еще догма.
«XML отлично подходит для хранения настроек»
Хранение персистентных (переживающих жизнь самого приложения) настроек — это сложность. Решает ли эту сложность XML?
Не читайте дальше, подумайте.
XML действительно удобен из-за своей иерархической структуры. Он позволяет быстро получать доступ к нужной ветке (когда он уже загружен в память). Он легко расширяется. Он хранится в текстовом файле, который может быть отредактирован вручную человеком.
Итак, у нас есть 100 мегабайтный XML-файл с настройками. Я хочу поменять в настройках один флаг с «0» на «1», то есть фактически один байт. Сколько байт мне придется записать на диск, чтобы отразить эту замену?
100 (сто) мегабайт.
Да, XML неплох для хранения read-only настроек. Но сложность, связанная с персистентностью, никуда не ушла. Она «прикрылась» небольшим размером XML-файлов.
Чтобы получить доступ к малюсенькой настройке требуется прочесть целиком весь XML-файл. Чтобы сохранить малюсенькое изменение — надо записать целиком файл.
Почему так вышло?
Давайте вычленим самое главное «хорошее» XML.
Это «человеко-читаемый» текстовый формат.
Бывает хорошее без плохого? Не бывает!
«Хорошее» всегда идет под руку с «плохим» — текстовый формат убог при больших объемах данных. Его невозможно обновлять по частям. Его нужно полностью загрузить в память, чтобы прочесть минимальный фрагмент данных.
Опять мы убеждаемся — плохое (т.е. сложность) никуда не ушла.
Хотим настоящую персистентность — RDBMS нам в помощь. Она контролирует эту сложность, отнимая у нас иерархию, человеко-читаемый формат и прямой доступ к настройкам (только через язык запросов — SQL).
И так далее.
Так можно ли сделать программирование простым? Существует ли «серебряная пуля», которая позволит школьникам создавать за пару дней свои операционные системы?
Нет, программирование было и осталось сложным.
Появилось много технологий, которые держат под контролем разные аспекты этой сложности.
Но сказать, что программирование стало простым — нельзя.
Поиск пути разумного контролирования сложности — это хорошо. Поиск пути без сложности — потеря времени.
PS Примеры в этой статье намеренно упрощены. Это сделано, чтобы статья не превратилась в многотомный труд. Разумеется, любая из затронутых тем является более глубокой и многосторонней.
Догмой (применительно к разработке) является утверждение о том, что некоторая технология (или технологическое решение) является абсолютным добром, то есть обладает преимуществами, не имея недостатков.
Основная мысль этой статьи — подобное догматическое мышление весьма распространено в индустрии, но оно вредно и ведет к печальным результатам.
Начнем с того, что программирование — это плохо. Почему?
Потому что оно сложное. Что лучше? Конструирование.
Ошибки конструирования видны сразу. Ошибки программирования незаметны.
Программирование — трудоемкий процесс, требующий массы знаний и умений. Конструирование требует низкой квалификации.
Представьте, что 25 лет назад вам поставили задачу — запрограммировать «динамическую страницу с картинками и текстом», которая высвечивает ссылки, при нажатии на них высвечивает другую «динамическую страницу» и так далее.
Представьте себе трудности, связанные с реализацией такой программы. На разных платформах.
А сейчас? А сейчас любой ботаник за день сконструирует такую страницу из HTML и CSS. Причем ошибки при конструировании такой страницы, как правило, видны сразу и легко исправляются.
Итак, программирование — это сложно. То есть трудоемко, требует высокой квалификации и большой команды, содержит неочевидные «подводные камни», нуждается в выработке архитектуры и т.д.
Сложность присуща программированию по его природе. Она неизбежна. Это «темная сторона» программирования.
Но есть и «светлая сторона». Программирование дает и неоспоримо хорошее — программы, поведение которых позволяет решать разнообразные задачи, операционные системы, драйвера и пр.
Догматический взгляд на программирование (как процесс в целом) часто сводится к отрицанию его сложности.
Но этот взгляд не всегда высказывается явно. Например, некоторые апологеты, евангелисты и другие пациенты любят утверждать, что программирование «пока еще является сложным». Но вот с появлением «вот этой вот штуки все изменится».
Давайте рассмотрим далее догму о том, что…
«автоматическое управление памятью (java) лучше (проще) ручного (C++) и, вообще, Java (C#) лучше C++»
Ручное выделение и освобождение памяти — это сложность.
Однако, есть определенные техники, которые позволяют управлять этой сложностью, то есть держать под контролем.
Например. Любой ресурс (который нуждается в явном освобождении) всегда принадлежит какому-то объекту. Он выделяется при создании объекта и возвращается системе при уничтожении объекта. Любой объект всегда принадлежит другому объекту. На самом верху этой иерархии находится главный владелец всех объектов — приложение.
Если требуется разделить владение объектом, вводим владельцев со счетчиком. Последний владелец (который установил счетчик в ноль) освобождает объект. Владение объектом можно явно передать.
Зачем пишу это здесь? Чтобы стал понятен уровень сложности.
Из своей практики могу сказать, что эти приемы решают 99% проблем ручного управления памятью. Никаких больше настроек или хитростей не требуется; только внимательность.
И вот приходит автоматическое управление памятью. И «упрощает» эту сложность.
Ушла ли сложность? Нет, конечно. Она трансформировалась.
Появился сборщик мусора. Это отдельная задача, которая требует ресурсов в непредсказуемые моменты времени (приостанавливая ваше приложение). Его требуется настраивать, то есть сборщик привносит свою (дополнительную) сложность.
Из языка ушел автоматический деструктор и простейшая задача — закрыть файл в том же месте кода, где он был открыт — превратилась в сложность. Финалайзер не решает эту сложность.
Самое интересно — нехватка памяти. Оказывается, в java она теперь стала _разной_. Если в C++ нехватка памяти означала нехватку памяти, то в Java нехватка памяти означает… Да непонятно что! Еще одна сложность.
Уф. Ну, хорошо, меня загрузили по уши новой сложностью. Но взамен? Взамен-то я избавлен, наконец, от утечек памяти, если у меня есть автоматическая сборка мусора?
НЕТ.
В чем тут был догматизм? И почему так вышло? Попробую объяснить.
Сложность требует высокой квалификации.
Программирование — как сложный процесс — требует высокой квалификации. Это дорого.
Взрывной рост IT привел к взрывному повышению спроса на разработчиков.
Нашлась умная голова, которая решила, что можно сделать программирование простым, то есть возможным с помощью разработчиков низкой квалификации.
Java — это и есть одна из таких попыток. Java задумывалась как средство разработки для программиста невысокой квалификации (да простят меня сейчас Java-гуру :-) ).
Java осталась жить по определенным причинам; у нее есть определенные преимущества, которые компенсируют ее недостатки.
Но можно ли однозначно утверждать, что автоматическое управление памятью _лучше_ ручного?
Оставляю этот вопрос на ваше усмотрение.
А можно ли однозначно сказать, что Java проще C++?
Вот пример. Заменить непечатные символы в строке на пробел.
Эта задача в C++ _не является задачей_. Вообще. Почему я так уверен? Потому что Гугл!
Гугл не может найти топика «C++ fastest replacing non-printable characters». Такой темы не существует.
А в Java — это задача. Требуется поиск решения. Требуется копание внутренностей Java.
Постойте, как же так?! Ведь Java это же «слошное хорошее»?! Это же стандартная библиотека, абстракция за абстракцией, ООП везде и
Байты спрятались за классами. Это хорошо. И это плохо.
Еще догма.
«XML отлично подходит для хранения настроек»
Хранение персистентных (переживающих жизнь самого приложения) настроек — это сложность. Решает ли эту сложность XML?
Не читайте дальше, подумайте.
XML действительно удобен из-за своей иерархической структуры. Он позволяет быстро получать доступ к нужной ветке (когда он уже загружен в память). Он легко расширяется. Он хранится в текстовом файле, который может быть отредактирован вручную человеком.
Итак, у нас есть 100 мегабайтный XML-файл с настройками. Я хочу поменять в настройках один флаг с «0» на «1», то есть фактически один байт. Сколько байт мне придется записать на диск, чтобы отразить эту замену?
100 (сто) мегабайт.
Да, XML неплох для хранения read-only настроек. Но сложность, связанная с персистентностью, никуда не ушла. Она «прикрылась» небольшим размером XML-файлов.
Чтобы получить доступ к малюсенькой настройке требуется прочесть целиком весь XML-файл. Чтобы сохранить малюсенькое изменение — надо записать целиком файл.
Почему так вышло?
Давайте вычленим самое главное «хорошее» XML.
Это «человеко-читаемый» текстовый формат.
Бывает хорошее без плохого? Не бывает!
«Хорошее» всегда идет под руку с «плохим» — текстовый формат убог при больших объемах данных. Его невозможно обновлять по частям. Его нужно полностью загрузить в память, чтобы прочесть минимальный фрагмент данных.
Опять мы убеждаемся — плохое (т.е. сложность) никуда не ушла.
Хотим настоящую персистентность — RDBMS нам в помощь. Она контролирует эту сложность, отнимая у нас иерархию, человеко-читаемый формат и прямой доступ к настройкам (только через язык запросов — SQL).
И так далее.
Так можно ли сделать программирование простым? Существует ли «серебряная пуля», которая позволит школьникам создавать за пару дней свои операционные системы?
Нет, программирование было и осталось сложным.
Появилось много технологий, которые держат под контролем разные аспекты этой сложности.
Но сказать, что программирование стало простым — нельзя.
Поиск пути разумного контролирования сложности — это хорошо. Поиск пути без сложности — потеря времени.
PS Примеры в этой статье намеренно упрощены. Это сделано, чтобы статья не превратилась в многотомный труд. Разумеется, любая из затронутых тем является более глубокой и многосторонней.