000
ОтложитьЧитал
Robert С. Martin
The Clean Coder:
A Code of Conduct for Professional Programmers
© Prentice Hall, Inc., 2011
© Перевод на русский язык, издание на русском языке ООО Издательство «Питер», 2012
Обязательное вступление
(Не пропускайте, оно вам понадобится!)
Почему вы выбрали эту книгу? Наверное, потому что вы – программист, и вас интересует понятие профессионализма. И правильно! Профессионализм – то, чего так отчаянно не хватает в нашей профессии.
Я тоже программист. Я занимался программированием 42[1] года и за это время повидал многое. Меня увольняли. Меня превозносили до небес. Я побывал руководителем группы, начальником, рядовым работником и даже исполнительным директором. Я работал с выдающимися программистами, и я работал со слизняками.[2] Я занимался разработкой как самых передовых встроенных программных/аппаратных систем, так и корпоративных систем начисления зарплаты. Я программировал на COBOL, FORTRAN, BAL, PDP-8, PDP-11, C, C++, Java, Ruby, Smalltalk и на многих других языках. Я работал с бездарными халявщиками, и я работал с высококвалифицированными профессионалами. Именно последней классификации посвящена эта книга.
На ее страницах я попытаюсь определить, что же это такое – «быть профессиональным программистом». Я опишу те атрибуты и признаки, которые, на мой взгляд, присущи настоящим профессионалам.
Откуда я знаю, что это за атрибуты и признаки? Потому что я познал все это на собственном горьком опыте. Видите ли, когда я поступил на свое первое место работы на должность программиста, никому бы не пришло в голову назвать меня профессионалом.
Это было в 1969 году. Мне тогда было 17 лет. Мой отец убедил местную фирму под названием ASC нанять меня программистом на неполный рабочий день. (Да, мой отец это умеет. Однажды он на моих глазах встал на пути разгоняющейся машины, поднял руку и приказал: «Стоять!» Машина остановилась. Моему папе вообще трудно отказать.) Меня приняли на работу, посадили в комнату, где хранились все руководства к компьютерам IBM, и заставили записывать в них описания обновлений за несколько лет. Именно тогда я впервые увидел фразу: «Страница намеренно оставлена пустой».
Через пару дней обновления руководств мой начальник предложил мне написать простую программу на Easycoder.[3] Его просьба вызвала у меня бурный энтузиазм, ведь до этого я еще не написал ни одной программы для настоящего компьютера. Впрочем, я бегло просмотрел несколько книг по Autocoder и примерно представлял, с чего следует начать.
Моя программа должна была прочитать записи с магнитной ленты и изменить идентификаторы этих записей. Значения новых идентификаторов начинались с 1 и увеличивались на 1 для каждой последующей записи. Записи с обновленными идентификаторами должны были записываться на новую ленту.
Начальник показал мне полку, на которой лежало множество стопок красных и синих перфокарт. Представьте, что вы купили 50 колод игральных карт – 25 красных и 25 синих, а потом положили эти колоды друг на друга. Так выглядели эти стопки. В них чередовались карты красного и синего цвета; каждая «колода», состоявшая примерно из 200 карт, содержала исходный код библиотеки подпрограмм. Программисты просто снимали верхнюю «колоду» со стопки (убедившись, что они взяли только красные или только синие карты) и клали ее в конец своей стопки перфокарт.
Моя программа была написана на программных формулярах – больших прямоугольных листах бумаги, разделенных на 25 строк и 80 столбцов. Каждая строка соответствовала одной карте. Программа записывалась на формуляре прописными буквами. В последних 6 столбцах каждой строки записывался ее номер. Номера обычно увеличивались с приращением 10, чтобы позднее в стопку можно было вставить новые карты.
Формуляры передавались операторам подготовки данных. В компании работало несколько десятков женщин, которые брали формуляры из большого ящика и «набивали» их на клавишных перфораторах. Эти машины были очень похожи на пишущие машинки, но они не печатали вводимые знаки на бумаге, а кодировали их, пробивая отверстия в перфокартах.
На следующий день операторы вернули мою программу по внутренней почте. Маленькая стопка перфокарт была завернута в формуляры и перетянута резинкой. Я поискал на перфокартах ошибки набора. Вроде все нормально. Я положил библиотечную колоду в конец своей стопки программ и отнес ее наверх операторам.
Компьютеры были установлены в машинном зале за закрытыми дверями, в зале с регулируемым микроклиматом и фальшполом (для прокладки кабелей). Я постучал в дверь, суровый оператор забрал у меня колоду и положил ее в другой ящик. Моя программа будет запущена, когда до нее дойдет очередь.
На следующий день я получил свою колоду обратно. Она была завернута в листинг и перетянута резинкой. (Да, в те дни мы использовали очень много резинок!)
Я открыл листинг и увидел, что программа не прошла компиляцию. Сообщения об ошибках в листинге оказались слишком сложными для моего понимания, поэтому я отнес их своему начальнику. Он просмотрел листинг, что-то пробормотал про себя, сделал несколько пометок, взял колоду и приказал следовать за ним. Он прошел в операторскую, сел за свободный перфоратор, исправил все карты с ошибками и добавил еще пару карт. Он на скорую руку объяснил суть происходящего, но все промелькнуло в одно мгновение.
Он отнес новую колоду в машинный зал, постучал в дверь, сказал какие-то «волшебные слова» оператору, а затем прошел в компьютерный зал. Оператор установил магнитные ленты на накопители и загрузил колоду, пока мы наблюдали. Завертелись ленты, затарахтел принтер – и на этом все кончилось. Программа заработала.
На следующий день начальник поблагодарил меня за помощь, и моя работа на этом завершилась. Очевидно, фирма ASC посчитала, что ей некогда нянчиться с 17-летними новичками.
Впрочем, моя связь с ASC на этом не завершилась. Через несколько месяцев я получил постоянную работу в вечернюю смену в ASC на обслуживании принтеров. Эти принтеры печатали всякую ерунду с образов, хранившихся на ленте. Я должен был своевременно заправлять принтеры бумагой, ставить ленты с образами, извлекать замятую бумагу и вообще следить за тем, чтобы машины нормально работали.
Все это происходило в 1970 году. Я не мог себе позволить учебу в колледже, да она меня, признаться, не особенно привлекала. Война во Вьетнаме еще не закончилась, и в студенческих городках было неспокойно. Я продолжал штудировать книги по COBOL, Fortran, PL/1, PDP-8 и ассемблеру для IBM 360. Я намеревался обойтись без учебы и как можно быстрее заняться реальным программированием.
Через год я достиг этой цели – меня повысили до штатного программиста в ASC. Я с двумя друзьями Ричардом и Тимом, которым тоже было по 19 лет, трудились вместе с тремя другими программистами над бухгалтерской системой реального времени для фирмы, занимающейся грузовыми перевозками. Мы работали на Varian 620i – простых мини-компьютерах, по архитектуре сходных с PDP-8, не считая того, что у них были 16-разрядные слова и два регистра. Программирование велось на ассемблере.
Мы написали каждую строку кода в этой системе. Да, без преувеличения каждую. Мы написали операционную систему, обработчики прерываний, драйверы ввода/вывода, файловую систему для дисков, систему подгрузки оверлеев и даже компоновщик с динамической переадресацией – не говоря уже о коде приложения. Мы написали все это за 8 месяцев, работая по 70–80 часов в неделю для соблюдения немыслимо жестких сроков. Тогда я получал $7200 в год.
Система была закончена в срок. А потом мы уволились.
Все произошло внезапно, и расставание не было дружеским. Дело в том, что после всей работы и успешной сдачи системы компания дала нам прибавку всего в 2 %. Мы почувствовали себя обманутыми. Некоторые из нас нашли работу в другом месте и попросту подали заявление.
К сожалению, я избрал другой, далеко не лучший путь. Мы с приятелем вломились в кабинет директора и уволились вместе с изрядным скандалом. Это доставило нам эмоциональное удовлетворение – примерно на день.
На следующий день я осознал, что у меня нет работы. Мне было 19 лет, я был безработным без диплома. Я прошел собеседования на нескольких вакансиях из области программирования, но они прошли неудачно. Следующие четыре месяца я проработал в мастерской по ремонту газонокосилок, принадлежащей моему сводному брату. К сожалению, ремонтника из меня не вышло, и в конце концов мне пришлось уйти. Я впал в депрессию.
Я засиживался до трех часов ночи, поедая пиццу и смотря старые фильмы ужасов по черно-белому телевизору моих родителей. Постепенно кошмары стали просачиваться с экрана в мою жизнь. Я валялся в постели до часа дня, потому что не хотел видеть очередной унылый день. Я поступил на курсы математического анализа в региональном колледже и провалил экзамен. Моя жизнь летела под откос.
Моя мать поговорила со мной и объяснила, что так жить нельзя и что я был идиотом, когда уволился, не найдя себе новую работу – да еще со скандалом и на пару с приятелем. Она сказала, что увольняться, не имея новой работы, вообще нельзя, и делать это следует спокойно, трезво и в одиночку. Она сказала, что мне следует позвонить старому начальнику и попроситься на старое место – по ее выражению, «проглотить обиду».
Девятнадцатилетние парни не склонны признавать свои ошибки, и я не был исключением. Тем не менее обстоятельства взяли верх над гордостью. В конечном итоге я позвонил своему начальнику. И ведь сработало! Он охотно принял меня на $6800 в год, а я охотно принял его предложение.
Следующие полтора года я работал на старом месте, обращая внимание на каждую мелочь и стараясь стать как можно более ценным работником. Моей наградой стали повышения и прибавки. Все шло хорошо. Когда я ушел из этой компании, мы остались в хороших отношениях, а мне уже предложили лучшую работу.
Наверное, вы подумали, что я усвоил полученный урок и стал профессионалом? Ничего подобного. Это был лишь первый из многих уроков, которые мне еще предстояло усвоить. В дальнейшем меня уволили с одной работы за сорванный по беспечности график и чуть не уволили с другой за случайное разглашение конфиденциальной информации. Я брался за рискованные проекты и заваливал их, не обращаясь за помощью, которая, как я знал, была мне необходима. Я рьяно защищал свои технические решения, даже если они противоречили потребностям заказчиков. Я принял на работу совершенно неквалифицированного человека, который стал тяжким бременем для моего нанимателя. И что хуже всего, из-за моих организационных ошибок уволили двух других людей.
Так что относитесь к этой книге как к каталогу моих заблуждений, исповеди в моих прегрешениях и сборнику советов, которые помогут вам избежать моих ошибок.
От издательства
Ваши замечания, предложения и вопросы отправляйте по адресу электронной почты comp@piter.com (издательство «Питер», компьютерная редакция).
Мы будем рады узнать ваше мнение!
Подробную информацию о наших книгах вы найдете на веб-сайте издательства http://www.piter.com.
1
Профессионализм
Смейся, Кертин, старина. Над нами сыграли отличную шутку – Господь Бог, природа или судьба, как тебе больше нравится. Но кто бы это ни был, у него наверняка есть чувство юмора! Ха!
Ховард, «Сокровище Сьерра-Мадре»
Итак, вы хотите стать профессиональным разработчиком? Ходить с гордо поднятой головой и объявить всему миру: «Я профессионал!» Хотите, чтобы люди смотрели на вас с уважением, а матери указывали на вас и говорили своим детям, что они должны вырасти такими же. Вы хотите всего этого, верно?
Оборотная сторона профессионализма
Термин «профессионализм» имеет много смысловых оттенков. Конечно, профессионализм – это своего рода почетный знак и повод для гордости, но также он является признаком ответственности. Понятно, что эти стороны профессионализма неразрывно связаны между собой: нельзя гордиться тем, за что вы не несете никакой ответственности.
Быть непрофессионалом намного проще. Непрофессионалы не несут ответственности за выполняемую работу – они оставляют ответственность своим работодателям. Если непрофессионал совершает ошибку, то мусор за ним прибирает работодатель. Но если ошибка совершается профессионалом, то устранять последствия приходится ему самому.
А если в ваш модуль закрадется ошибка, которая обойдется вашей компании в $10 000? Непрофессионал пожмет плечами, скажет: «Всякое бывает», и продолжит писать следующий модуль. Профессионал должен выписать своей компании чек на $10 000![4]
Да, когда речь идет о ваших личных деньгах, все выглядит немного иначе, верно? Но это ощущение присутствует у профессионалов постоянно. Более того, в нем заключается сущность профессионализма. Потому что профессионализм – это ответственное отношение к делу.
Ответственность
Вы прочитали введение, правда? Если не прочитали – вернитесь и прочитайте сейчас; оно задает контекст для всего остального материала.
Чтобы понять, почему так важно брать на себя ответственность, я на собственном опыте пережил последствия отказа от нее.
В 1979 году я работал на компанию Teradyne. Я был «ответственным инженером» за разработку программы, управляющей мини- и микрокомпьютерной системой для измерения качества телефонных линий. Центральный мини-компьютер подключался по выделенным или коммутируемым линиям на скорости 300 бод к десяткам периферийных микрокомпьютеров, управлявших измерительным оборудованием. Код был написан на ассемблере.
Нашими пользователями были администраторы по обслуживанию, работавшие в крупных телефонных компаниях. Каждый из них отвечал за 100 000 и более телефонных линий. Моя система помогала администраторам находить и исправлять неполадки и проблемы в телефонных линиях еще до того, как они будут замечены клиентами. Таким образом сокращалась частота жалоб клиентов – показатель, который измерялся комиссиями по предприятиям коммунального обслуживания и использовался для регулировки тарифов. Короче говоря, эти системы были невероятно важными.
Каждую ночь эти системы проводили «ночную проверку»: центральный мини-компьютер приказывал каждому из периферийных микрокомпьютеров протестировать все телефонные линии, находящиеся под его контролем. Каждое утро центральный компьютер получал список сбойных линий с характеристиками дефектов. По данным отчета администраторы по обслуживанию строили графики работы ремонтников, чтобы сбои исправлялись до поступления жалоб от клиентов.
Время от времени я рассылал нескольким десяткам заказчиков новую версию своей системы. «Рассылал» – самое правильное слово: я записывал программу на ленты и отправлял эти ленты своим клиентам. Клиенты загружали ленты, а затем перезапускали свои системы.
Очередная версия исправляла ряд незначительных дефектов и содержала новую функцию, которую требовали наши клиенты. Мы пообещали реализовать эту новую функцию к определенной дате. Я едва успел записать ленты в ночную смену, чтобы клиенты получили их к обещанной дате.
Через два дня мне позволил Том, наш менеджер эксплуатационного отдела. По его словам, несколько клиентов пожаловались на то, что «ночная проверка» не завершилась, и они не получили отчетов. У меня душа ушла в пятки – ведь чтобы вовремя выдать готовую версию программы, я не стал тестировать новый код. Я протестировал основную функциональность системы, но на тестирование проверки линий потребовались бы много часов, а я должен был выдать программы. Ни одна из исправленных ошибок не содержалась в коде проверки, поэтому я чувствовал себя в безопасности.
Потеря ночного отчета была серьезным делом. Она означала, что у ремонтников было меньше работы, а позднее им придется отрабатывать упущенное. Также некоторые клиенты могли заметить дефект и пожаловаться. Потери данных за целую ночь было достаточно, чтобы менеджер по обслуживанию позвонил Тому и устроил ему разнос.
Я включил тестовую систему, загрузил новую программу и запустил проверку. Программа проработала несколько часов, а затем аварийно завершилась. Код не работал. Если бы я протестировал его до поставки, то данные не были бы потеряны, а менеджеры по обслуживанию не терзали бы Тома.
Я позвонил Тому и сообщил, что мне удалось воспроизвести проблему. Оказалось, что многие другие клиенты уже обращались к нему с той же проблемой. Затем он спросил, когда я смогу исправить ошибку. Я ответил, что пока не знаю, но работаю над ней, а пока клиенты могут вернуться к старой версии программы. Том рассердился – возврат стал бы двойным ударом для клиентов: они теряют данные за целую ночь и не могут использовать обещанную функцию.
Ошибку было трудно найти, а тестирование занимало несколько часов. Первое исправление не сработало. Второе – тоже. Мне понадобилось несколько попыток (а следовательно, дней), чтобы разобраться в происходящем. Все это время Том звонил мне через каждые несколько часов и спрашивал, когда будет исправлена ошибка. Он также передавал мне все, что ему говорили клиенты и как неудобно было предлагать им поставить старые ленты.
В конце концов я нашел дефект, отправил новые ленты, и все вошло в норму. Том (который не был моим начальником) остыл, и весь эпизод остался в прошлом. Но когда все было кончено, мой начальник пришел ко мне и сказал: «Это не должно повториться». Я согласился.
Поразмыслив, я понял, что отправка программы без тестирования кода проверки была безответственным поступком. Я пренебрег тестированием для того, чтобы сказать, что программа была отправлена вовремя. При этом я думал только о своей репутации, а не о клиенте и не о работодателе. А нужно было поступить ответственно: сообщить Тому, что тестирование не завершено и что я не готов сдать программу в назначенный срок. Было бы неприятно, Том расстроился бы, но клиенты не потеряли бы свои данные, и обошлось бы без звонков рассерженных клиентов.
Первое правило: не навреди
Итак, какие же принципы присущи ответственному поведению? Руководствоваться клятвой Гиппократа немного нескромно, но разве можно найти лучший источник? И в конце концов, это только логично – одаренный профессионал должен в первую очередь думать о том, чтобы его способности применялись только в добрых целях?
Какой вред может причинить разработчик? С чисто программной точки зрения он может навредить функциональности и структуре продукта. Давайте разберемся, как избежать именно такого ущерба.
- Экстремальное программирование. Разработка через тестирование
- Как пасти котов. Наставление для программистов, руководящих другими программистами
- Дефрагментация мозга. Софтостроение изнутри
- Чистый код: создание, анализ и рефакторинг (pdf+epub)
- Карьера программиста
- Программист-фанатик
- Отъявленный программист. Лайфхакинг из первых рук
- HTML5 и CSS3. Веб-разработка по стандартам нового поколения
- UML 2.0. Объектно-ориентированное моделирование и разработка
- Идеальный программист. Как стать профессионалом разработки ПО
- Приемы объектно-ориентированного проектирования. Паттерны проектирования
- Приложения для Windows 8 на C# и XAML
- Release it! Проектирование и дизайн ПО для тех, кому не всё равно
- Реактивные шаблоны проектирования (pdf+epub)
- В работу с головой. Паттерны успеха от IT-специалиста
- Swift. Основы разработки приложений под iOS, iPadOS и macOS (pdf + epub)
- Машинное обучение (pdf+epub)
- Kali Linux в действии. Аудит безопасности информационных систем (pdf+epub)
- Глубокое обучение. Погружение в мир нейронных сетей
- Психбольница в руках пациентов. Алан Купер об интерфейсах
- Angular и TypeScript. Сайтостроение для профессионалов (pdf+epub)
- С++17 STL. Стандартная библиотека шаблонов
- Хакинг. Искусство эксплойта (pdf+epub)
- Глубокое обучение на Python (pdf+epub)
- Чистый Python. Тонкости программирования для профи (pdf+epub)
- Глубокое обучение на R (pdf+epub)
- Linux API. Исчерпывающее руководство
- Теоретический минимум по Big Data. Всё что нужно знать о больших данных (pdf+epub)
- Машинное обучение и TensorFlow (pdf+epub)
- Совершенный алгоритм. Основы
- Python. Экспресс-курс (pdf+epub)
- Вероятностное программирование на Python: байесовский вывод и алгоритмы
- Грокаем глубокое обучение (pdf+epub)
- Java для всех (pdf+epub)
- Микросервисы. Паттерны разработки и рефакторинга (pdf+epub)
- Linux в действии (pdf+epub)
- Разработка с использованием квантовых компьютеров (pdf+epub)
- Квантовые вычисления для настоящих айтишников
- Классические задачи Computer Science на языке Python
- Изучаем Python: программирование игр, визуализация данных, веб-приложения
- Глубокое обучение в картинках. Визуальный гид по искусственному интеллекту
- Spring Boot 2: лучшие практики для профессионалов
- Паттерны объектно-ориентированного проектирования
- Время UNIX. A History and a Memoir (pdf + epub)
- Гид по Computer Science. Расширенное издание
- Глубокое обучение: легкая разработка проектов на Python
- Ловушка для багов. Полевое руководство по веб-хакингу (pdf + epub)
- Совершенный алгоритм. Алгоритмы для NP-трудных задач (pdf + epub)
- Vue.js в действии (pdf+epub)
- React быстро (pdf+epub)
- Искусство программирования на R. Погружение в большие данные (pdf+epub)
- Java. Быстрый старт (pdf + epub)
- Python. Быстрый старт (pdf + epub)
- Безопасно by design
- Наглядный CSS
- Scala. Профессиональное программирование
- Обработка естественного языка. Python и spaCy на практике
- Python. Лучшие практики и инструменты
- Байесовская статистика: Star Wars, LEGO, резиновые уточки и многое другое
- Программируй & типизируй. С примерами на TypeScript
- JavaScript с нуля
- Data Science для карьериста
- Облачные архитектуры: разработка устойчивых и экономичных облачных приложений
- Python, например
- Классические задачи Computer Science на языке Java (pdf+epub)
- JavaScript для глубокого обучения: TensorFlow.js (pdf+epub)
- Эффективный C. Профессиональное программирование (pdf+epub)
- {Вы пока еще не знаете JS} Область видимости и замыкания (pdf+epub)
- {Вы пока еще не знаете JS} Познакомьтесь, JavaScript (pdf+epub)
- Путь Python. Черный пояс по разработке, масштабированию, тестированию и развертыванию (+ epub)
- Глубокое обучение с подкреплением на Python. OpenAI Gym и TensorFlow для профи (pdf + epub)
- Стильный Java. Код, который работает всегда и везде
- Глубокое обучение с подкреплением. Теория и практика на языке Python
- System Design. Подготовка к сложному интервью
- Большая книга проектов Python
- Отзывчивый дизайн на HTML5 и CSS3 для любых устройств (pdf + epub)
- Профессиональный бенчмарк. Искусство измерения производительности (pdf + epub)
- Компьютерная графика. Рейтрейсинг и растеризация (pdf+epub)
- Этичный хакинг. Практическое руководство по взлому (pdf+epub)
- Python. Чистый код для продолжающих
- Scala. Профессиональное программирование
- SQL. Быстрое погружение (pdf + epub)
- Теоретический минимум по Computer Science. Сети, криптография и data science (pdf + epub)
- Идеальная работа. Программирование без прикрас
- Управление проектами с нуля (pdf + epub)
- Алгоритмы неформально. Инструкция для начинающих питонистов (pdf + epub)
- Кибердзюцу. Кибербезопасность для современных ниндзя (pdf + epub)
- Тестирование JavaScript
- Грокаем стриминг. Обработка событий в реальном времени
- PyTorch. Освещая глубокое обучение (+ epub)
- Знакомство с Python (+ epub)
- Python без проблем. Решаем реальные задачи и пишем полезный код (+ epub)
- Black Hat Go. Программирование для хакеров и пентестеров (+ epub)
- Создание приложений машинного обучения. От идеи к продукту (+ epub)
- Пять строк кода (+ epub)
- Математические алгоритмы для программистов. 3D-графика, машинное обучение и моделирование на Python (pdf + epub)
- Основы Python для Data Science (pdf + epub)
- Pandas в действии (pdf + epub)
- Kafka Streams и ksqlDB. Данные в реальном времени (pdf + epub)
- Машинное обучение. Портфолио реальных проектов (pdf + epub)
- Внутри CPython. Гид по интерпретатору Python (pdf + epub)
- 40 алгоритмов, которые должен знать каждый программист на Python (pdf + epub)
- Алгоритмы на практике. Решение реальных задач (pdf + epub)
- Объекты. Стильное ООП (pdf + epub)
- Python для хакеров. Нетривиальные задачи и проекты (pdf+epub)
- Software. Ошибки и компромиссы при разработке ПО (pdf+epub)
- Паттерны проектирования API (pdf+epub)
- Код, который умещается в голове: эвристики для разработчиков (pdf+epub)
- Python за 7 дней. Краткий курс для начинающих (pdf+epub)
- README. Суровые реалии разработчиков (pdf+epub)
- Python для data science (pdf+epub)
- SQL Server. Наладка и оптимизация для профессионалов (pdf+epub)
- Аппаратный хакинг: взлом реальных вещей (pdf+epub)
- Рекурсивная книга о рекурсии (pdf+epub)
- JavaScript с нуля до профи (pdf+epub)
- Грокаем функциональное мышление
- Карьера продакт-менеджера. Все что нужно знать для успешной работы в технологической компании
- Грокаем глубокое обучение с подкреплением (pdf + epub)
- Искусство чистого кода (pdf + epub)
- Кодер с улицы. Правила нарушать рекомендуется (pdf + epub)
- Киберкрепость. Всестороннее руководство по компьютерной безопасности
- Прикладные структуры данных и алгоритмы. Прокачиваем навыки (+epub)
- Изучаем vi и Vim. Не просто редакторы (+epub)
- Грокаем функциональное программирование
- Настоящий CTO: думай как технический директор
- Грокаем машинное обучение (pdf + epub)
- Linux для сетевых инженеров (pdf + epub)
- Гейм-дизайн: как создаются игры
- Путь 1С-разработки. Не спеша, эффективно и правильно (pdf + epub)
- Python с нуля (pdf + epub)
- Blender. Дизайн интерьеров и архитектуры (pdf + epub)
- System Design. Машинное обучение. Подготовка к сложному интервью (pdf + epub)
- Основы компиляции: инкрементный подход (pdf + epub)
- Продвинутые алгоритмы и структуры данных (pdf + epub)
- Грокаем Continuous Delivery
- Дизайн для разработчиков (+ epub)
- Тестирование веб-API (+ epub)
- Объектно-ориентированный Python (+ epub)
- Чистый код: создание, анализ и рефакторинг (pdf+epub)
- Основы Dart (pdf+epub)
- Алгоритмы с нуля (pdf+epub)
- Java для опытных разработчиков (pdf+epub)
- Сам себе тестировщик. Пошаговое руководство по тестированию ПО (pdf+epub)
- Основы TypeScript (pdf+epub)
- Антипаттерны SQL. Как избежать ловушек при работе с базами данных (pdf+epub)
- Тюнинг систем. Экспериментирование для инженеров от A/B-тестирования до байесовской оптимизации (pdf+epub)
- Рецепты Python. Коллекция лучших техник программирования (pdf+epub)
- Микросервисы и API (pdf+epub)
- Алгоритмы? Аха! (pdf + epub)
- Программирование на Python с помощью GitHub Copilot и ChatGPT (pdf + epub)
- Hypermedia-разработка. htmx и Hyperview (pdf + epub)
- Поговорим на Python. Разработка ПО для начинающих (pdf + epub)
- Алгоритмы и структуры данных на Python (PDF + EPUB)
- PowerShell: практическая автоматизация. Эффективная разработка скриптов от консоли до облака (PDF + EPUB)
- Грокаем конкурентность