Привет, Хабр! Представляю вашему вниманию перевод статьи "Advice for programming students".

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

Решите, что вам нужно


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

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

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

Математика


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

Новые технологии постоянно появляются. Многие из них основаны на существующих математических моделях. Если вы хорошо знаете базовую математику, вы получаете очень приятные преимущества:

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

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

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

Учитесь на лучшем, используйте лучшие инструменты


Выберите свой первый язык. Он должен быть хорошо спроектированным, то есть иметь:

  • Согласованность.
  • Малое ядро.
  • Отсутствие лишней сложности (например, при изучении «сложного» языка, есть вещи, о которых вы должны просто знать или постоянно помнить, они не приносят ничего полезного для обучения).
  • Малую вероятность «выстрелить себе в ногу».
  • Высокоуровневость, потому что программирование — это решение задач и проблем, а не мастерство в каком-то языке. Знать все маленькие особенности вашего любимого языка еще не значит быть совершенным в программировании.

Я советую выбрать один из следующих языков:

  • Scheme (есть отличный классический вводный курс «Structure and Interpretation of Computer Programs»).
  • Smalltalk
  • Eiffel
  • ML

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

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

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

Например, представьте, что вы изучаете новый язык Go. Погуглите «Go language sucks» и почитайте почему люди критикуют его. Некоторые комментарии будут незначительными, но другие из них действительно будут иметь смысл. Вероятно, вы получите новые знания от чтения критических замечаний, оценивая их, чтобы потом определить имеют ли они значение, или это просто пустые слова.

Думайте сами


Я преподаю программирование (C и ассемблер) с 2009 студентам университета ИТМО в Санкт-Петербурге. У многих людей есть проблемы с программированием и никогда им не удается научиться этому из-за того, что они не создают код. Когда они получают задание, они пытаются имитировать существующее решение, возможно, взяв некоторые фрагменты из Stack Overflow, настроив их по своему вкусу. Хорошо, получили решение, что еще нужно?

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

Программировать значит делать сознательный выбор. Вы находитесь в состоянии А (у вас есть доступ к ряду языковых функций / библиотек, и вы знаете как их комбинировать); вы хотите получить состояние В (языковые конструкции объединены для решения задачи). Как вы построите маршрут от А до В? Теперь это реальное программирование, решение проблем.

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

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

Расширяйте свой кругозор


Программируйте каждый день, делайте сторонние проекты все время. Это очень простой (и в основном точный) способ для меня как учителя понять, что мой ученик с большой вероятностью добьется успеха. Один вопрос: что вы программируете в свободное время?

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

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

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

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

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

Программирование намного больше, чем общеизвестные C / Python / Java / C++ / C# / Go / Javascript, построенные на одинаковых принципах: императивный, структурный, немного с ООП и синтаксическим сахаром для имитации других стилей программирования. Мир программирования ОГРОМЕН. Как насчет:

  • Промышленные функциональные языки программирования с комплексными и продуманными типовыми системами (Haskell, Ocaml).
  • Функциональные языки с зависимыми типами, которые позволяют не только программировать, но и записывать доказательства (Coq, Agda, LEAN).
  • Конкатенативные языки (Forth).
  • Логическое программирование (Prolog, Refal).
  • Конечные автоматы (регулярные выражения, Promela).
  • Сильно расширяемые языки, позволяющие реализовывать практически любые синтаксические конструкции, как например Lisp, Forth, Camlp4/5, Rebol.
  • Предметно-ориентированные языки (JetBrains MPS, XText).

Каждую новую модель вычислений трудно понять, потому что это новый способ мышления. Но потраченные силы и время стоят того.

Будьте общительными


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

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

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

Пишите тесты


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

Я надеюсь, что это может помочь кому-то получить более полную картину, быстрее научиться и стать лучшим программистом; если у вас возникнут вопросы, я буду рад помочь. Удачи!

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


  1. maslyaev
    04.10.2018 18:03
    -1

    Вам понадобится логика, комбинаторика, теория множеств, все виды дискретной математики, теория графов, теория вычислимости, формальные грамматики, лямбда-исчисление, формальная семантика, топология, теории типов, теория чисел, группы, кольца, поля, категории.
    Где это больше пригождается — в бэкенде или фронтенде?


    1. DocJester
      04.10.2018 18:18
      +2

      А современное программирование ограничено веб-сервисами?


      1. arandomic
        04.10.2018 18:52

        Ну, если вы собрались разрабатывать LLVM backend/frontend… то весь список придется держать в активной памяти.


      1. maslyaev
        04.10.2018 20:40
        +1

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

        Во времена, когда компьютер был вычислительной машиной, он был про математику. Тогда, конечно, без теории чисел и формальных грамматик лучше было даже не соваться. Теперь компьютер является средством коммуникации между людьми, и поэтому на первое место выходит то, что называется soft skills. Какой смысл будет от того, что программа является шедевром с точки зрения теории типов, если разработчик напрочь лишён чуйки по части нужд пользователей, и поэтому программой всё равно никто не будет пользоваться?

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


        1. third112
          04.10.2018 21:52

          Вот у нас есть ООП. Инкапсуляция, наследование, полиморфизм. В чём математическая основа этой штуки? Теория множеств? Или группы? Или категории? Как базовые понятия (объект, класс, атрибут, метод) мэппятся на математику?

          Теория типов.


          1. maslyaev
            04.10.2018 23:26

            Есть доступное простым смертным описание этой штуки? Чтобы по-нашему, по рабоче-крестьянски?

            И что, кстати, эта теория говорит насчёт старого холивара про множественное наследование? Кошер оно или не кошер?


            1. third112
              05.10.2018 11:41

              Есть доступное простым смертным описание этой штуки?
              ИМХО в Википедии четко и доступно:

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

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

              Современная теория типов была частично разработана в процессе разрешения парадокса Рассела и во многом базируется на работе Бертрана Рассела и Альфреда Уайтхеда «Principia mathematica»[1].


              Как видим ноги растут из теории множеств (как и у др. теорий современной математики). Мне как программисту в первую очередь вспоминаются классические книги:
              • Дал У., Дейкстра Э., Хоор К., Структурное программирование. М.:«Мир», 1975.
              • Н.Вирт, К. Иенсен. Паскаль. Руководство для пользователя и описание языка. М.: Финансы и статистика, 1982 ;
              • Алгоритмы + структуры данных = программы. М.: Мир, 1985;

              С точки зрения этого подхода классы ООП естественным образом выглядят, как расширения паскалевских записей (type record) начиная с turbo-Pascal 5.5 и Think Pascal до Delphi 7. (Более поздние версии Дельфи могут больше, но ИМХО цена за это — частичная утрата первоначальной стройности).
              про множественное наследование

              ИМХО очень яркая вспышка холивара произошла в процессе принятия спецификации CORBA, т.к. у OMG был принцип достижения полного консенсуса среди участников, а участвовали лидеры IT индустрии. Если поднять выпуски OMG First Class Newsletter, можно отследить доводы сторонников и противников, вполне разумные ИМХО попытки примерить множественное наследование с теорией типов.

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


              1. maslyaev
                05.10.2018 14:13

                Спасибо за развёрнутый ответ.

                Ну Вы, наверно, и сами понимаете, что «какая-либо формальная система» — это не совсем то, что было бы достаточно. Хотелось бы что-нибудь похожее на то, как оно принято у реальных пацанов — аксиоматику, теоремы, леммы и т.п. История возникновения и прочая лирика, конечно, интересны, но не в них соль.

                Вообще, вопрос про математическую основу ООП далеко не праздный. В первую очередь, именно с концептуальными идейными недоработками я склонен связывать тот лавинообразный рост сложности (а как следствие, прожорливости, тормознутости и ненадёжности) программ. За последние 20 лет объём ОП вырос в тысячу (!!!) раз, скорострельность процессоров тоже как минимум на порядок, но по субъективным ощущениям, всё тормозит ещё сильнее. В некоторых областях (например, в отрисовке 3D-сцен) гигантский прогресс, но по части бытовой элементарщины типа формочек-кнопочек-менюшек громоздим фреймворк на фреймворк поверх ещё кучи фреймворков, и конца-краю этому не видно.

                Казалось бы, задача ORM (object-relational mapping) должна быть проще пареной репы, но оказывается, решения «в общем виде» вообще не существует. Реляционные дела у нас на строгой математической основе (исчисление предикатов), а объектные, по сути, являются набором шаманских практик. Прямое соответствие между математикой и шаманством протянуть без шансов.

                Возвращаемся к первоначальной теме. И вот смотрите, приходит в «цех» молодой боец, изучивший и понявший кучу разнообразных экзотических исчислений, и получает в зубы GoF (паттерны ОО-проектирования). Изучай, товарищ, многообразие и конструктивные особенности шаманских бубнов.


                1. third112
                  05.10.2018 15:41

                  ИМХО в первую очередь стоит упомянуть о принципиальной разнице между
                  сomputer science (CS) и математикой. Первая (как отметили Аллен Ньюэлл
                  и Герберт Саймон в своей лекции на вручении премии Тьюринга) экспериментальная наука, а вторая нет. Но математика и CS имеют области пересечения. Теория типов — одна из таких областей. Чистый мат. подход нужно искать у Рассела — см. в вики статью «парадокс Рассела». — Там не просто математика, а мат. логика, которую иногда противопоставляют обычной «недостаточно строгой» математике. Обратите внимание на секцию «Влияние на математику» — в числе прочего такое нехилое направление, как интуиционизм.

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

                  Но всякая монета имеет оборотную сторону. Как Вы справедливо отметили, платой за всевозможные фреймворки является тормознутость. Тут ИМХО многое зависит от общей проф.культуры программиста. Почти всегда можно найти золотую середину. Но не все умеют, а многие не хотят, а хотят спихнуть работу быстрее, чтобы хоть как-то работало.

                  BTW интересно, что многие популярные ЯП не требуют обязательного применения ООП. Интересно, что и многие алгоритмы (не только старые, но и новые) описывают на псевдокоде без ОО. Я зачастую делаю на ООП только GUI. Нпр., когда хочу проверить собственный алгоритм.


                  1. maslyaev
                    05.10.2018 17:04

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

                    Программирование — такая же деятельность, как и остальные. Ковыряясь в теле программы, мы не можем без выделения объектов. Если программа совсем простая, нам хватает мелкой нарезки (переменные, синтаксические конструкции), но при дальнейшем даже очень небольшом возрастании сложности возникает потребность оперировать более крупными строительными блоками. Хотя бы порезать это безобразие на процедуры и модули. И, да, структуры и классы.

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


                    1. third112
                      05.10.2018 18:24

                      Спасибо! Очень интересный получается разговор. Чтобы он был конкретнее, предложу в качестве примера собственный код. Там я поставил перед собой задачу показать различные способы представления графов, и ИМХО ООП для такой задачи очень подходит. А вот в послужившей отправной точкой программе игры "Из мухи слона" (МС) я не использовал ООП для выбранного представления графа (только для GUI). Как по-Вашему, это согласуется с принципами ООП типа SOLID? ;)

                      То есть это не самой реальности свойственно состоять из объектов, а нашему мышлению свойственно пребывать в полном недоумении до тех пор, пока мы не смогли с некоторой устраивающей нас степенью условности поделить единую реальность на объекты.
                      Делая программу МС, я не задумывался над выделением объектов «буква», «слово». Чаще просто определял по мере надобности локальные переменные. «Объект» Граф — это просто несколько массивов: один — двумерная матрица смежности с элементами Булева типа, где элемент (i,j) равен истине, если существует ребро между вершинами i и j, другой массив — вектор, где компонента i — слово (стандартная строка string) из словаря существительных русского языка, и т.д. Все операции осуществлял через простые процедуры и функции, но не методы ООП. ИМХО через ООП все то же самое выглядело бы академичнее, но код был бы большего размера, а выигрыша никакого. (Тем более, что не преследовал цели публиковать код).
                      Могут такие примеры спасти молодых бойцов от шаманских бубнов?


                      1. maslyaev
                        05.10.2018 20:11

                        Наворачивать иерархии служебных (инструментальных) классов — да на здоровьечко. То есть цепочка «TObject-TGraph-TDirectedGraph-...-TDirectedGraphWithBlackJackAndWhores» — совершенно нормально.
                        В моём правиле говорится о бизнес-сущностях. То есть тех, которые имеют какое-то отношение не только к внутренеей кухне, но и к грешному реальному миру.

                        Могут такие примеры спасти молодых бойцов от шаманских бубнов?
                        Молодых бойцов от шаманских бубнов, увы, не спасёт ничто :(

                        Когда-то давным-давно, лет 15 назад, у меня была фантазия о том, что очень не хватает возможности многократно типизировать объекты. То есть, например, объект Вася пусть будет типа «ТМужчина+ТСантехник+ТАлкаголик», объект Маня будет «ТЖенщина+ТУборщица+ТАлкаголик». С динамической доклассификацией/расклассификацией на лету. Вот в такой интерпретации мы бы получали очень неплохое идейное соответствие теории множеств. То есть классы у нас были бы множествами, а объекты — их элементами.


                        1. KvanTTT
                          06.10.2018 01:25

                          многократно типизировать объекты. То есть, например, объект Вася пусть будет типа «ТМужчина+ТСантехник+ТАлкаголик», объект Маня будет «ТЖенщина+ТУборщица+ТАлкаголик».

                          Интерфейсы?


                        1. third112
                          06.10.2018 02:57

                          Как только обстоятельства чуточку меняются (мы называем это уточнением постановки задачи) вполне вероятно, что тот способ декомпозиции реальности, который нам секунду назад казался незыблемой вечной истиной, летит ко всем чертям. Если та декомпозиция уже была воплощена в иерархию классов, начинаем всё перепиливать. Или, если на это нет бюджета, расставлять миллион костылей.
                          Увы, это общая проблема моделирования. Модель всегда минимизирует свойства прототипа, т.е. отбираются только значимые свойства. Нпр., модель самолета для испытаний в аэродинамической трубе может быть сделана из монолитного куска дерева и не иметь двигателя, иллюминаторов, шасси и т.д. Для каких-то других испытаний придется выбросить деревяшку и изготовить другую модель, отражающую другие свойства прототипа. Про методологию мат.моделирования очень интересные книги:
                          • Блехман И.И., Мышкис А.Д., Пановко Я.Г. Механика и прикладная математика. Логика и особенности приложений математики.
                          • Мышкис А. Д., Элементы теории математических моделей. Изд. 3-е, исправленное. М.: КомКнига, 2007

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

                          При исследовании различных гипотез может оказаться, что две модели одного прототипа противоречат друг-другу. Тогда единая иерархия классов будет невозможна. Т.о. ИМХО ООП мощный и полезный инструмент, но каждый инструмент не универсален и имеет границы применимости, нпр., отверткой не надо забивать гвозди, а молотком саморезы. Когда без ООП можно обойтись — лучше ИМХО обойтись, если это не усложнит программу. (Disclaimer. Как и ко всем общим рекомендациям, к этой надо отнестись с большой осторожностью!)


                1. 0xd34df00d
                  05.10.2018 21:36

                  Большая взрослая теория типов для ООП ну так себе нужна.

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

                  И вот мы выбираем, скажем, операционную семантику. Это такая штука, которая оперирует состоянием некоторой абстрактной машины, а состояние этой машины — текущий вычисляемый терм (например, if false then true else if true then false else 10 для соответствующего простейшего языка с if, булевыми константами и натуральными числами). Вернее, операционная семантика — это бинарное отношение на множестве состояний (она связывает предыдущее состояние со следующим).

                  Есть два вида операционной семантики — small-step и big-step. В big-step вы говорите, что результат вычисления выражения выше — false, сразу, в один шаг. В small-step вы делаете маленькие шажки и говорите, что первым шагом тот терм переходит в if true then false else 10, а следующим — в false.

                  Но проблема в том, что не все термы языка связаны с каким-то другим термом. if 10 then true else false ни во что не переходит, например (если вы, конечно, не добавите правила вычисления if'а для натуральных чисел, но это неиллюстративно). И возникает вопрос: как бы заранее, не выполняя программу, узнать, что она ерундовая?

                  Ну и приходит на помощь концепция типа. Теперь у нас есть не только бинарное отношение вычисления, но и тернарное (если язык чистый) или 4-арное (если язык мутабельный) отношение типизации.

                  И можно начать доказывать всякие полезные теоремки. Например, что STLC — типобезопасно. А типобезопасность — это что терм при вычислении не зависнет и либо сделает шаг вычисления, либо окажется некоторым финальным значением. И оказывается, что это полезное свойство в продакшене.

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

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

                  И потом оказывается, что ООП можно дешугарить в STLC с записями. ООП с наследованием — в STLC с записями с сабтайпингом. ООП с наследованием и открытой рекурсией (когда базовые методы могут дёргать виртуальные методы, переопределённые в наследнике) — в STLC с записями, сабтайпингом и оператором неподвижной точки. И для всех этих вариантов те теоремы выполняются.

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

                  А потом можно вспомнить, что есть более другие языки, с более другими системами типов, ML там всякие, хаскели. И оказывается, что в ряде случаем их система типов — это тоже STLC, просто типизирующее типы, а не термы.

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

                  А большая взрослая логика и теория типов нужны не в ООП, а, например, чтобы вы в упомянутых в посте Агде или Идрисе ненароком не попытались доказать утверждение типа ¬¬p > p.


                  1. third112
                    06.10.2018 03:17

                    Начинается всё с попытки вообще формализовать, что такое программа на языке программирования. Ну там, что значит её выполнение, например.
                    Именно программа? — что такое программа на языке программирования, а не что такое алгоритм?


                    1. 0xd34df00d
                      06.10.2018 03:30

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


                      1. third112
                        06.10.2018 03:37

                        Ага, спасибо. Именно про оттенки я и спросил. Нпр., доказывают корректность алгоритма (если доказывают, иначе называют «эвристическим» :), оценивают его теоретическую вычислительную сложность для наихудшего случая и т.д.


            1. 0xd34df00d
              05.10.2018 21:17
              +2

              Пирсовский Types and Programming Languages, думаю, вполне доступен простым смертным. Прочитать и понять первую где-то треть до сабтайпинга включительно можно, наверное, за месяц.

              И про множественное наследование там тоже есть.


              1. maslyaev
                05.10.2018 22:02

                Глянул. Судя по всему, интересная книжка. Почитаю на досуге. Спасибо.


        1. KvanTTT
          05.10.2018 01:42

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

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


          1. Zoolander
            05.10.2018 08:41

            это базовое понятие обычно и объясняется по месту в объяснялках по О нотации, так что знание логарифма тут так себе…


            1. KvanTTT
              05.10.2018 17:18

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


        1. nexmean
          05.10.2018 08:10

          Вот у нас есть ООП. Инкапсуляция, наследование, полиморфизм. В чём математическая основа этой штуки? Теория множеств? Или группы? Или категории? Как базовые понятия (объект, класс, атрибут, метод) мэппятся на математику? Вот реляционная алгебра, например — прямой потомок исчисления предикатов. А ООП — чей потомок?

          Это аргумент против ООП, не против математики.


    1. mkshma
      04.10.2018 20:15

      На фронтенде вам ничего не пригодится. Тыкайте себе кнопочки на здоровье. В среднем даже будет работать.


      1. theaklair
        04.10.2018 23:21

        Как минимум надо бы в типизацию уметь на фронтенде.


  1. Griboks
    04.10.2018 19:58

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


  1. third112
    04.10.2018 21:59

    Про математику нет единого мнения, см., нпр., этот опрос — вопрос: «Роль математики для информатики в школе высокая».

    ИМХО математика очерь нужна программисту, но в списке статьи топология — это непонятно, где топология в программировании, указана теория графов и там топология (не геометрия) — это Ok — нужно, но мат. дисциплина топология, где ее практически применить в кодах?

    PS Не указана теория сложности вычислений. М.б. я просмотрел, м.б. иначе названа?


  1. sfi0zy
    04.10.2018 22:25

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

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

    Возьмите хорошую книгу и решайте олимпиадные задачи онлайн.

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

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


  1. Germanjon
    05.10.2018 07:52

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


  1. Vlad_fox
    05.10.2018 10:45

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


  1. nick_gabpe
    05.10.2018 17:29

    Scheme, Smalltalk, Eiffel, ML… Я никогда не понимал зачем учить мёртвые языки.
    Лучше учить те языки с которыми можно идти в продакшн. Java, C#, C++, Python… При помощи одного из этих языков можно идти в реальный продакшн, писать, развиваться.

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


  1. Amomum
    05.10.2018 20:32
    +2

    Не холивара ради, а исключительно из любопытства — чем все-таки автору не угодил Python как первый язык?

    Мне всегда казалось, что самый первый язык должен быть простым, умеренно-лаконичным, не стрелять программисту в ноги и самое главное — чтобы на нем можно было сделать что-то клевое. На мой взгляд только так человек может заинтересоваться программированием.

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

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

    Еще крайне желательно, чтобы рабочая среда была дружелюбной и настраивалась легко и быстро.

    Python этим требованиям вроде бы вполне удовлетворяет. А вот как с этим у Scheme и Smalltalk — я вообще не в курсе, к сожалению.

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


    1. Amomum
      05.10.2018 20:35
      +1

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

      Подозреваю, что у предложенных вами языков с этим похуже.


  1. true-grue
    05.10.2018 21:19
    +1

    Автор статьи сразу же уточняет, что советы его имеют субъективный характер: «пост состоит из некоторых полезных советов, которые я хотел бы услышать, когда мне было 18 лет». Поэтому критиковать положения из статьи стоит умеренно. В конце концов, если вы не последуете этим советам, то не станете преподавателем компьютерных наук, а вашу книгу по низкоуровневому программированию не будут рекламировать на Amazon. Только и всего. К счастью в информатике довольно широких дорог и узких тропинок для всех. Но лично мне интересен опыт автора и его путь в программировании.

    Видно, что автор находится в стадии очарования функциональным и доказательным программированием. Ни вижу в этом ничего плохого. Но вот интересный момент: что предлагается выбрать в качестве первого языка. Scheme/Smalltalk — это языки компьютерных первопроходцев-экспериментаторов. Они олицетворяют тот подход в программировании, который позволяет эволюционно и итеративно разрабатывать программы. Эти языки не сковывают программиста правилами, а дают возможность уточнять задачу и алгоритмы прямо в процессе реализации. Совсем другое дело — Eiffel и ML. Замечательные языки, но нацелены они на совсем иной подход к разработке ПО. Предполагается, что в уме у нас уже есть формализованная модель задачи и мы описываем ее со всеми необходимыми ограничениями, которые не позволят получить некорректный результат. На мой взгляд, начинающему лучше иметь дело с языками Scheme/Smalltalk, которые не будут к нему и его не до конца оформленным идеям слишком строги. Другой вариант — какой-то язык с постепенной типизацией.

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

    Полностью разделяю призыв автора знакомиться с разными подходами к программированию, с разными языками. Тут можно привести известные слова А. Перлиса: «A language that doesn't affect the way you think about programming, is not worth knowing».

    Приятно, что упомянут и пункт по конструированию DSL — очень близкая мне тема. Вот только с выбором конструкторов не могу согласиться (JetBrains MPS, XText). Я бы предложил в первую очередь Stratego/XT.

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


    1. akryukov
      05.10.2018 22:06

      Для Питона, увы, нет эквивалента SICP.

      Почему вы так думаете?
      Вот по ссылке заявлена книга SICP in Python: https://wizardforcel.gitbooks.io/sicp-in-python/content/index.html
      Темы в ней, правда, немного переставлены. Странно было бы ждать полного эквивалента от книги на другом языке.


      1. true-grue
        05.10.2018 22:25

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

        Выбор именно Scheme для оригинального SICP являлся определяющим с точки зрения методики преподавания: это «пластилиновый» язык, голое синтаксическое дерево. С одной стороны, конкретный синтаксис не затеняет детали реализаций алгоритмов, а с другой — Scheme дает гибкость в исследовании самых разных стилей программирования.

        Повторюсь, учебника для Питона, который учит решать задачи в хорошем питоновском стиле я пока не встретил. В этом отношении мне понравился подход П. Норвига: norvig.com/python-lisp.html
        Обратите внимание на пример с генератором случайных фраз. Норвиг сначала приводит реализацию на Питоне такой, какой бы написал ее Лисп-программист. Затем он показывает более изящный вариант — более идиоматический, характерный для Питона.


  1. gatoazul
    05.10.2018 23:01
    +1

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

    Бедные современные студенты, с молодости попавшие под пяту необходимости.