Connect with us

Программирование

Я идиот: стратегия успешного идиотизма в разработке

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

Анна Гуляева

Опубликовано

/

     
     

Разработчик Ричард Тертон выступил на конференции RWDevCon и рассказал, почему нам всем нужно понять, что мы идиоты (подсказка – чтобы успешно работать вместе).

Привет. Меня зовут Рич и я идиот. Сегодня я хочу рассказать вам три вещи: что я идиот, что вы, возможно, идиот и как быть идиотом.

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

Шаг 1: Я идиот

Я слева

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

Все признаки идиота

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

Я постоянно путаюсь в самых базовых и простых вещах в жизни. Вот вам пример: у меня две маленьких дочери и у них есть по два ящика для одежды. Я работаю из дома, поэтому я занимаюсь стиркой, пока Xcode восстанавливается после сбоя или делает что-то ещё. Итак, после стирки я раскладываю вещи по двум ящикам. Один ящик – для верха, другой – для низа. Футболка – это верх. Леггинсы – это низ.

А платье? Платье – это верх или низ? Я не знаю. Наука не знает. Каждый раз я даю разный ответ на этот вопрос, поэтому мои дети каждый раз так долго переодеваются.

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

Этот пес знает больше, чем я

У меня нет образования программиста. Я был биохимиком, затем я был поваром, затем я снова стал биохимиком. Я пытался излечить рак. Это было сложно. Затем я работал над реестром костного мозга в банке крови и подумал: “Я вроде бы хочу быть программистом”. Но я не мог получить работу, потому что никогда не программировал. Единственной возможностью для меня было получить работу в компании, которая разработала собственный язык программирования – все кандидаты на должность не знали, как на нем писать.

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

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

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

Когда я работаю над кодом, я постоянно совершаю одни и те же ошибки. Например, операторы greater-than и less-than. Я постоянно их путаю, хотя знаю правило про голодного крокодила. Оно просто не появляется у меня в мозге в нужный момент. То же самое с минимумом и максимумом.

Сейчас я работаю с суперумными людьми в агентстве MartianCraft. Я не знаю, слышали ли вы о нем, но люди, основавшие MartianCraft, пишут книги о создании iOS-приложений. Вы легко можете представить, как иногда я чувствую, что мне там не место, ведь эти люди могут использовать операторы greater-than и less-than правильно с первого раза.

Но это нормально. Если вы думаете, что вы лучший человек в комнате, вы либо неправы, либо вы в неправильной комнате. Если я работаю или общаюсь на конференции/в Twitter/в Slack и думаю: “О, этот человек намного умнее и лучше меня” – это отлично! Это мой шанс узнать что-то новое.

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

Шаг 2: мы все идиоты

Надеюсь, я донес свою первую мысль. Теперь более сложная часть: мне нужно убедить вас, что вы идиот. Я сделаю это, показав вам некоторые цитаты от людей, которых я называю “высокоэффективными идиотами”. Я надеюсь, что некоторые цитаты заставят вас подумать: “Да, я был в такой ситуации”. И может быть, вы начнете думать, что и вы идиот.

У всех нас было так, что целый день вы пытаетесь что-то сделать, но оно не работает и не работает. Затем вы резко понимаете, что происходит, и чувствуете себя гением! Этот переход и это чувство… Это главная причина, по которой я люблю свою работу. Переход от состояния гения к состоянию идиота не так приятен; но я думаю, что однажды Уильям Шекспир сказал: “Жизнь – это американские горки, вы просто должны на ней ехать”.

Следующий твит принадлежит Алексису, который выступал до меня. “Никто на самом деле не знает, как кодить, мы все просто бродим, бесплодно молясь об освобождении”. Очень поэтично, не так ли? У вас, скорее всего, были дни, когда вы просто перебирали случайные вещи, чтобы решить проблему. Затем, внезапно, вы всё исправляете. Вы просто делаете это и движетесь дальше.

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

Отличная цитата. “Самый важный навык для программистов – чувствовать себя комфортно, не зная, что вы делаете”. Почти каждый раз, когда я что-то начинаю, я очень комфортно чувствую себя в этой ситуации.

Когда Swift только появился, я начинал новый проект на работе и подумал: “Я сделаю его на Swift! Какая отличная возможность.” Итак, я создаю новый проект, выбираю язык и появляется Swift. Но…как с ним работать? Я не знаю! Это нормально, так вы учитесь чему-то новому.

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

Готовы вступить в клуб?

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

Если вы все ещё не верите мне, вы, возможно, находитесь в фазе риска на этом графике.

Это график, следовательно, это наука. Давайте предположим, что я убедил вас, что вы идиоты. Теперь мы можем перейти к третьей части: как быть идиотом.

Шаг 3: как быть идиотом

Первый шаг к успеху – всегда помнить о том, что вы идиот. Не давайте своему идиотскому мозгу много задач. Не пытайтесь запомнить всё. Делайте записи. Используйте список задач. Используйте диспетчер сниппетов.

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

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

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

Пишите для идиотов

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

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

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

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

Я пишу для этого идиота

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

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

Джеймс Джойс не знал, как быть идиотом

Возможно, вы делаете всё неправильно

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

Как и в литературе, существует бесконечное число способов написать что-либо. Если способов бесконечно много, то с точки зрения статистики, вы выбрали неправильный. Если он не совсем ошибочный, тот он не идеален. Но это не так важно. Главное, что всё работает и ваш код легко можно изменить. Помните: он никогда не будет идеальным.

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

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

Не будьте умным

Есть и другой вопрос, который вы должны постоянно задавать себе: “Становлюсь ли я слишком умным?” У меня есть цитаты об этом:

Умный код нельзя исправить.

Умный код – это как съесть целый луковый цветок из Outback. Вы будете гордиться собой, но позже вы за это заплатите.

Умный код – это не добродетель. Прошлым летом я работал над образовательными материалами для людей, которые хотят изучать Swift с нулевым знанием о программировании. Было интересно вернуться к основам со всеми знаниями, которые я накопил в своей голове. Что такое переменная, что такое константа? Как сказать компьютеру, что нужно сделать? И Swift позволяет вам выразить эти идеи очень-очень просто.

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

Целые блоги заполнены такими вещами. Можете ли вы сказать, что делает этот код? Сможете ли вы сделать это снова через три месяца? Даже этот код в замешательстве – посмотрите на это лицо в середине.

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

Краткость – это не ясность. Пишите для чтения. Пишите для идиотов. Теперь перейдем к более позитивным вещам, которые делают идиоты: вы можете попросить о помощи.

Просите о помощи

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

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

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

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

Помогайте другим

Как идиоту успешно ответить на вопрос? Используйте свой идиотизм.

Задавайте дополнительные вопросы. “Что делает эта часть?” И так человек понимает, что в этой части и находится его проблема, и они чувствуют себя отлично, потому что её решили. А вы чувствуете себя отлично, потому что помогли им решить проблему, не зная ничего. Помните, как тяжело не знать ничего и просить о помощи. Не удивляйтесь, когда кто-то не знает того, что знаете вы. Вы это тоже когда-то не знали. Давайте простые, но обоснованные ответы.

Этот утенок научился плавать (и кодить), задавая вопросы отзывчивым идиотам на Stack Overflow

И, конечно, вы можете не знать ответ на вопрос. Это нормально. Вы можете провести небольшое исследование и попытаться найти ответ самостоятельно. Я узнал так много разных вещей на Stack Overflow таким образом! И это гораздо эффективнее, чем просто создание проекта, потому что проект обычно задействует меньше областей знания.

Будьте идиотом

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

  1. Общайтесь понятно
  2. Помогайте друг другу

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

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

 

Комментарии
Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Advertisement
5 комментариев

5 Comments

  1. Konstantin Konopko

    01.08.2017 at 18:27

    Статья отличная! Но уберите функцию Поделиться при выделении текста — я просто читаю выделяя текст, чтобы пометить где остановился.

You must be logged in to post a comment Login

Leave a Reply

Программирование

3 навыка лучшего инженера по программному обеспечению

Виктор Савкин является со-основателем nrwl.io, предоставляя консультации по Angular командам предприятий. Ранее он работал в команде Angular Core в Google, и сделал  модули инъекции зависимостей, отслеживания изменений, форм и роутеров.

AppTractor

Опубликовано

/

Автор:

Когда меня спрашивают «Как стать хорошим инженером-программистом?», я обычно рекомендую развивать следующие три направления:

  • Деление и упрощение.
  • Хорошие ментальные модели.
  • Инструменты.

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

Делите и упрощайте

Делите

Поскольку мы не можем удерживать более 5-7 объектов в рабочей памяти, любая нетривиальная проблема слишком велика, чтобы держать ее в голове. Мы можем либо абстрактно осмыслить проблему в целом, либо детально рассмотреть небольшую часть проблемы. Оба способа важны. Также важно знать уровень абстракции, на котором вы сейчас работаете. Либо мыслите абстрактно, используя большие метафоры и аппроксимации, или думайте точечно. Старайтесь не смешивать такие подходы.

Вот процесс, который я использую при разделении проблемы на подзадачи:

Шаг первый: удостоверьтесь, что вы понимаете проблему.

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

Шаг второй: нарисуйте диаграмму проблемной области.

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

Шаг третий: выберите подзадачу и используйте тот же процесс, чтобы разделить его дальше.

  • Остановитесь, когда проблемы (проблемный субдомен) станут малы и понятны.
  • Решите их индивидуально и объедините результаты.

Упрощайте

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

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

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

Используйте научный подход

Используйте научный подход, чтобы улучшить понимание проблемы. Он работает следующим образом:

  1. Запишите вопрос, на который вы пытаетесь ответить.
  2. Запишите гипотезу.
  3. Запишите прогноз, которое является результатом гипотезы.
  4. Проверьте прогноз и запишите результат.
  5. Повторяйте, пока не получите ответа на вопрос.

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

Запишите вопрос: почему для рендеринга сетки требуется 5 секунд?

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

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

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

Теперь, к следующему вопросу: почему обнаружение изменений выполняется сотни раз?

Шаги 1, 3, 4 этого процесса хорошо определены. Они выполняются почти механически. Шаг 2 – выдвижение гипотезы – это то, где происходит творческая работа. И здесь хорошие ментальные модели и интуиция очень помогают.

Все инженеры умеют программировать, но не все программисты могут быть инженерами: в чем отличие?

Развивайте хорошие ментальные модели

«Точка зрения дает нам 80 баллов IQ» Алан Кей

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

Разработка хороших ментальных моделей – одна из самых важных инвестиций, которую мы можем сделать в качестве инженеров. Например, посмотрите на этот список:

  • Язык программирования.
  • Программа.
  • Компилятор.
  • Система типов
  • Функциональное программирование, императивное, логическое программирование.
  • Виртуальная машина
  • Интерпретатор
  • Сборка мусора
  • База данных.
  • Распределенная система
  • Обмен сообщениями.

У вас есть хорошие ментальные модели для всех из них?

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

Ментальные модели, представленные выше, являются общими. Вот некоторые ментальные модели, ориентированные на frontend:

  • Bundling.
  • Treeshaking.
  • Change detection.
  • Observable objects.
  • Virtual DOM.
  • CQRS/event sourcing/Redux.

Разработка ментальных моделей

Как можно развить хорошие ментальные модели?

Читайте

Во-первых, много читайте. Читайте книги, читайте статьи.

Используйте «узкие» технологии

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

Создавайте их сами

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

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

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

“Должности ничего не значат”: чем отличается разработчик от инженера?

Изучите свои инструменты

Инженеры-программисты – профессионалы, которые полагаются на инструменты. Вот некоторые из инструментов, которые я использую каждый день:

  • Клавиатура.
  • Операционная система.
  • Оболочка.
  • Редакторы и IDE.
  • Менеджер пакетов (brew, npm, yarn, …).
  • Языки (typescript, css, …).
  • Инструменты разработчика (инструменты Chrome Dev, отладчик node…).
  • Фреймворки и инструменты (angular, rxjs, webpack, rollup, …).

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

Есть две причины хорошо изучить свои инструменты:

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

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

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

Я считаю, что следующее истинно:

Любой инженер, который хорошо знает свои инструменты – это хороший инженер. Человек, который не знает своих инструментов хорошо, вряд ли будет хорошим инженером.

Вы должны быть больше, чем просто хорошим инженером

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

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

Желаем вам удачи!

 

Комментарии
Продолжить чтение

Обучение

Бесплатное руководство “iOS-разработка: от начинающего до профессионала”

Эта бесплатная книга позволит вам начать разрабатывать приложения для iOS на языке Swift.

AppTractor

Опубликовано

/

Автор:

В ней не просто даются все основополагающие принципы программирования на Swift, но и основы дизайна, пользовательского опыта, микровзаимодействий, виральности, работы с платформенными функциями (встроенные покупки, Touch ID и т.п.).

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

Скачать руководство вы можете на официальном сайте.

 

Комментарии
Продолжить чтение

Программирование

Основы параллельного программирования в Swift: часть 2

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

AppTractor

Опубликовано

/

Автор:

Параметры для контроля конкурентности

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

Приоритетная инверсия (Priority Inversion)

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

Представьте себе наличие двух высокоприоритетных тредов (1 и 2) и тред с низким приоритетом (3). Если 3 блокирует ресурс, к которому 1 хочет получить доступ, 1 придется ждать. Поскольку 2 имеет более высокий приоритет, вся его работа будет выполнена в первую очередь. В случаях, когда процесс не заканчивается, тред 3 не будет выполнен, и, таким образом, поток 1 будет заблокирован до бесконечности.

Наследование приоритета (Priority Inheritance)

Решение для Priority Inversion – это наследование приоритета (Priority Inheritance). В этом случае тред 1 отдаст приоритет треду 3, если он заблокирован. Таким образом, тред 3 и 2 имеет высокий приоритет и оба выполняются (в зависимости от ОС). Как только 3 разблокирует ресурс, высокий приоритет возвращается к треду 1, и он будет продолжать свою первоначальную работу.

Atomic

Atomic содержит ту же идею, что и транзакция в контексте базы данных. Вы наверняка захотите написать значение сразу, как одну операцию. Приложения, скомпилированные для 32 бит, могут иметь довольно странное поведение при использовании int64_t и не иметь его в atomic. Почему? Давайте подробно рассмотрим, что происходит:

int64_t x = 0
Thread1:
x = 0xFFFF
Thread2:
x = 0xEEDD

Наличие неатомной операции может привести к тому, что первый поток начнет записывать в x. Но поскольку мы работаем в 32-разрядной операционной системой, мы должны разделить значение, которое мы записываем в x, на две очереди 0xFF.

Когда в то же время Thread2 попытается записать значение в x, может произойти планирование операций в следующем порядке:

Thread1: part1
Thread2: part1
Thread2: part2
Thread1: part2

В итоге мы получим:

x == 0xEEFF

который не равен ни 0xFFFF, ни 0xEEDD.

Используя atomic, мы создаем единую транзакцию, которая приведет к следующему поведению:

Thread1: part1
Thread1: part2
Thread2: part1
Thread2: part2

В результате x содержит значение, установленное Thread2. Сам Swift не работает с atomic. В Swift Evolution предлагается добавить его, но на данный момент вам придется реализовать его самостоятельно.

Lock

Lock – это простой способ предотвратить доступ нескольких тредов к ресурсу. Сначала тред проверяет, может ли он войти в защищенную часть или нет. Если он может войти, он блокирует защищенную часть и продолжает работу. Как только он выйдет, то разблокирует его. Если при входе тред встречает заблокированную часть, то он будет ждать. Обычно это делается при помощи сна и регулярного пробуждения, что позволяет проверить, заблокирован все еще ресурс, или нет.

В iOS это можно сделать с помощью NSLock. Но имейте в виду, что при разблокировке тред должен быть тем же самым, что и блокировал.

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

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

На уровне процессов существует также распределенная блокировка (distributed lock). Разница заключается в том, что в случае блокирования процесса он просто сообщает об этом процессу, и процесс может решить, как справиться с этой ситуацией.

Циклическая блокировка (Spinlock)

Блокировка состоит из нескольких операций, которые «усыпляют» треды, пока они снова не включатся. Это приводит к изменениям контекста для CPU (переключением регистров и так далее для сохранения состояния тредов). Эти изменения требуют большого времени вычислений. Если у вас действительно небольшие операции, которые вы хотите защитить, вы можете использовать спинлоки. Основная идея в том, потоки опрашивают блокировку в процессе ожидания. Для этого требуется больше ресурсов, чем просто в спящих тредах. В то же время они наблюдают за изменением контекста и, таким образом, быстрее работают при небольших операциях.

Это звучит неплохо в теории, но в iOS всегда все по другому. iOS имеет концепцию Quality of Service (QoS). С QoS может случиться так, что треды с низким приоритетом не будут выполняться вообще. Наличие спинлока на таком треде и более приоритетный тред, пытающийся получить доступ к его ресурсу, приведут к тому, что более приоритетный тред будет «голодать» по нижнего треда, не разблокируя требуемый ресурс и блокируя самого себя. Как результат, спинлоки являются незаконными на iOS.

Mutex

Mutex подобен замку. Разница в том, что это могут быть разные процессы, а не только треды. К сожалению, вам придется реализовать свой собственный Mutex, поскольку Swift его не поддерживает. Это можно сделать с помощью pthread_mutex от C.

Semaphore

Семафор – это структура данных, обеспечивающая взаимную эксклюзивность в синхронизации тредов. Он состоит из счетчика, очереди FIFO и методов wait() и signal().

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

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

Можно рассматривать двоичный семафор (семафор со значением счетчика 0 или 1) как Mutex. Но в то время как Mutex связан с механизмом блокировки, семафор является сигнальным механизмом. Это особо не помогает, так где же разница?

Механизм блокировки – это защита и управление доступом к ресурсу. Таким образом, он предотвращает одновременное обращение нескольких тредов к одному ресурсу. Сигнальная система больше напоминает вызов “Эй, я закончил! Продолжай!”. Например, если вы слушаете музыку на своем мобильном телефоне и вам звонят, общий ресурс (наушники) будет задействован на телефоне. Когда звонок закончится, система проинформирует ваш mp3-плеер при помощи сигнала для продолжения. Это тот случай, когда следует предпочесть семафор мьютексу.

Так в чем же фишка? Представьте, что у вас есть тред с низким приоритетом (1), который находится в защищенной области, и у вас есть тред с высоким приоритетом (2), который просто вызывает wait() на семафоре. 2 спит и ждет, когда семафор разбудит его. Теперь у нас есть тред (3), который имеет более высокий приоритет, чем 1. Этот тред в сочетании с QoS блокирует сигнал от 1 к семафору и, таким образом, голодают оба других потока. Таким образом, семафоры в iOS не имеют приоритетного наследования (Priority Inheritance).

Synchronized

В Objective-C существует также опция использования @synchronized. Это простой способ создания мьютекса. Поскольку у Swift его нет, мы должны копнуть глубже. Вы можете познакомиться с @synchronized, вызвав objc_sync_enter.

Поскольку я неоднократно видел этот вопрос в интернете, давайте ответим на него тоже. Насколько я знаю, это не конфиденциальный метод, поэтому его использование не исключает вас из App Store.

Concurrency Queues Dispatching

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

Недостатком является большое количество времени, поскольку нужно много перемещений и изменений контекста. Это не имеет значения, если ваше приложение не нуждается в высокой вычислительной мощности, но в случае, если у вас возникнут потери фреймов, вы можете рассмотреть другое решение (например, Mutex).

Dispatch Barriers

Если вы используете GCD, у вас есть больше возможностей для синхронизации вашего кода. Один из них – Dispatch Barriers. С их помощью мы можем создавать блоки защищенных частей, которые должны выполняться вместе. Мы также можем контролировать, в каком порядке выполняется асинхронный код. Это звучит странно, но представьте, что вам предстоит выполнить долгую задачу, которую можно разделить на части. Эти части необходимо запускать по порядку, но их можно снова разделить на более мелкие куски. Эти меньшие куски части могут выполняться асинхронно. Dispatch Barriers теперь можно использоваться для синхронизации больших частей, в то время как отдельные куски могут работать сами по себе.

Trampoline

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

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

Заключение

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

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

Комментарии
Продолжить чтение

Новости

Искусственный интеллект научили писать Java-код

Группа исследователей из университета Райса (США) развивает интеллектуальный ассистент разработчика Bayou, позволяющий частично автоматизировать процесс написания кода на языке Java. Проект использует алгоритмы глубинного машинного обучения и модель, натренированную на примерах рабочего Java-кода, представленного на GitHub. Наработки проекта открыты под лицензией Apache 2.0, код написан на Java и Python. Модель машинного обучения реализована при помощи платформы Tensorflow и инструментария scikit-learn.

AppTractor

Опубликовано

/

Автор:

Как описывает OpenNET, на основе задаваемых разработчиком меток c упоминанием методов API и типов данных, которые следует использовать в коде, Bayou позволяет синтезировать готовые программные блоки с реализацией шаблонов использования Java API, соответствующих контексту уже имеющегося кода. Иными словами, Bayou позволяет использовать методы машинного обучения для воплощения парадигмы разработки copy&paste, при которой разработчик находит и использует готовые куски кода, применяемые в других проектах.

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

Online-демонстрацию возможностей Bayou можно найти на данной странице. Например, при возникновении задачи написания кода для чтения из файла разработчик может добавить метку “{ /// call:readLine }”:


   import java.io.File;
   public class Test {
       void read(File file) {
           {
              /// call:readLine
           }
       }
   }

После обработки данной конструкции будет предложен готовый вариант кода:


   import java.io.BufferedReader;
   import java.io.File;
   import java.io.IOException;
   import java.io.FileNotFoundException;
   import java.io.FileReader;
   public class TestIO {
     void read(File file) {
       {
         FileReader fr1;
         BufferedReader br1;
         String s1;
         try {
           fr1 = new FileReader(file);
           br1 = new BufferedReader(fr1);
           s1 = br1.readLine();
         } catch (FileNotFoundException _e) {
         } catch (IOException _e) {
         }
         return;
       }
     }
   }

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

В текущем виде система требует задания достаточно точных меток, не поддерживает указание масок для типов и может использовать лишь ограниченный набор API (java.lang, java.io и java.util). В будущем разработчики намерены реализовать возможность формирования запросов на естественном языке и добавить функциональность интерактивной оболочки, позволяющей выбирать разные варианты кода и уточнять свои пожелания. В более отдалённой перспективе планируется обеспечить генерацию более сложного кода, включающего группы методов или классов.

Комментарии
Продолжить чтение

Реклама

Наша рассылка

Нажимая на кнопку "Подписаться" вы даете согласие на обработку персональных данных.

Вакансии

Популярное

X
X

Спасибо!

Теперь редакторы в курсе.