Pull to refresh

Comments 72

Сам из семьи таких вот физиков-программистов. Для своего времени эти люди очень неплохо знали язык, даже находили ошибки в компиляторах. Но это на всяких БЭСМ-6. Те программы были по сути более лаконичной версией ассемблера. С тех пор всё изменилось, их программы (очень хорошие для своего времени) больше никому не нужны, а переписывать их в лоб не имеет никакого смысла. И компьютерная грамотность, да.

Контакт поколений произошёл когда я начал пробовать Linux. Оказалось, что папа 20 лет назад тоже пользовался vi под советским клоном UNIX :)
никто не обращает внимания на рост сложности программ.… далеко не все знают и задумываются о том, что рост размера программы ведет к нелинейному росту числа ошибок


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

Это та ситуация, когда «достаточно одного раза». Ну и, вообще, они обычно и не разваливаются — просто существуют в почти-рабочем состоянии.
Есть мнение, что рост количества ошибок напрямую с размером кода не связан. Он связан с «кривостями» архитектуры. А вот оные кривости допускаются тем чаще, чем больше проект. В огромном проекте архитекторы должны быть часто семи пядей во лбу. И если мы предположим, что количество «костылей» пропорционально количеству кода, а количество ошибок на строку кода пропорционально количеству «костылей», то вот мы уже получили нелинейную зависимость. Так, на пальцах.

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

ps
Другими словами, допускается ошибок на единицу кода всегда одно и тоже количество, но вот кол-во исправленных ошибок падает экспоненциально из-за ограниченности ресурсов.

pps
Соответственно, большие проекты разваливаются из-за того, что добавление новой небольшой фичи (или исправление трудноуловимого глюка) по стоимости становится сравнимым с разработкой с нуля всего проекта.
никто не обращает внимания на рост сложности программ.… далеко не все знают и задумываются о том, что рост размера программы ведет к нелинейному росту числа ошибок


Что то мне подсказывает, что прораммисты не от нечего делать стремятся упростить задачу и написать меньше кода.
<зануда mode> Если число ошибок более чем линейно растет от размера кода, то рано или поздно оно станет больше, чем битов в коде. Что сомнительно.
Асимптотически — да. Но код становится неподдерживаемым и технически непригодным значительно раньше ;)

Как в том старом анекдоте; есть задача — юноша и девушка стоят друг от друга на расстоянии 2 метра. Юноша очень стеснителен и подходит к девушке медленно. За первую минуту он прошёл 1 метр, за вторую еще полметра, за третью — четверть… в общем, понятно. Вопрос: когда они встретятся?

Ответ математика: никогда
Ответ физика: в бесконечно удаленный момент времени
Ответ инженера: через полчаса они окажутся достаточно близко друг к другу для реализации любых практических надобностей.
Не я с вами в разных мирах. Это мы и они в разных. :)

Вы никогда не слышали историй, когда на крупном предприятии какая-то программа учета представляет собой один здоровый файл с кодом на несколько мегабайт? Типа, постепенно добавляли, добавляли…
Слышал. Но я имел в виду то, что всетаки большинство обращает внимние и задумывается.

Дочитав до этой фраза я остановился и подумал, что это рекламная акция.
Вы предлагаете программистам в сторонних областях подтвержадать квалификацию в этих областях или использовать PVS-Studio?
Я бы не прочь продавать им PVS-Studio. Но это нереально. Как раз наоборот, PVS-Studio покупают те, кто очень хорошо разбирается в создании программного обеспечения. Они понимают, в чем ценность статического анализа и что лишняя проверка не повредит.

Так что эта статья скорее просто мысли в слух. И вдруг, кто-то прочитает и задумается. А то ли и так ли он делает в своем НИИ/заводе/т.д.
хочу добавить, что программы, которые используются для вычислений в серьезных научных и медецинских организациях — обязательно должны проходить серьезное тестирование, которое должно исключить опечатки и ошибки в синтаксе. Даже в вашем примере, физики прежде чем поверить программе — проверили еще одно значение. Так что может все не так фатально?
Какая знакомая проблема :) Поясню, работая в инженерных изысканиях, мы постоянно сталкиваемся с работой таких «калькуляторов», причем в некоторых случаях (например, обработка GNSS-данных) выполнить итерации вручную не представляется возможным. Для контроля используется 2-3 программных идентичных продукта, результаты которых сравниваются и применяются в зависимости от степени «разброса». Иногда приходится подключать «тяжелую артиллерию» в виде научно-коммерческого Bernese, выпускаемого астрономическим институтом Берна…
Как хорошо было бы не использовать C++ для программирования калькулятора. Жалко, что мы живём в реальном мире и люди зачастую не хотят использовать правильные инструменты для решения их задач.
Какие инструменты и языки предлагаете для написания научных программ?
Matlab, например. На нем даже UI для этих научных программ вполне адекватно можно делать.
Расчеты в матлабе медленнее на порядок/порядки
Зависит от техники реализации алгоритма, если всё делать только с помощью матричных операций, скорость будет очень высокой.
Проблема пакетов типа Matlab/Maple в полной непрозрачности того, что они делают. Для анализа типа «реши мне диффур аналитически» они годятся хорошо. Но если вы хотите иметь полный контроль за методом решения (а в любой научной и тем более инженерной задаче вы его хотите), придется кодить ручками.
При всем при этом, Matlab прекрасно подходит для разработки прототипов. Не так уж часто необходимо получать максимальную производительность с первой же итерации.
Отлично подходит язык C#. Несмотря на проседание итоговой производительности по сравнению с кодом на чистом C (примерно в полтора-два раза на математических задачах, в своё время собственноручно измерял), в нем есть строгая типизация, гарантирующая отсутствие многих проблем, великолепный отладчик, отсутствие необходимости явно оперировать с памятью и возможность создавать пользовательский интерфейс довольно легко и быстро.

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

Ну и люди, беспокоящиеся о лицензионной чистоте, добавят сюда, что C# — детище «корпорации зла». Хотя он стандартизован, а mono издан под GPL…

Я на C# писал курсовую — рассчитывал некоторые процессы в полупроводниках при низких температурах. Всё было легко — и считать, и диаграммы красивые рисовать, и графики строить.
Маленькие проекты и курсовые — нормально. Большие не получится, т.к. есть большая разница между расчетами день или два дня, неделя или полмесяца… Особенно, если тестов надо провести много.
Суперкомпьютеры как правило работают на Linux и как программу на C# поднять на суперкопьютере в консоли? И какого будет проседание производительности не в родной платформе?
есть большая разница между расчетами день или два дня, неделя или полмесяца…


1. Если у вас такой пасчет, что даже падение производительности в 2 раза по сравнению с нативной — беда, значит у вас нет выбора, на чём писать. Пишите на C++ (надеюсь, Фортран в качестве реальной альтернативы не рассматривается — те кривые костыли, которыми туда приделали ООП, вызывают слёзы). А что касается тестов — основная потеря времени при написании сложного расчетного софта — его отладка, а не исполнение. Если над программой работают 20 человек и им всем платят деньги, купить еще один компьютер и распараллелить задачу на 2 обычно удаётся. И, кстати, в этом случае лучше использовать язык современный, с нормальной поддержкой сети в стандартной библиотеке.

2. Если всё же так остро проблема с производительностью не стоит, то
Суперкомпьютеры как правило работают на Linux и как программу на C# поднять на суперкопьютере в консоли?

Здесь я могу вам предложить пройти вот сюда: www.mono-project.com/Main_Page
Кроссплатформенная имплементация CLR вместе со стандартными библиотеками позволит вам запустить программу хоть на суперкомпьютере, хоть на кластере. Разумеется, ее необходимо там иметь, но я это уже указывал как недостаток выше. В конце концов, если у вас такая серьёзная программа, то просто добавить в нее код mono и отправить на суперкомпьютер всё вместе — дело 1-2 дней. А производительность под .NET и под mono практически одинакова и отличается на 1-2%
которыми туда приделали ООП, вызывают слёзы
Простите, а зачем для программы, связанной с вычислительной математикой, ООП?
Очень опасаюсь, что получу еще порцию негодования, начав объяснять свою точку зрения подробнее. Но всё же рискну.

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

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

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

А теперь, когда метафора развёрнута, упростим ее.

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

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

И вот эти, вторые работники — объекты. И именно чтобы их создать, нужно ООП.

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

И еще пару слов в оправдание за мой заминусованный комментарий.

Я не знаю, с какими проблемами придется столкнуться при использовании C# на суперкомпьютере. Это надо проверять. Я лишь пытался порекомендовать язык, достаточно мощный для любых практических целей и при этом помогающий хорошо защитить разработчика от случайных ошибок. Подробнее на эту тему я отписался ниже.
И вот эти, вторые работники — объекты. И именно чтобы их создать, нужно ООП.


Собственно, исходя из вашего комментария, у меня ещё сильнее выросло ощущение того, что ООП в вычислительных задачах (причем не суть важно — на суперкомпьютерах или на микроконтроллерах) — исключительно перенос классических практик разработки general purpose software на специфическую предметную область.

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

Все вышенаписанное, имхо, естественно.

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

Но сперва обращу ваше внимание вот на что:
Как средство организации кода — да, использовать ООП можно, но не более.

Возможно, эта мысль покажется вам непривычной, но всё — и функции, и классы — не более, чем средство организации кода. Процессор же, как и 30 лет назад, умеет исполнять лишь совершенно неструктурированные дурацкие команды типа mov, add или cmp. А всё остальное люди придумали для себя. Если же вы намекаете этой фразой на то, что надо использовать классы как «коробочки», в которые просто напихиваются функции, то я вас заклинаю от такого подхода — пишите лучше просто на функциях. ООП — это не ключевое слово «class» в языке. ООП — это, прежде всего, манера мышления, при которой разработчик, разрабатывая и тестируя отдельный класс, выбрасывает из своего сознания все прочие, вернее, он выбрасывает их внутреннее устройство. И именно для того, чтобы подобный подход работал, существует инкапсуляция. Без нее один объект может внезапно изменить внутреннее состояние другого в неожиданный момент. И такая программа будет неуправляемо глючить. Поэтому если вы собираетесь создавать в ваших классах публичные внутренние поля, лучше не используйте классы вовсе. Вам же проще будет.

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


Давайте разберем это утверждение по частям. Во-первых, понятие «высокий уровень инкапсуляции» считаю бессмысленным примерно как «высокий уровень беременности» (применительно к одной женщине). Инкапсулированность класса — понятие модальное. Либо она есть, либо нет. Если класс допускает возможность менять своё внутреннее состояние без своего ведома, значит он не инкапсулирован (читай — не закрыт).

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

Во-первых, смею заверить вас, что любой более-менее солидный компилятор любой ваш геттер/сеттер непременно сделает inline-методом, то есть код val = 3 и setVal(3) превраитися в один и тот же бинарный код. Так что по поводу производительности можете быть спокойны. В C++ — точно, в C# и Java — скорее всего.

Во-вторых, в C# существует элегантнейшая вещь, называемая "свойствами", которая позволяет сделать так, чтобы вызов getter-а выглядел просто как обращение к переменной (равно как и вызов setter-а).

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

class Point
{
    private double x, y;
    public Point(double x, double y)
    {
        this.x = x; this.y = y;
    }
    public double X
    {
        get { return x; }
    }
    public double Y
    {
        get { return y; }
    }
}


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

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

классических практик разработки general purpose

Я не считаю, что есть такое понятие, как практики general purpose. Есть большие программы и маленькие. Маленькие можно писать как попало и на чем угодно — вы легко сможете их и проверить, и отладить. А вот большие надо писать очень аккуратно и вдумываться прежде всего в их организацию. А то вызовете на белый свет Летающего Макаронного Монстра.  ;)
Есть библиотеки, к примеру ILNumerics, которые могут существенно увеличить скорость алгоритмов, написанных на C#, за счёт оптимизаций управления памятью. К примеру, при сравнительно больших наборах данных, скорость может приближаться к реализации на FORTRAN. ilnumerics.net/blog/fast-faster-performance-comparison-c-ilnumerics-fortran-matlab-and-numpy-part-ii/
Да. А еще можно самый внутренний цикл счетного ядра, который отрабатывает за пару секунд, обложить юнит-тестами и переписать на C. А код этот дёрнуть через P/Invoke. И таким образом получить производительность, отличающуюся от нативной на проценты.

Разумеется, так можно сделать не всегда, но во многих случаях.
Я считаю, что надо создать высокопроизводительную базу (например, на C/C++) — качественные библиотеки символьных вычислений, работы с массивами, сортировки, и т.д., а чтобы потом «прикладные программисты» вызывали их из чего-то более лёгкого и высокоуровнего (Python?)

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

И тогда выпускник такой школы не будет опускать ручки: "(Word/3dMax/AutoCAD) это не умеет, значит это невозможно", а будет брать инициативу в свои руки, создавать скрипты, писать плагины и т.д. (а для этого надо создать вышеупомянутые библиотеки для всего спектра задач, решаемых с помощью компьютера: от офисных редакторов до физического моделирования, от обработки видео и 3d-моделлинга до систем распознавания/синтеза речи). Разумеется это должно быть всё open source. Вот так я вижу идеальное будущее образования в обществе, которое уже немыслимо без компьютера в каждой авторучке.
Все уже придумано до вас.

1. Boost — набор довольно таки высококачественных библиотек широкого спектра действия :) Часть кода которого идет дальше в стандарты. Почитайте про boost tr1.
2. Есть достаточно инструментов связывания таких С++ библиотек, на вскидку SWIG. Не говоря уже о существующем Boost.Python
3. Буст с каждой версией расширяется и модернизируется, добавляются новые библиотеки, новые алгоритмы работы с различными данными.

Про образование согласен.
Я имел в виду более высокий уровень, чем boost (это уже во второй части моего комментария). Это скорее следует назвать API.

P.S. А для чистого С такие штуки знаете?
Я считаю, что надо создать высокопроизводительную базу (например, на C/C++) — качественные библиотеки символьных вычислений, работы с массивами, сортировки, и т.д., а чтобы потом «прикладные программисты» вызывали их из чего-то более лёгкого и высокоуровнего (Python?)


Именно так мы и делали. Хардкод на Fortran + симпатичный простой интерфейс на python.
Удивляюсь, как за столько лет существования программирования никто не собрался и не создал какой-нибудь глобальный консорциум, который бы занимался созданием глобального API на все случаи жизни.

Описывал бы интерфейсы этих API, а потом бы принимал реализации, обложенные тестами со всех сторон, которые бы отличались лишь временем работы.

Идеально чтобы это всё было формально верифицируемо.
Этой идее сто лет в обед. Проблема в том, что у разных задач разные требования.
Кто-то готов пожертвовать точностью, кто-то скоростью.
А так — миллионы строк на FORTRAN, mathlab, python (numpy) давно написаны и ими пользуются. Никто метод Гаусса или решение каких других уравнений скорее всего не будет писать, а если будет, значит требования особые.
Начало статьи очень интересное, плоть до того места, как мы переключаемся на PVS Studio.
Я полагаю, что это называется «от слов — к делу».
Пару лет назад имел счастье приобщиться к этому комплексу программ в одном Московском НИИ. В основном работал с TPP и X!Tandem.
На самом деле спектр проблем даже шире, чем описан в статье и начинается он не с программ, а со стандартов. Как и в любой области, учёным довольно быстро пришлось придумать какой-либо стандарт на файлы, которыми будут обмениваться программы (например унифицированный формат результата эксперимента или масс-спектр). А так как им очень хотелось сохранить гибкость и большое разнообразие информации, которую каждый производитель аппаратов для экспериментов писал свою, то стали появляться такие шедевры как полуторагиговый XML в котором в BASE64 зашифрован массив структурок из 2х double'ов и тегами модель аппарата и его настройки. Унификации в итоге не получилось. Большинство программ падали в корку если на вход поступал файл от программы не «своего» производителя (pipline в названии продукта не с проста). Помнится я писал специальную программу-конвертр, которая конвертировала файл (удаляла лишние переносы строк!) чтобы программа из другого комплекса не падала.
Как с этим жили? — На основные эксперименты довольно быстро появлялись коммерческие центры с платными закрытыми продуктами хорошего качества. SAAS, техподдержка и все дела.
Также большие базы данных экспериментов, где все учёные делились исходными данными и выводами программ. В итоге усреднением результатов расчётов нескольких комплексов (и для этого начали писать софт) получалась какая-то истина.
Благо, научиться как-то программировать проще, чем разобраться в органической химии и принципах создания лекарств.
ИМХО, не проще, сравнивать вообще некорректно. Просто в случае с медициной часто ответственность больше, поэтому туда кто попало не лезет. Но и в программировании есть области куда просто так не лезут. И даже не из-за сложности. В авионике, например, программы не супер сложные, однако требования к надежности и ответственность куда выше.
Тут сразу много причин и следствий в одном клубке. Попробуем разобраться.

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

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

Физики используют С++ — вот это проблема. Но проблема-то надуманная. Заберите С++, верните Фортран — профит! Или не Фортран, а Питон, Лисп, R на худой конец. Маткад опять же.

Программисты используют С++ — это да, беда. Но беда иллюзорная. На самом деле ведь программисты не используют С++. В лучшем случае — безопасное подмножество (MISRA, HICPP), в худшем случае — опасное подмножество (Си с этим, как его, клястером). Иногда мне кажется, что С++ целиком использует в целом мире один Александреску, поэтому у него такой задумчиво-печалный вид на каждой конференции.

Программисты вроде как используют С++, но С++ против такого использования. Вот это действительно проблема, и ее можно решить. Статический анализ помогает. Кроме шуток, это очень полезная, хотя и недооцененная часть рабочего процесса. На самом деле, не обязательно даже покупать PVS, чтобы приобщиться к хорошему, достаточно сказать компилятору, к примеру, "-Wall -Wextra -pedantic -Weffc++" и перестать смотреть на него, как на телевизор. Все, что говорит компилятор, надо читать осмысленно — это наш первый и главнейший союзник в борьбе со злом.

Потом можно попробовать и другие анализаторы, почему нет. Анализ делает за меня самую скучную и нервную работу, делает ее быстро, надежно и не просится в отпуск. Как можно не любить статический анализ? Но одного анализа недостаточно. Надо еще учиться писать код, да. Учиться надо много, упорно и постоянно. Пользуясь случаем, хочу напомнить, что новый стандарт С++11 сказочно хорош, и все мы там будем, так что кто еще не ознакомился — самое время.

Еще надо уважать общепринятые стандарты программирования. Или хотя бы принять свой собственный стандарт и уважать его лично. Причем, не просто скобки / табы / с большой буквы, а нормальный такой стандарт уровня JSF AV C++.

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


Это — правда. Проблема лишь в том, что уровень компьютерной грамотности человека, пишущего «в один файл и на Фортране стандарта F77» действительно соответствует уровню охотника, который при наличии в городском арсенале ружей идёт в лес с дубиной. Много такой зайцев наловит?

Это — сложная проблема. И начинать, мне кажется, надо с образования. Высшие (и даже средние) школы должны учить людей компьютерной грамотности не только для взгляда «с этой стороны монитора», но также и «с той».
Если лезть в образование, то там клубок причин еще больший. Еще более пугающий. Легко сказать, «средняя школа должна». А кто пойдет в среднюю школу учить грамотности? Вот даже если мы с вами сейчас соберемся и пойдем в школу вместо того, чтобы клавиатуры чесать, в России примерно пятьдесят тысяч школ, — мы до пятницы точно не управимся, а на субботу у меня планы.

В высшем образовании чуть проще. Я даже поработал несколько лет на четверть ставки, — вполне себе годное хобби, пока основная работа позволяет. Но если уйти в академию с головой, придется забыть о карьере. А это дважды нехорошо: во-первых, зарплаты преподавателя не хватает на шлюх и кокаин, во-вторых, без связи с индустрией придется постепенно превратиться в физика и начать писать на Фортране.
Финансовых вопросов я в своих рассуждениях не касаюсь, так как неграмотен. Скажу только, что если государство хочет науку, оно должно хорошо вложиться в образование. Университет — это не базар. Он не может кормить сам себя. В самых капиталистических странах, где государство даже соц обеспечением не занимается (всё на страховках), насколько мне известно, образование всегда дотируется.

Вопрос лишь в том, куда эти деньги вкладывать. Я считаю, что людей надо учить концепциям программирования (типа отличий ФП от ООП и подобным) также, как сейчас их учат алгебре и Евклидовой геометрии. Это уже стало наукой, причем эта наука вполне усвоябельна при желании этак классе в 9-10 (сам тогда начинал это всё изучать понемногу).

И тогда если в своей карьере человек столкнётся с тем, что ему надо писать какие-то команды, он уже не будет «охотником с дубиной».
Не страшно, если из-за такой ошибки в игре у вас станет меньше жизней после взрыва, чем планировалось. А что означают неправильные данные при химических расчетах?

Ну, возможно, из-за них у вас тоже станет меньше жизней после взрыва.
Справедливости ради, скалярное произведение (SpectraSTPeakList::calcDot), где '&&' был перепутан с ',' — всегда или работает правильно, или порождает мусор и/или стрельбу по памяти.
Сама задача предполагает, что оба вектора имеют одинаковую размерность, поэтому что с запятой, что с конъюнкцией на правильных данных получится правильный результат.
А на неправильных… ну, в любом случае неправильные данные ведут к неопределённому поведению. Так какая разница? :)
Исправление должно выглядеть так:
assert(this->bins.size() == other->bins.size());
for(
i = this->bins.begin(), j = other->bins.begin();
i != this->bins.end();
++i, ++j
)
Как физик использующий калькулятор компьютер могу сказать, что не всё так страшно. Во-первых, большинство знакомых физиков программирует на довольно высоком уровне. И не только на Fortran, да. Во-вторых, любой результат подвергается куче проверок и перепроверок. В-третьих, если есть баги (а они всегда есть) то в большинстве случаев ошибка очевидна. Например, есть параметр который для кристалла равен 0, для газа 5, и если внезапно для жидкости он будет равен 100500, то это очевидно не гениальное открытие, а косяк в коде. В-четвертых, большинство вычислений дублируются (иногда полностью, иногда с немного измененными параметрами) коллегами из других институтов, и если что-то не так, это довольно быстро станет заметно. Ну и в-пятых, заверю вас, что между подсчетом того как какой-нибудь пептид влияет на почки и выпуском на рынок таблеток с ним, есть довольно большой промежуток, как во времени, так и в дополнительных проверках.
Вы не упомянули важный фактор — время. Физик может изучить Lisp, узнать, что такое виртуальный деструктор и научиться делать rebase в git. Ничего принципиально сложного в этом нет, это не квантовая механика, просто нужно время. Примерно лет десять, как в любой другой области. Те же десять лет нужны для того, чтобы физику изучить. Но лишних десяти лет ни у кого нет.

Отсюда и кривые программы, использующиеся для расчётов. Цена ошибок в таком одноразовом коде ниже, чем затраты на исправление ошибок. Утекает память? Ну и что, когда программа закончилась, операционная система её всё равно освободит. Много однотипного кода? Это вообще не ошибка. Неинициализированная переменная? Если на результат это не влияет, кого это волнует? С таким же успехом можно критиковать физиков за плохой почерк.

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

При необходимости можно отдать кривую одноразовую программу расчёта, которую физик написал, как умел, на Фортране, настоящему программисту и он сделает аналог на современном языке, который не стыдно будет продавать и поддерживать.
Анекдот вспомнился.
2100-й год, генетический программист разбирает цепочку ДНК, и натыкается на комментарий:
A5E2C1… // не забыть выпилить отсюда этот кусок кода нахрен (Архангел Михаил)
Если я правильно понял, одно из опасений автора — то, что серьезный физически/медицинский/химический [...] инструментарий пишут специально (не)обученные физики/медики/химики.

Есть у меня подозрение, что, например, систему моделирования белков пишут не врачи, подучившие плюсы по третьему изданию Страуструпа, а специально обученные разработчики — которые могут вообще не иметь медицинского образования, зато умеют читать грамотно составленное тем же медиком ФС, в котором нет медицинской теории и предположений, зато есть четкие алгоритмы бизнес-уровня и формулы, расчет которых нужно реализовать программно.
Основная рассчетная часть @folding взята из GROMACS, который таки написали обычные физики.
Если я правильно понял, одно из опасений автора — то, что серьезный физически/медицинский/химический [...] инструментарий пишут специально (не)обученные физики/медики/химики.

Есть у меня подозрение, что, например, систему моделирования белков пишут не врачи, подучившие плюсы по третьему изданию Страуструпа, а специально обученные разработчики — которые могут вообще не иметь медицинского образования, зато умеют читать грамотно составленное тем же медиком ФС, в котором нет медицинской теории и предположений, зато есть четкие алгоритмы бизнес-уровня и формулы, расчет которых нужно реализовать программно.
Гениально! Редкий случай, когда я читал на одном дыхании и думал, вот это да, действительно круто написано, чтобы на это сказали ребята из PVS-Studio. И на тебе, и это реклама, только с длииинным-длинным приквелом.
Растете!
Теперь я буду бояться всяких реакторов и коллайдеров :)
Он всю жизнь программировал на Фортране. Начинал еще с перфокарт. Я не виню его за то, что не учит C++… Никакого ООП в проекте под миллион строк кода, никакого статического анализа.  В том то и дело, что фортран превосходит С/C++  в области научных программ — нормальный компилятор фортрана сам массивы нолями инициализирует и не придется как в Си следить за указателями и совместимостью типов. Сам по себе фортран в научных вычислениях (из-за своей архитектуры) позволяет делать меньше ошибок. А ООП есть и в нем, если все таки оно действительно нужно в проекте.

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

А ошибки можно и в  Excel  сделать, вспомним известную статью по экономике. Все по итогу упирается в мотивацию.
В вашем комментарии вижу домыслы и странную логику.
нормальный компилятор фортрана сам массивы нолями инициализирует

Укажите, пожалуйста, какой компилятор вы называете «нормальным»? Даже лёгкое гугление позволяет найти вот это: software.intel.com/en-us/forums/topic/367699, где особое внимание предлагаю обратить на фразу
Arrays as well as scalar variables, whether allocated on the heap or the stack, have to be initialized before they are used.

В компиляторе gcc, который мне симпатичнее по многим причинам, чем ifort, есть опция -finit-local-zero, которая инициализирует локальные переменные в функции нулями. Но ее наличие еще надо знать, ее надо включить, а кроме того она, как уже было указано, действует не на все, а только на локальные переменные. В любом случае, такая нетривиальная логика при решении настолько простого вопроса наводит на размышления. И подобные ситуации в Фортране случаются сплошь и рядом.

Сам по себе фортран в научных вычислениях (из-за своей архитектуры) позволяет делать меньше ошибок.

Ничем не аргументированный миф, поддерживаемый и лелеемый большим числом традиционалистов. Возьму на себя наглость побыть Доном Кихотом и попытаться его развеять.

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

1. Каким способом в Фортране прочитать из файла строковую константу, оканчивающуюся тремя знаками пробела и не потерять их в конце (я искренне не смог найти способов работы с null terminated strings, возможно я плохо искал)
2. Каким кроссплатформенным и кросскомпиляторным способом в языке, заметим, предназначенном для платформо-независимого математического программирования (то есть обязанном иметь универсальную стандартную библиотеку) создать директорию?

Оба примера показывают, что таки да, в ряде случаев разработчику математического ПО на Фортране приходится решать совсем не математические проблемы. В отличие от C++, где всё это аккуратно решено за него. Но это — далеко не главные проблемы Фортрана. Дальше — больше;

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


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

Рассмотрим, к примеру, хорошее решение поставленной проблемы с обнулением переменных. Прекрасно эта проблема решена в языках Java и C#. Там компилятор члены классов обнуляет автоматом, а локальную переменную разработчик обязан инициализировать сам. Это снимает проблему. Хочешь ноль? Пиши int i = 0;. Написал int i; и затем прочел из него значение — получаешь ошибку компиляции. При таком подходе проблем не будет никогда. Другой пример — не менее важный — отлов исключений в Java. Если функция кидает исключение, являющееся результатом нештатной ситуации — разработчик обязан либо поймать его, либо явно указать, что прокидывает его дальше. Да-да, я о том самом «throws». Не хочешь лишний раз думать и писать «лишний» код — иди, пиши скрипты. Большая программа — не игрушка.

Я не знаю, как проблема инициализации переменных решена в питоне. Возможно, там тоже использование неинициализированной переменной — ошибка, хотя сильно в этом сомневаюсь, так как питон проектировался из расчета на лаконичность кода. И я даже готов смириться со стандартным поведением Фортрана, при котором переменные с именем «irrational» и «norm» имеют тип INTEGER, а переменная с именем «string1» — тип REAL, причем компилятор ни сном ни духом не даст понять, что вы забыли их объявить, если не напишите специально implicit none. Но тот факт, что переменные в функцию по умолчанию передаются по ссылке и могут в ней быть изменены, если явно возле каждой не писать intent(in) означает, что использовать этот язык для программирования крупных проектов — недальновидно. Вы будете искать ошибку в функции foo, а она будет в функции bar, которая «нечаянно» изменила переданную ей в параметре переменную. Это поведение языка было осмысленно, когда при программировании считали каждый такт и байт. Сейчас оно — преступно.

Эти примеры (кстати, в современном Фортране вообще есть exceptions?) ясно показывают, что человек, в равной степени хорошо владеющий Фортраном и, скажем, C# при наличии смертельной ответственности за качество того, что он кодирует, выберет C#. Даже если писать в нем без использования ООП. Просто из-за прозрачности поведения компилятора и стандартов языка.

Разумеется, и у Фортрана есть свои достоинства. К примеру, то, что на нем пишет половина физмат-сообщества и уже написала на нем кучу вспомогательного математического кода, который зачастую поможет вам решить проблемы. Есть хорошие математические библиотеки и т. д… Иными словами, Фортран популярен. Но давайте, положа руку на сердце, подумаем — а такое ли уж это достоинство? Мне приходит на ум аналогичный пример очень популярной операционной системы, созданной группой программистов из города Сиэттла, которая доминирует из-за того, что под нее написано больше всего пользовательских приложений. Вы уверены, что она действительно самая лучшая и удобная?..

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


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

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

Поэтому чем меньше язык дает свободы разработчику среднего уровня (не знающему язык досконально) — тем больше шансов, что ограничения языка уберегут разработчика от проблем. Пример: в Java строки надо проверять так — s2.equals(s1). А в C# и C++ — так: s2 == s1. Для профессионала это уже не проблема (хотя не знаю ни одного джависта, которого бы эта «особенность» не бесила), а вот разработчик более слабый нет-нет да и споткнётся об это. Потому что в Java выражение s2 == s1 успешно компилируется, но неверно работает. Вот это — и есть главная беда в данном случае.

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

Строки — больное место везде. В Джаве они еще реализованы более-менее удачно. Оператор == проверяет ссылки, равно как и для любого другого объекта любого класса, а для проверки содержимого строк есть специальный метод. Можно один раз запомнить и потом не спотыкаться. Похоже сделано и в Objective C, не помню, чтобы у кого-то были с этим серьезные проблемы.

В шарпе такой же Equals, но оператор == переопределен. Как по мне, это костыль. В итоге нормальный ссылочный тип ведет себя как значение и ломает мозг программистам. Я уверен, если сейчас опросить у тысячи шарпистов, является ли строка значимым типом, половина ответит «да».

В плюсах строки — это вообще все и ничто одновременно. Десяток разных реализаций я точно видел. Далеко не все перегружают оператор ==, но стандартные, например, таки да. Но это, опять же, порождает класс проблем. Потому что null-terminated строчки со стандартной библиотекой Си никто тоже не отменял, а головы у программистов не сменные. Постоянно кто-то пытается складывать одно с другим в неправильном порядке, прибавлять чар к литералу или гонять строчки туда-сюда через c_str там, где это вовсе не нужно. К вопросу о строгости, компилятор это все жует не отрыгивая. Спасает только CppCheck.

Питон такие проблемы обходит просто. Он их не порождает. Я не могу иметь неинициализированную переменную, потому что не могу декларировать переменную без инициализации. Строки — отдельный примитив языка, не объект как в Джаве и не список, как в Эрланге, поэтому они вполне могут сравниваться по ==. Переполнить массив невозможно, потому что вместо массивов списки. Сломать счетчик в цикле — потому что цикл проходит по неизменяемому ленивому ренджу. И так далее, и тому подобное.
а головы у программистов не сменные

Эх, а как бы хорошо было иногда… А если серьёзно, то вы очень здорово сформулировали проблему обратной совместимости между C++ и C. Я бы сказал еще грубее: главная проблема этой совместимости в том, что она есть, а парадигмы — разные.

К остальному, что вы сказали, мне добавить почти нечего. Спасибо за интересные факты. Уточню лишь, что под строками в C++ я имел в виду std::string, который находится в стандартной библиотеке и, по факту, является частью языка.

Но одна вещь в вашем рассуждении показалась мне всё же непоследовательной:

Строки — больное место везде.

Вот тут полностью согласен, но кое-что добавлю: строки — проверка объектно-ориентированного языка «на вшивость», то есть проверка того, насколько в нём легко (и можно ли вообще) создавать производительные, удобные объекты, с которыми бы было легко и приятно работать. Из перечисленных языков проверку целиком выдержал лишь C++. Там строка реализована средствами языка. ее можно присваивать, строки можно соединять естественным способом (переопределен +), их можно передавать как по ссылке, так и по значению (копировать). Всё удобно, всё на месте. И работает достаточно быстро. В Java нет переопределения операторов, а значит удобной инкапсуляции тоже нет. Разработчики, отказавшись от переопределения операторов «из-за нетривиальности» должны бы были пойти дальше и сделать s2.concat(s1) вместо s2 += s1, но, понимая, что это будет чудовищно неудобно, они слицемерили и переопределили в языке ровно один оператор для ровно одного класса — "+" для String. А переопределить == забыли или не смогли. Сравнение строк по указателю означает равенство их по значению, но только обратное утверждение неверно. И это надо было встроить в ==, чтобы не было проблем.

В C# объекты-ссылки действительно обычно сравниваются по указателю. string не был сделан объектом-значением из соображений производительности и экономии. И поэтому было принято решение «сломать мозг» тем, кто очень сильно хочет влезть в детали языка, а не тем, кто просто хочет сравнить две строки. В отличие от Java. Так что C# гордо займет второе место. А Питон просто дисквалифицировал себя из соревнования.

Строки — отдельный примитив языка, не объект как в Джаве и не список, как в Эрланге, поэтому они вполне могут сравниваться по ==.

Вот это — как раз и означает лютый костыль, по сравнению с которым тот, что в Java и тот, что в C# — сущие пустяки. Возможно, я неправ, но самый красивый и честный подход — в C++. А почему никто не считает, что stdc++ — стандартная библиотека, которую должно считать частью языка, для меня загадка. Возможно, виноват Герберт Шилдт, не уделивший ей должного внимания в своей суперпопулярной книге…
И вообще я действительно жалею, что программисты рекомендуют ученым переходить с фортрана на плюсы, хотя выгодней бы изучить питон, который также как и фортран хорош для научных вычислений.


Вот вам написали длинный ответ, а на практике всё намного проще. Нашей группе было всё равно на чем писать, лишь бы не на бреинфаке, и вычисления были быстрыми. К сожалению, на чистом питоне в среднем всё считалось раз в 200-300 медленнее. И всё. Не имеет никакого значения объявление переменных, заточенность под ООП и прочее.
Просто не умеете его готовить (это про питон).
1. Какой-то неумеха продолжает писать неправильные циклы

Судя по комментариям в файле, а также по истории коммитов репозитория, этот неумеха — Генли Лам:
www.linkedin.com/pub/henry-lam/5/448/848

http://ihome.ust.hk/~kehlam/
image

Henry Lam
Insitute for Systems Biology
1441 North 34th St.
Seattle, WA 98103 USA
hlam@systemsbiology.org
(орфография сохранена)

Файл с найденными дефектами он написал ещё в июне 2006 года, но до сих пор его поддерживает: есть свежий коммит — от 15 июня 2013 года.

Оказывается, даже выпускники Массачусетского технологического могу писать кривой код.
Отучился в США: MIT, Стенфорд, а потом вернулся в родной Гонконг на должность ассистент-профессора в гонконгский университет науки и технологии.
Sign up to leave a comment.