image


Предлагаю вашему вниманию перевод оригинальной статьи Роберта С. Мартина.


За последние несколько месяцев я попробовал два новых языка. Swift и Kotlin. У этих двух языков есть ряд общих особенностей. Действительно, сходство настолько сильное, что мне стало интересно, не является ли это новой тенденцией в нашей языкомешалке. Если это действительно так, то это тёмный путь.


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


Проблема в том, что оба языка сделали ставку на сильную статическую типизацию. Кажется, оба намерены заткнуть каждую дыру в своём родном языке. В случае со Swift – это странный гибрид C и Smalltalk, который называется Objective-C; поэтому, возможно, упор на типизацию понятен. Что касается Kotlin – его предком является уже довольно строго типизированная Java.


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


Дело не в том, что меня беспокоит статическая типизация Swift и Kotlin. Скорее меня беспокоит глубина статической типизации.


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


Swift и Kotlin, с другой стороны, становятся абсолютно непреклонными, когда дело доходит до их правил типов. Например, в Swift, если вы объявите функцию, которая бросает исключение, то каждый вызов этой функции, вплоть до начала древа вызовов, должен быть обёрнут в блок do-try, или try!, или try?. В этом языке нет способа тихо выбросить исключение вплоть до верхнего уровня, без прокидывания через все древо вызовов. (Вы можете посмотреть, как Джастин и я боремся с этим, в наших видеоматериалах Mobile Application Case Study)


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


А теперь вопрос. Кто должен разруливать все эти риски? Язык? Или это работа программиста?

В Kotlin, вы не можете наследоваться от класса, или переопределить функцию, пока вы не отметите этот класс или функцию ключевым словом open. Вы также не можете переопределить функцию, если она не отмечена ключевым словом override. Если вы не объявите класс как открытый для наследования, язык не позволит вам наследоваться от такого класса.


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


А теперь вопрос. Кто должен разруливать все эти риски? Язык? Или это работа программиста?

Оба языка, Swift и Kotlin, включают в себя концепцию обнуляемых типов (nullable). Тот факт, что переменная может содержать null, становится частью типа этой переменной. Переменная типа String не может содержать значение null, она может содержать только конкретную строку. С другой стороны, переменная типа String? имеет обнуляемый тип и может содержать null.


Правила языка настаивают на том, что когда вы используете переменную, допускающую значение null, вы должны сначала проверить эту переменную на null. Так что если s это String? тогда var l = s.length не будет компилироваться. Вместо этого вам следует писать так: var l = s?.length ?: 0 или var l = if (s != null) s.length else 0.


Возможно, вы думаете, что это хорошо. Возможно, вы видели довольно много NPE в вашей жизни. Возможно, вы знаете, без тени сомнения, что непроверенные null`ы являются причиной сбоев программного обеспечения на миллиарды и миллиарды долларов. (Действительно, документация Kotlin называет NPE «Billion Dollar Bug»). И, конечно, вы правы. Очень рискованно иметь неконтролируемые null`ы повсюду.


А теперь вопрос. Кто должен разруливать все эти null`ы? Язык? Или это работа программиста?

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


Но пока пальцы на руках и ногах не закончились, мы создаём языки, которые содержат десятки ключевых слов, сотни ограничений, извилистый синтаксис и справочное руководство, которое читается как книга закона. Действительно, чтобы стать экспертом в этих языках, вы должны стать юристом по языку (термин, который был изобретен в эпоху C++).


Это неверный путь!

Спросите себя, почему мы пытаемся исправить дефекты языковыми функциями. Ответ должен быть очевиден. Мы пытаемся исправить эти дефекты, потому что эти дефекты случаются слишком часто.


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


И что же программисты должны делать для предотвращения дефектов? Я загадаю вам загадку. Вот пара подсказок. Это глагол. Он начинается на букву «Т». Да. Вы поняли. ТЕСТИРОВАТЬ!


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


Почему эти языки используют все эти функции? Потому что программисты не покрывают тестами свой код. И поскольку программисты не тестируют свой код, у нас теперь есть языки, которые заставляют нас ставить слово open перед каждым классом, от которого мы хотим наследоваться. Теперь у нас есть языки, которые заставляют нас оборачивать каждую функцию, сквозь всё древо вызовов, в блок try!. Теперь у нас есть языки, которые настолько ограничены и настолько переобусловлены, что нужно проектировать всю систему заранее, прежде чем начать кодить.


Рассмотрим пример. Как узнать, открыт ли класс для наследования или нет? Как я узнаю, что где-то вниз по древу вызовов кто-то может выбросить исключение? Сколько кода мне придется изменить, когда я наконец узнаю, что кто-то действительно должен вернуть null в древе вызовов?


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


И из-за всего этого есть основания полагать, что они наказывают вас, когда вы неправы. Они заставляют вас вернуться назад и изменить огромное количество кода, добавив try! или ?: или open сквозь всё древо вызовов.


И как вы избегаете этого наказания? Есть два пути. Тот, который работает, и тот, который не работает. Тот, который не работает, заключается в том, чтобы проектировать всё перед написанием кода. А тот, который избегает наказания, должен переопределить все меры предосторожности.


И поэтому вы объявляете все свои классы и все свои функции открытыми для наследования. Вы никогда не используете исключения. И вы привыкаете к использованию большого количества символов ! для переопределения проверок на null и позволяете NPE расплодиться в своих системах.




Почему атомная станция в Чернобыле загорелась, расплавилась, разрушила небольшой город и оставила большую территорию непригодной для жизни? Они переопределили все меры предосторожности. Так вот, не надо полагаться на безопасность, чтобы предотвратить катастрофу. Вместо этого лучше привыкнуть к написанию большого количества тестов, независимо от того, какой язык вы используете!

Поделиться с друзьями
-->

Комментарии (75)


  1. NaHCO3
    16.03.2017 16:29
    +20

    > Потому что программисты не покрывают тестами свой код

    Тьюринг полнота намекает, что покрыть тестами ВЕСЬ свой код невозможно. А вот если взять некоторое ограниченное подмножество от языка, то для него можно показать корректность. Именно этим и занимается статическая типизация. Доказывает, что некоторые элементы программы, которые целиком укладываются в это подмножество — корректны. Конечно, у вас есть опасные связи между этими островками безопасности, которые нарушают гарантии, но вы знаете где именно вам надо пытаться искать ошибки тестами — на границе!

    > Они предполагают, что вы знаете, какие классы должны быть открыты для наследования, а какие нет.

    Начните с final. По мере необходимости можете final снимать. Но вообще final очень полезная штука для escape analysis.


    1. DexterHD
      16.03.2017 16:39
      -9

      Вы это Дяде Бобу объясняете?


  1. ik62
    16.03.2017 16:57

    Пусть пробует D — хороший баланс фич сделает его шерсть мягкой и шелковистой.


  1. snuk182
    16.03.2017 16:58
    +18

    С трудом дочитал до конца — уровень истерики и субъективизма зашкаливает.

    Дефекты — это ошибка программистов. Это программисты создают дефекты, а не языки.

    image


    1. maxru
      16.03.2017 17:00
      +4

      Языки, в свою очередь, иногда этому способствуют.


      Псст, парень, не хочешь объехать этот мучительный участок на потайном велосипеде?


      1. snuk182
        16.03.2017 17:24
        +12

        А блин, я только заметил — это же мой любимый Роберт Мартин, гений тоталитаризма в софтверном менеджменте. До сих пор при одном упоминании о книге «The Clean Coder» хочется убивать, даже несмотря на то, что там по сути довольно здравые вещи. Но стиль изложения все перечеркивает — собственные шишки достижения преподносятся как неотъемлемая часть профессионального роста любого программиста, что позволяет с высоты своего, так сказать, опыта поплевывать на седины измучившихся и жаждущих ценного совета салаг. Ну прямо как на форуме рожениц — девочка, которая «уже», не минует возможности поучить тех, кто только ждет своей участи.


        1. raveclassic
          17.03.2017 23:32
          +1

          Метко!


  1. maxru
    16.03.2017 16:59
    +4

    То есть тезисно получается, что язык программирования что-то должен разработчику/Бобу?


  1. phillennium
    16.03.2017 17:18
    +12

    Если после текста заинтересовало мнение «другой стороны» — этот пост недавно как раз обсудили в интервью на Хабре Андрей Бреслав, возглавляющий Kotlin, и Антон Кекс, пишущий на Kotlin:

    «Антон: Андрей, а ты видел интереснейший пост Uncle Bob как раз на тему Kotlin и nullability? Он хорошо прошёлся по этой nullability, мне интересен твой комментарий.

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

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

    Во-вторых, там есть некоторые конкретные аргументы «как же, если я, например, сделал какой-нибудь тип в своей программе nullable, то мне ж теперь надо поменять всю остальную программу, чтобы эта программа скомпилировалась». Этот момент я не понимаю, потому что — да, конечно, нужно что-то поменять, это содержательно. Если какой-то тип стал nullable, значит, код, который этот тип использует, должен учесть этот факт, иначе он будет неправильно работать! И, конечно, этот код надо поменять. Ну, можно его запустить, получить исключение, и поменять потом, а можно просто сразу поменять. Вот в Kotlin надо сразу.

    Там ещё есть какие-то аргументы, аналогии с const в C++, ещё чем-то — эта аналогия не совсем корректная, по-моему.

    Антон: При всём уважении к Uncle Bob, мне тоже кажется, что он просто использовал возможность ещё раз сказать «вы всё равно должны писать тесты для своего кода, и компилятор вас не спасёт». В чём он, в принципе, прав, но мне лично очень нравится в Kotlin эта фича с nullability, может быть, для меня это даже одна из основных фич, ради которых хочу писать на Котлине. С другой стороны, бывает такое, когда Kotlin не позволяет мне легко описать то, что я хочу, компилятор говорит, что я должен где-то поставить либо ?, либо !!.. В последнее время, когда у меня всё больше опыта с языком, мне всё меньше приходится бороться с компилятором, но есть такие кейсы. Для этого есть ещё ключевое слово lateinit, которое иногда помогает. Так что есть и плюсы, и минусы, но мне кажется, что всё-таки уклон ушёл в правильную сторону, что от этого больше пользы, чем неудобства.

    Андрей: Безусловно, я согласен, что минусы есть, но за всё надо платить. Если мы хотим, чтобы компилятор что-то гарантировал, то требуется какое-то количество работы с нашей стороны. Здесь просто вопрос, что более оправданно. По-моему, опыт нас самих и всех остальных людей с Kotlin показывает, что введение nullable-типов вполне оправдано, получилось хорошо. »


    1. Nakosika
      16.03.2017 18:59
      -5

      Анкл Боб вполне справедливо не хочет переписывать пол программы когда переменная стала nullable. Скорее всего она стала nullable только в какой-то определенный промежуток времени (к примеру во время инициализации), а вообще там нул можно не учитывать. Проверка на нул нужна только если мы пишем ifelse на основании того есть там какие-то данные или нет. В других случаях это синтаксический шум, который будет скрывать нулы, и провоцировать ошибки которые тяжело найти.


      1. guai
        16.03.2017 19:21
        +1

        в котлине есть lateinit как раз для этого


        1. AlexTheLost
          16.03.2017 20:36

          В статье есть и на это ответ :)


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

          Я за Option.)


          1. guai
            16.03.2017 23:55
            +2

            с другой стороны, а куда мне еще девать пальцы, солить?
            какая-то высшая цель есть, чтоб их не использовать?

            вы за опшен, ваш коллега против, и будете вы в свои опшны нуллы получать :)
            или можно потратить палец и решить проблему кардинально


            1. solver
              17.03.2017 10:39
              +1

              Так о том-то и речь собственно, что проблема кардинально не решена.
              Просто пальцем заткнули дырку…


      1. Guzergus
        17.03.2017 06:16
        +3

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

        Других сценариев «переменная взяла и стала nullable» я, честно говоря, не вижу.


  1. reforms
    16.03.2017 17:25

    Я не первый раз слышу про проблемы Kotlin и ?: и даже местами понимаю автора. Здесь вот интересно, можно ли провести аналогию с Generic в Java — определенную избыточность на уровне синтаксиса, особенно до появления Diamond Operator? Просто я помню свои возмущения когда приходилось писать полностью Map<String, String> someName = new HashMap<String, String>(); Мне таки казалось эта конструкция невозможной многословностью — ведь я сам знаю, что пишу!


    1. Sirikid
      18.03.2017 04:33

      Зато вывод типов не надо прикручивать.


  1. yarric
    16.03.2017 17:26
    -4

    Из статьи больше всего понравилась ссылка на языкомешалку. Это действительно проблема, поскольку, несмотря на то, что новые языки не добавляют почти ничего концептуально нового по сравнению с языками 70-х — 80-х годов, они всё-же разняться в множестве мелких деталей и требуют много времени на освоение. Лучше бы это время потратить на программирование или создание новых подходов к программированию, как это делается для того же JavaScript, даже для старой версии которого было написано немало оригинальных фреймворков.


    1. sleeply4cat
      16.03.2017 17:40
      +2

      Есть перевод на хабре.
      https://habrahabr.ru/post/306782/


    1. snuk182
      16.03.2017 18:00
      +24

      C++ — самая наглядная демонстрация кривости подхода «старым языкам — новые подходы».
      Пока вы один, вы можете писать самый чистый и идеологически верный код в мире, но стоит команде расшириться, начинается пыщь пыщь ололо. Пойдут линты, хуки на коммиты, тренинги, в крайних случаях придется ставить грязный, вонючий, весь в солидоле костыль, минуя все хуки и линты, потому что прод упал, а возиться с идеологией некогда. Рано или поздно придет кто-то не знающий о правилах поведения и начнет совать код в стиле «я так тридцать лет пишу, что вы меня учите?». В то же время запрет городить фигню на уровне компилятора резко сужает необходимость распыляться на мелочи и больше внимания уделить тому, что ты, собственно, хочешь сделать.


      1. hanovruslan
        16.03.2017 19:40
        +3

        Кармы не хватает за этот камент вручить жирный плюс


      1. yarric
        16.03.2017 22:28

        С C++ проблема в том, что каждый может программировать на каком-то его подмножестве, да и в принципе у него нет какого-то определенного дизайна, просто нагромождение фич.


        1. kosmos89
          17.03.2017 13:36
          +2

          У современного C++ есть дизайн, но проблема в том, что в нем для совместимости оставлены практически все старые фичи.


          1. Gryphon88
            20.03.2017 19:45

            А можете посоветовать книжку или проект, где этот дизайн демонстрируется? Я примерно на Срр03 его потерял


    1. develop7
      16.03.2017 18:08
      +2

      новые языки не добавляют почти ничего концептуально нового по сравнению с языками 70-х — 80-х годов

      define «почти ничего» и «языки 70-80гг»


      1. yarric
        16.03.2017 23:39
        -2

        В современных языках трудно найти какую-либо существенную фичу, которой меньше 30 лет. Отличия языков друг от друга, и от более "старых" языков всё больше сводятся к вкусовщине вроде нюансов наименований ключевых слов и синтаксическому сахарку.


        1. develop7
          16.03.2017 23:44
          +3

          Это я уже понял. Так какие именно языки вы имеете в виду? Приведите характерных примеров.


          1. yarric
            17.03.2017 08:50
            +1

            Примеры чего? Давно реализованных фич? ООП, корутины, сборка мусора — Simula-67, 1967 год. Исключения — PL/I, 1964 год. Функциональное программирование — LISP, 1958 год.


            1. develop7
              17.03.2017 10:36
              +1

              Лихо вы всё функциональное программирование лиспом ограничили. Ну ладно, а pattern matching?


              1. yarric
                17.03.2017 14:00
                +1

                ML, NPL, SNOBOL — 60-е — 70-е годы.


                1. 0xd34df00d
                  18.03.2017 09:19
                  +3

                  Зависимые типы?


                  1. yarric
                    23.03.2017 00:39

                    Nuprl, в 80-х появился, сама теория ещё в 30-х. Не сказал бы, что это сильно распространённый подход в современных языках.


              1. e_Hector
                24.03.2017 12:58

              1. spinagon
                24.03.2017 12:58

                SNOBOL, 1962


        1. samsergey
          23.03.2017 01:57
          +3

          Настоящие и стОящие теории требуют вдумчивой проверки временем и длительного осмысления, после чего они превращаются в непотопляемый и неподвластный моде фундамент. Развитие современных ЯП состоит в создании эффективных механизмов для воплощения фундаментальных идей и в поиске современных задач, решаемых "старыми" методами. Изоморфизм Карри-Ховарда, в конце концов, сводит большинство "новых" подходов в программировании к "старым" подходам в алгебре, логике или топологии. Но это не значит, что всё уже "украдено до нас" и "всё в географии открыто".
          Кстати, находка по-настоящему удачного синтаксического сахара к полезной, но неудобоваримой теоретической конструкции — это очень важная составляющая прогресса. Изобретение бра и кет векторов для исчисления состояний, оператора Гамильтона для представления дифференциальных операторов в теории поля, диаграмм Фейнмана для описания механики частиц, регулярных выражений для представления конечных автоматов, введение do-нотации для монад и адаптация коалгебры для комонады косостояния в виде изящных линз в Haskell, "толстые" стрелки для представления громоздких делегатов… все эти синтаксические нововведения не являются чем-то фундаментальным, но они позволяют просто и последовательно рассуждать о сложных концепциях, не теряя внутренней структуры концепции. Это сродни открытию нового представления для группы или построения изоморфизма между абстрактной "невидимой" структурой и житейским "обозримым" понятием. Это классная, красивая, хоть и непростая и небыстрая часть прогресса!


  1. sbnur
    16.03.2017 18:11

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


    1. WinPooh73
      16.03.2017 23:18
      +1

      Одной из проблем Чернобыля была такая конструкция реактора, в которой при введении стержней в зону на некотором участке их хода реактивность не падала, а возрастала… Кто ещё не читал — всем рекомендую Дятлова, физика процесса там подробно описана.


      1. sbnur
        16.03.2017 23:55

        при чем тут конструкция — как я написал была потеряна управляемость реактора — если машину на скользком участке заносит от неудачного маневра, то виновата конструкция?
        Кстати, Смоленская АЭС с реактором РБМК, как на Чернобыле, в 2011 году получила высокую оценку экспертами МАГАТЭ


        1. netch80
          19.03.2017 09:38
          +2

          если машину на скользком участке заносит от неудачного маневра, то виновата конструкция?

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


          Кстати, Смоленская АЭС с реактором РБМК, как на Чернобыле, в 2011 году получила высокую оценку экспертами МАГАТЭ

          После Чернобыльской аварии все РБМК подверглись коренной переработке управляющих конструкций и пересмотру правил эксплуатации.


          1. sbnur
            19.03.2017 09:46

            насчет диверсии это слишком — конечно недостатки есть в любом промышленном объекте, причем исходная разработка была направлена не на мирный атом.
            Но несоблюдение правил и непрофессионализм в том смысле о котором я сказал — и есть причина аварии
            Кстати аналогичная ава рия была ранее в США на станции Тримайлайленд — где тоже причиной были ошибки персонала


            1. netch80
              19.03.2017 15:29

              насчет диверсии это слишком — конечно недостатки есть в любом промышленном объекте, причем исходная разработка была направлена не на мирный атом.

              Именно. Перевод на "мирные рельсы" без адекватного обеспечения (хотя и начальная разработка в таком опасном виде).


              Но несоблюдение правил и непрофессионализм в том смысле о котором я сказал — и есть причина аварии

              Неотъемлемая компонента причины, вместе с проблемами конструкции.


              1. sbnur
                19.03.2017 15:52
                -1

                Нет проблем в конструкции — эти реакторы продолжали выпускать — и они работают на ряде станций.
                То есть если на одном автомобиле кто-то разбился, не справившись управлением, то виновата не конструкция.
                Все остальное про недостатки конструкции просто досужие рассуждения
                Скажите какие конкретно были недостатки, если такие реакторы продолжают эксплуатироваться


          1. sbnur
            19.03.2017 09:53

            и какие были закрыты или переделаны —
            Кстати вы представляете себе, что такое переделать действующий реактор


            1. netch80
              19.03.2017 15:22

              Кстати вы представляете себе, что такое переделать действующий реактор

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


              1. sbnur
                19.03.2017 15:46

                Плохо представляете, несмотря на техническое образование — вот на Чернобыле также думало руководство — инженер — значит пусть работает, а то, что нужно более продвинутая подготовка.в области ядерной физике, то это просто ерунда. Вот смена и смотрела на реактор, как на кастрюлю с кипчящей водой — убавил — потише стало кипеть, добавил — посильнее.
                Самое печальное, что вины на них нет — нарушение эксплутационных условий в силу недостаточной подготовки.

                Да — кстати причем тут стержни — какая работа должна быть сделана — их нужно добавить?, то есть сделать новые каналы — или как? Напомню в действующем реакторе

                Кстати на последующих моделях РБМК модификация заключалась в увеличении мощности от РБМК1000 к РБМК1500 и так далее


        1. t-nick
          24.03.2017 12:58

          Проблема была в том, что конструктора реактора отрицали наличие в нем «уязвимости». На момент аварии о ней никто толком не знал, несмотря на то, что она себя уже проявляла ранее.


          1. sbnur
            25.03.2017 10:01

            Вы, думается сами понимаете, что не существует в принципе неуязвимых конструкций, и этого ни один конструктор и ни один инженер утверждать не будет — это журналистские бредни
            Любая конструкция может разрушится в силу случайного или преднамеренного стечения обстоятельств
            Бык надежен, пока у него в носу кольцо.
            Как я писал подобная авария была прежде на америкаской АЭС, разница только в последствиях — урон от Чернобыля выше (значительно) — американцам повезло. Но результат один блок — находится под саркофагом


        1. really4g
          24.03.2017 12:58

          Согласно информации (и не только этого источника) РБМК после Чернобыля, на станциях, оснащенных реакторами РБМК, были осуществлены мероприятия по модернизации, с целью повышения надежности и безопасности. И как мне видится Смоленская АЭС именно поэтому получила высокую оценку. Я думаю, что реактор Чернобыльской АЭС вряд ли бы сейчас получил оценку подобную Смоленской АЭС.


          1. sbnur
            25.03.2017 10:13

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


  1. guai
    16.03.2017 20:29

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


    1. kolipass
      17.03.2017 10:12
      +1

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


      List<Integer> list = new ArrayList<>();
      list.add(1);
      assert list.size()==1;

      не будет работать у потомка:


      List<Integer> list = new DoubleList<>();
      list.add(1);
      assert list.size()==1;

      Ну и, соответственно, если кто-то подложит в реализацию вместо ArrayList, DoubleList то логика в приложении пойдёт не по задуманным рельсам.


      1. sAntee
        17.03.2017 10:26

        А это, насколько я понимаю, «фича» джавы — что любой метод, если не сказано обратное, виртуальный. В C# и C++ вот, например, не так, и ничего, живем.


        1. DarkEld3r
          17.03.2017 11:10

          Дык, разве против этого не такой же самый аргумент будет? Мол как всё final по умолчанию неудобно, так и отсутствие виртуальности (по умолчанию) тоже неудобно.


          И я действительно встречал людей, которые считают, что (в С++) лучше писать virtual для каждой функции: мол так удобнее и гибче, а то вдруг автор оригинального класса что-то не продумал, а поменьять поведение в наследники уже нельзя. Переубедить не удалось.


      1. guai
        17.03.2017 12:18
        +1

        Вот как раз такого я и не видел никогда в реальном коде.
        Я вполне понимаю, почему класс Class финальный. ArrayList кстати не финальный, но даже если бы и был, я бы, наверное, подумал, что была причина. А вот зачем всё подряд делать финальным — убей не понимаю.

        Это уже моя ответственность сделать так, чтоб мои наследники ничего не ломали. Зачем у меня вообще отбирать возможность даже попытаться сделать правильно?

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


        1. kosmos89
          17.03.2017 13:46

          А вот зачем всё подряд делать финальным — убей не понимаю.

          Возможно, для оптимизации.


          1. snuk182
            18.03.2017 00:07

            Для «Composition over Inheritance».


            1. kosmos89
              18.03.2017 00:23

              Отсутствие final не мешает делать композицию.


              1. snuk182
                18.03.2017 00:41

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

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


    1. Beholder
      18.03.2017 13:59

      Есть плагин Kotlin компилятора, который классы делает open по умолчанию. Или все, или помеченные определёнными аннтоциями (например, для Spring).


  1. samsergey
    16.03.2017 22:19
    +5

    А теперь вопрос. Кто должен разруливать все эти риски? Язык? Или это работа программиста?


    А кто должен писать тесты? Язык? Или это работа программиста?

    Строгая, стройная система типов без «нельзя, но если очень хочется, то можно» даёт возможность использовать системы автоматической генерации тестов, типа QuickCheck, что позволяет упростить работу программиста.


  1. s_suhanov
    17.03.2017 00:12
    +5

    Истерика про опциональные типы особенно доставила. Жаль, что не упомянули о том, что таким образом на 99.9% снижается вероятность краша приложения. Но разве это важно? )))


  1. i_user
    17.03.2017 09:26
    +7

    Такое ощущение, что человек написавший это, при всем уважении, не совсем понимает что такое Optional type.
    Это не про NPE, а про, черт возьми, настоящую строгую типизированность. Когда сущность какого-то типа обозначает именно сущность этого типа, а не «Стринг — это, конечно, Стринг, но иногда еще и null».

    Я не знаю кейса, когда из-за этого не хватило какой-то гибкости языка.

    P.S.

    А теперь вопрос. Кто должен разруливать все эти риски? Язык? Или это работа программиста?


    Работа программиста — фичи деливерить, а не выдавать код нравящийся кому бы то ни было. Если какая-то функциональность позволяет деливерить фичи быстрее с более высоким уровнем качества, не повышая при этом существенно порог входа в технологию (возможно при этом мешая нескольким фрикам делать какую-то жесть) — эта функциональность хорошая.


    1. Johan
      17.03.2017 12:59
      +1

      Вот, да. Эта истерика напоминает лозунги луддитов, но те работы лишались, у них был весомый повод.


      1. snuk182
        17.03.2017 14:01
        +1

        Тут тоже не очень далеко от правды, имхо: больше дисциплины при программировании — меньше проблем в работе — меньше проблем в синхронизации участников команды — меньше поводов обращаться к «консультантам по аджайлу и ТДД».


        1. Johan
          17.03.2017 15:45
          +1

          Вот и смысл подвезли. Как говаривает один небезызвестный человек: "Если не понятно в чём дело, значит дело в деньгах".


          1. potorof
            24.03.2017 12:58

            Конечно, и бессмысленно рассматривать вопрос «что лучше» вне этого контекста.


  1. LooMaclin
    17.03.2017 12:32
    +4

    Rust наше всё:


    Result<T,E> и Option<T>

    И отсутствие NPE. И всё прочее.


    1. snuk182
      17.03.2017 13:57
      +3

      Тсс, пожалейте беднягу — он ведь тоже кушать хочет, а если все начнут использовать строго формализованные безопасные языки, его работа станет не нужна )


  1. kosmos89
    17.03.2017 14:07
    +1

    А теперь вопрос. Кто должен разруливать все эти риски? Язык? Или это работа программиста?

    Ну пусть пишет на азме. Это же его работа...


    Спросите себя, почему мы пытаемся исправить дефекты языковыми функциями.

    И что же программисты должны делать для предотвращения дефектов? Я загадаю вам загадку. Вот пара подсказок. Это глагол. Он начинается на букву «Т». Да. Вы поняли. ТЕСТИРОВАТЬ!

    А как по мне, так это тестирование является костылем. Причем автору лень писать формальную спецификацию, и предлагает разменять формальную верификацию на ручное, все равно неполное, тестирование. Так где тут выгода, если все равно что-то придется дополнительно писать?


    Чернобыль. Тесты.

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


    1. netpilgrim
      24.03.2017 12:58

      Причем автору лень писать формальную спецификацию, и предлагает разменять формальную верификацию на ручное, все равно неполное, тестирование.

      Боб — пропагандист TDD. Очень маловероятно, что речь была про ручное тестирование.


      1. kosmos89
        24.03.2017 17:17

        Я имел в виду ручное написание тестов для TDD.


  1. Danik-ik
    17.03.2017 20:27

    Присоединяюсь. Писать много тестов на граммотное использование нулла вместо того, чтобы воспользоваться готовыми тестами, встроенными в компилятор мне кажется неразумным. Ибо DRY.


    Final по умолчанию я всё же не понимаю, но паники он у меня не вызывает. Если я не могу унаследоваться от чужого класса — никто не мешает использовать вместо наследования композицию — обернуть его фантиком и проксировать интерфейс, переопределив, что надо, в обёртке. Неидеально из-за несовместимости с исходным классом, но тут уж интерфейсы — наше всё.


    1. Danik-ik
      17.03.2017 20:29

      В смысле, к kosmos89 присоединяюсь. А не к автору исходного текста


  1. Koyotter
    17.03.2017 22:44
    +2

    Читаю вот я, программист-атомщик, комментарии, и у меня такое чувство что практически все засветившиеся, включая дядю боба, атомщики и все знают про Чернобыль и из-за чего беда произошла...


  1. HKA
    24.03.2017 12:59
    +1

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