Erhalten Sie Zugang zu diesem und mehr als 300000 Büchern ab EUR 5,99 monatlich.
Незаменимые практические советы по написанию кода в устойчивом темпе и по управлению сложностью, из-за которой проекты часто выходят из-под контроля. В книге описываются методы и процессы, позволяющие решать ключевые вопросы: от создания чек-листов до организации командной работы, от инкапсуляции до декомпозиции, от проектирования API до модульного тестирования. Автор иллюстрирует свои выводы фрагментами кода, взятыми из готового проекта. Написанные на языке C#, они будут понятны всем, кто использует любой объектно-ориентированный язык, включая Java, C++ и TypeScript. Для более глубокого изучения материала вы можете загрузить весь код и подробные комментарии к коммитам.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 372
Veröffentlichungsjahr: 2024
Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:
Переводчик С. Черников
Марк Симан
Роберт Мартин рекомендует. Код, который умещается в голове: эвристики для разработчиков. — СПб.: Питер, 2023.
ISBN 978-5-4461-2293-6
© ООО Издательство "Питер", 2023
Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.
Мы обязаны своим прогрессом в разработке ПО нашим предшественникам. Богатый опыт Марка позволил ему привести в своей книге философские и организационные идеи, а также дать конкретные рекомендации по написанию кода. Вам предоставлена удивительная возможность перенять этот опыт, чтобы помочь себе развиваться. Воспользуйтесь им.
Адам Ральф, спикер, преподаватель и специалист по упрощению особого программного обеспечения
Я читаю блог Марка уже много лет. Каждый его пост несет в себе что-то интересное, в то же время раскрывая глубокие технические познания автора. Книга «Код, который умещается в голове» написана по тому же принципу: она передает огромное количество исчерпывающей информации разработчикам ПО, желающим вывести свои навыки на новый уровень.
Адам Торнхилл, основатель CodeScene, автор книг Software Design X-Rays и Your Code as a Crime Scene
В этой книге мне больше всего нравится то, что в качестве рабочего примера используется единая база. В вашем распоряжении находятся не отдельные части кода, а единый репозиторий Git с полным приложением. Его история создана вручную, чтобы показать эволюцию кода наряду с концепциями, объясняемыми в книге. Читая о конкретном принципе или технике, вы найдете прямую ссылку на код, иллюстрирующий изложенную идею. Конечно, вы можете изучать проект выборочно, останавливаясь на интересующих вас этапах, чтобы проверить, отладить код и поэкспериментировать с ним. Никогда прежде я не встречал в книгах интерактив такого уровня, и это доставляет мне особую радость, потому что здесь по-новому используются преимущества уникальной разработки Git.
Энрико Кампидольо, независимый консультант, спикер и автор Pluralsight
Марк Симан не только опытный архитектор и разработчик больших программных систем, но и один из ведущих идеологов в области масштабирования и управления сложными взаимоотношениями между такими системами и командами, которые их создают.
Майк Хэдлоу, внештатный консультант по программному обеспечению и блогер
Марк Симан известен тем, что ясно и подробно объясняет самые сложные концепции. В этой книге свой обширный опыт разработки ПО он превратил в структуру практических и прагматичных методов для написания устойчивого и читабельного кода. Эта книга — мастхэв для каждого программиста.
Скотт Влашин, автор книги Domain Modeling Made Functional
Марк пишет: «Успешное ПО долговечно», и эта книга поможет вам писать как раз такое ПО.
Брайан Хоган, архитектор ПО, подкастер, блогер
Марк обладает необычайной способностью помогать другим глубоко задуматься об отрасли и профессии разработчиков ПО. После каждого шоу на «.NET Rocks!», которое я сам веду, я еще раз прослушиваю запись, чтобы по-настоящему разобраться во всем, что мы обсуждали.
Ричард Кэмпбелл, соведущий на шоу «.NET Rocks!»
Моим родителям.
Матери Улле Симан за внимание к деталям, которое я перенял от нее.
Отцу Лейфу Симану, который научил меня играть против правил.
Мой внук учится программировать.
Да-да, вы не ошиблись. Мой 18-летний внук учится программировать на компьютере. Его обучает моя младшая дочь, которая родилась в середине 80-х и полтора года назад решила сменить профессию инженера-химика на программиста. Где они оба работают? У моего старшего сына, который вместе со своим младшим братом открывает вторую консалтинговую компанию по разработке ПО.
Да, программное обеспечение рулит в нашей семье. Конечно же, и я не отстаю: тоже программирую уже долгое-долгое время.
Не так давно дочь привезла мне своего сына, и я целый час обучал его основам программирования. Мы начали с кортежей, затем я прочитал ему лекцию о том, что такое компьютеры, как они появились, как выглядели в самом начале и... Ну вы знаете.
К концу нашего занятия я рассказал о разработке алгоритма для умножения двух двоичных целых чисел на языке ассемблера PDP-8. Если вы не в курсе, в PDP-8 нет команды умножения — нам пришлось самостоятельно разрабатывать ее. Там даже не было команды вычитания: для этого нужно было использовать дополнение до двух и добавлять псевдоотрицательное число (чтобы вы понимали всю сложность ситуации).
Когда я закончил с примером кодирования, мне показалось, что я напугал своего внука до смерти. Я имею в виду, что в мои 18 лет этот процесс будоражил меня, но, вероятно, он был не так интересен молодому парню, чья тетя мечтала научить его писать простенький код на Clojure.
Так или иначе, я задумался, насколько сложен на самом деле процесс программирования. Да-да, именно так. Очень сложен. Думаю, это самое трудное, что сотворило человечество.
Я не имею в виду написание кода для вычисления набора простых чисел, или последовательности Фибоначчи, или простой пузырьковой сортировки. Это все не так уж и сложно. Но что насчет авиадиспетчерской системы? Системы выдачи багажа? Складского учета? Игры Angry Birds? Вот что действительно сложно. Очень, очень сложно.
Я знаком с Марком Симаном на протяжении вот уже нескольких лет, но не помню, чтобы мы встречались в жизни. Мы никогда не видели друг друга, но довольно часто общаемся в профессиональных новостных группах и социальных сетях. Он один из моих любимчиков, тот, с кем я всегда буду рад подискутировать.
Наши мнения расходятся во многих областях. Мы спорим о противостоянии статической и динамической типизаций, об операционных системах и языках, полемизируем на темы многих интеллектуально сложных вещей. Но к этому процессу нужно подходить очень осторожно, ведь логика аргументов Марка безупречна.
Увидев эту книгу, я подумал: «Как здорово будет прочесть ее и поспорить с автором». Именно так и произошло. После прочтения я остался не согласен с некоторыми аспектами и с воодушевлением начал искать способы изменить мнение Симана. Мне кажется, что в некоторых случаях у меня это даже получилось… по крайней мере в уме.
Но дело не в этом. Суть в том, что разработка ПО — это сложно, и бо́льшая часть последних семи десятилетий потрачена на поиски способов упростить этот процесс. В своей книге Марк собрал все лучшие идеи за эти 70 лет под одной обложкой.
Более того, он структурировал эти мысли в набор эвристических методов и приемов и привел их в том порядке, в котором нужно их выполнять. Являясь взаимосвязанными, эти техники помогают переходить от этапа к этапу в процессе разработки ПО.
По сути, Марк работает над проектом ПО на протяжении всей книги, объясняя каждый этап и эвристические методы и приемы, которые будут полезны в том или ином случае.
Марк использует язык C# (с чем я не согласен ;-)), но это не главное. Код прост, и эвристические методы и приемы применимы к любому другому языку программирования. Автор охватывает такие темы, как контрольные списки, TDD (разработка через тестирование), CQS (разделение команд и запросов), Git, цикломатическая сложность, ссылочная прозрачность, вертикальные срезы, устранение легаси-кода и разработка outside-in («от общего к частному»), — это лишь некоторые из них.
Вообще, жемчужины знаний встречаются повсюду в этой книге. Я имею в виду, что, читая главу, вы можете внезапно встретить что-то вроде: «Разверните свою тестовую функцию на 90 градусов и посмотрите, сможете ли вы ее сбалансировать по принципу AAA», или «Цель не в том, чтобы писать код быстро. Цель — в устойчивом программном обеспечении», или «Сохраните схему базы данных в репозитории».
Некоторые из этих жемчужин — бесценные знания, некоторые — праздные комментарии, а некоторые — домыслы автора, но все они говорят о глубоком понимании темы, которое Марк приобрел за эти годы.
Внимательно прочтите эту книгу. Задумайтесь о безупречной логике Марка. Внедрите описанные эвристические подходы и приемы. Встретив одну из жемчужин, остановитесь на минутку и поразмышляйте, и, возможно, когда придет время читать лекции своим внукам, вы не напугаете их, как я.
Роберт Мартин
Будущее уже здесь — оно просто не очень равномерно распределено.
Уильям Гибсон
Во второй половине 2000-х я устроился научным редактором в издательство. Ознакомившись с некоторыми из моих работ, редактор связался со мной, чтобы обсудить книгу о внедрении зависимостей.
Наши первые переговоры были немного странными. Обычно, когда ко мне обращались по поводу книги, у нее уже как минимум были план и автор, но не в этот раз. Редактор просто решил узнать, востребована ли такая тема.
Поразмышляв несколько дней, я решил, что тема интересная, но не видел необходимости в целой книге. Аудитории были доступны посты в блогах, техническая документация, журнальные статьи и даже несколько книг (на смежные темы).
Немного погодя, я понял, что доступная информация разбросана по источникам, а термины в ней непоследовательны и противоречивы. Эти знания нужно было объединить и поработать над общей терминологией.
Два года спустя я стал гордым автором опубликованной книги.
По прошествии нескольких лет я задумался о том, чтобы написать еще одну книгу. Не о внедрении зависимостей, а на какую-то другую тему. Потом у меня появилась третья, четвертая, но не хватало именно этой.
Еще через десять лет я начал понимать, что, консультируя команды по написанию лучшего кода, я предлагаю методы, которым научился у гораздо более крутых специалистов, чем я сам. И я снова осознал, что бо́льшая часть этих знаний доступна, но разбросана по разным источникам и мало кто связал их в последовательное описание принципов разработки ПО.
Опыт работы над первой книгой позволил мне понять, что полезно собирать разрозненную информацию и последовательно ее излагать. Это издание — очередная моя попытка создать такой ресурс.
Книга предназначена для опытных программистов. Предполагается, что они уже имели дело с неподдерживаемым кодом, с неудачными проектами по разработке ПО и стремятся к решению этих проблем.
Основная аудитория книги — разработчики корпоративного ПО, в частности бэкенд-разработчики. Я много лет работал в этой области — по сути, книга отражает мой личный опыт. Но если вы фронтенд-разработчик, разработчик игр, DevOps-инженер и т.п., то, думаю, вы все равно извлечете для себя много полезной информации.
Надеюсь, вам будет удобно читать код на компилируемом, объектно-ориентированном языке семейства C. Хотя бо́льшую часть своей карьеры я программировал на C#, я многому научился из книг, где код был написан на C++ или Java1. В этой книге примеры кода приведены на C#, но я надеюсь, что программисты на Java, TypeScript и C++ тоже найдут их полезными.
Это книга не для начинающих. Несмотря на то что в ней рассматриваются вопросы организации и структурирования исходного кода, вы не найдете здесь самых основ. Предполагается, что вы уже понимаете, чем полезны отступы для форматирования кода, почему длинные методы вызывают проблемы, а глобальные переменные — это плохо и т.д. Не обязательно зачитывать до дыр книгу «Совершенный код» [65], но желательно знать основную информацию, описанную там.
Термин «архитектор» каждый понимает по-своему, даже если контекст ограничен разработкой программного обеспечения. Одни архитекторы фокусируются на общей картине, помогают организации в целом преуспеть в своих начинаниях. Другие глубоко разбираются в коде и заботятся в основном об устойчивости конкретной кодовой базы.
Я отношусь к последнему типу. Моя задача — организовать исходный код так, чтобы он отвечал долгосрочным бизнес-целям. Я пишу о том, что знаю, поэтому в первую очередь эта книга будет полезна архитекторам именно этой направленности.
Здесь мы не будем говорить о методах анализа компромиссов в архитектуре (ATAM), анализа видов и последствий отказов (FMEA), об обнаружении сервисов и т.д. Описание таких архитектур выходит за рамки этой книги.
Хотя это пособие о разных методологиях, я структурировал его на примере кода, который используется на протяжении всей книги, чтобы материал был более убедительным, чем в типичном каталоге паттернов программирования. С этой же целью я внедряю практики и эвристические методы, лишь когда они соответствуют повествованию. Также отмечу, что методы здесь расположены именно в том порядке, в котором я обычно представляю их, когда обучаю команды.
Повествование структурировано вокруг примера системы бронирования столиков в ресторане. Исходный код доступен по адресу informit.com/title/9780137464401.
Чтобы эту книгу можно было использовать в качестве справочника, в конце я добавил приложение со списком всех приемов и ссылками на разделы.
Примеры кода написаны на языке C#, который быстро развился за последние годы. В нем внедряется все больше синтаксических идей из функционального программирования. Например, пока я писал эту книгу, были выпущены неизменяемые типы записей. Некоторые из подобных новейших функций языка я решил не учитывать здесь.
Когда-то код Java был очень похож на код C#. Современный же код C# далек от него.
Я хочу, чтобы код смогли понимать как можно больше читателей, и надеюсь, что так же, как я многому научился из книг с примерами на Java, люди смогут использовать это издание, не зная новейшего синтаксиса C#. Поэтому здесь я буду придерживаться консервативного подхода разработки на C#, который должен быть понятен другим программистам.
Это никак не влияет на концепции из книги. Да, возможно, в некоторых случаях есть более лаконичная альтернатива, специфичная для C#, но это лишь означает наличие возможности дополнительных улучшений.
Ключевое слово var было введено в C# в 2007 году. Оно позволяет объявить переменную без явного указания ее типа. Вместо этого компилятор определяет тип из контекста. Для ясности: переменные, объявленные с помощью var, точно так же статически типизированы, как и те, что объявлены с явными типами.
Долгое время использование этого ключевого слова ставилось под сомнение, но сегодня его применяют большинство людей. Я тоже так делаю.
Хотя я использую var в своих проектах, написание кода для пособия — это немного другой контекст. Обычно интегрированная среда разработки (IDE) всегда под рукой. Современные среды могут быстро определить тип неявно типизированной переменной, в отличие от книги. Поэтому я иногда явно объявляю переменные.
В большинстве примеров по-прежнему используется ключевое слово var, так как оно делает код короче, что особенно важно для книги, ширина строки которой ограничена. Но в некоторых случаях я намеренно явно объявляю тип переменной, чтобы облегчить понимание кода при чтении в печатном формате.
Большинство листингов взяты из одного примера кодовой базы. Я использовал репозиторий Git, а примеры кода брал с разных этапов разработки. Каждый такой пример содержит относительный путь к соответствующему файлу, а часть пути к файлу служит идентификатором коммита Git.
Например, в листинге 2.1 приведен такой относительный путь: Restaurant/f729ed9/Restaurant.RestApi/Program.cs. Это значит, что пример взят из коммита с идентификатором f729ed9 из файла Restaurant.RestApi/Program.cs. Проще говоря, чтобы просмотреть эту конкретную версию файла, вам нужно перейти в следующий коммит:
$ git checkout f729ed9
После этого вы можете исследовать файл Restaurant.RestApi/Program.cs в его контексте.
В библиографии вы найдете много ресурсов, включая книги, посты в блогах и видеоролики, большинство из которых есть в интернете, поэтому я указываю URL-адреса. При работе над книгой я старался добавлять в основном те источники, которые есть в свободном доступе в интернете.
Но все меняется. И если на момент, когда вы читаете эту книгу, URL-адрес недействителен, обратитесь к интернет-архиву. Сейчас лучший сайт для этого https://archive.org, но он тоже может исчезнуть в будущем.
Помимо сторонних ресурсов, в библиографии вы найдете и список моих трудов. Я понимаю, что ссылаться на себя — не слишком научный подход, и не воспринимаю написанные мной публикации как некий козырь в рукаве. Свои работы я добавил для тех, кто заинтересован в получении более подробной информации. Я цитирую себя лишь для того, чтобы вы могли найти расширенный аргумент или более подробный пример кода в ресурсе, на который я ссылаюсь.
Я хотел бы поблагодарить свою жену Сесиль за любовь и поддержку на протяжении всех совместно прожитых лет и детей Линею и Ярла, которые старались не доставлять нам хлопот.
Также я благодарен своему бесценному старому другу Карстену Стрёбеку, который не только терпел мои выходки четверть века, но и стал первым рецензентом этой книги. Он помог мне с советами и приемами LaTeX и добавил больше записей в алфавитный указатель, чем я.
Хочу сказать спасибо Адаму Торнхиллу за его отзыв о разделе, посвященном его работе.
Я в долгу перед Дэном Нортом за идею названия этой книги, которая могла выйти еще в 2011 году [72].
Ваши замечания, предложения, вопросы отправляйте по адресу [email protected] (издательство «Питер», компьютерная редакция).
Мы будем рады узнать ваше мнение!
На веб-сайте издательства www.piter.com вы найдете подробную информацию о наших книгах.
1 Если вам интересно, какие книги я имею в виду, загляните в библиографию.
Марк Симан — бывший экономист, который в итоге нашел себя в программировании. Трудился веб-разработчиком и разработчиком корпоративных продуктов с конца 1990-х годов. В молодости Марк мечтал стать рок-звездой, но, к сожалению, по его словам, не обладал ни талантом, ни внешностью — зато потом стал сертифицированным разработчиком Rockstar. Он написал удостоенную премии Jolt2 книгу о внедрении зависимостей, принял участие в сотнях международных конференций и записал видеокурсы для Pluralsight и Clean Coders. Марк регулярно ведет блог с 2006 года. Сейчас он живет в Копенгагене с женой и двумя детьми.
2 Премия Jolt Award известна как «“Оскар” индустрии программного обеспечения». — Примеч. ред.
Первая часть книги построена вокруг процесса программирования. Все примеры кода, от создания первого файла до завершения написания первой функции, соответствуют стандартному образцу кодовой базы.
В начале я буду подробно объяснять все изменения в коде, но по мере продвижения по главам некоторые детали будут опущены. Представленные примеры помогут вам в освоении новых методов и применении их на практике.
Если я упустил какую-то деталь, о которой вы хотели бы узнать больше, можете обратиться к репозиториям Git, ссылка на которые приведена в книге. Каждому листингу кода присвоен свой ID, идентифицирующий определенный источник.
Вам может показаться, что представленная история коммитов безупречна и что я не допустил ни одной ошибки. Но это не так.
Я, как и любой другой человек, могу ошибаться. И одно из преимуществ Git — в возможности переписывать свою историю. Чтобы достичь желаемого результата, мне несколько раз приходилось перебазировать эту часть репозитория. Все это я сделал не для сокрытия своих ошибок, а для того, чтобы они не мешали читателям, которые будут пользоваться моим репозиторием.
Представленные примеры помогут вам лучше понять и использовать описанные мною методы. В этой части книги вы увидите развитие кода от начала до развернутой функции. Но даже если вы не занимаетесь разработкой с нуля, методы, изложенные здесь, помогут вам в повышении личной эффективности.
Вы ученый или художник? Инженер или ремесленник? Садовник или повар? Поэт или архитектор? Наконец, вы программист или разработчик ПО? Кем вы себя считаете?
Мой ответ таков: «Никем из вышеперечисленного. Я программист, но в то же время немного и повар, и садовник, и художник, и строитель».
Важно задавать такие вопросы. Индустрии разработки ПО в общей сложности около 70 лет, и мы все еще не до конца разобрались в этой области. Основная проблема здесь в том, как мы думаем о ней. Процесс разработки программного обеспечения похож на строительство дома? Или он напоминает стихосложение?
Десятилетиями программирование сравнивали с чем угодно, даже с возделыванием сада, но лучшей метафоры так и не нашли.
Я считаю, что то, как мы думаем о разработке ПО, влияет на то, как мы работаем. Программист должен подстраиваться под свои проекты. Он должен понимать, что и для чего он пишет.
Многие годы разработку ПО сравнивали со строительством здания.
Кент Бек сказал об этом так:
«К сожалению, разработка программного обеспечения была скована метафорами физического проектирования» [5].
Это одно из самых распространенных, неоднозначных и вводящих в заблуждение мнений.
Полагая, что разработка ПО похожа на строительство здания, вы совершаете первую ошибку — думаете об этом процессе как о проекте. У проекта есть начало и конец. Как только вы дойдете до конца, работа будет сделана.
Полностью завершить можно только неудачное ПО, успешное же будет долговечным. Качественное программное обеспечение предполагает постоянное развитие, которое может длиться годами, а иногда и десятилетиями3.
После того как здание построено, люди могут в него заселиться. Чтобы поддерживать дом в исправном состоянии, его нужно обслуживать, но затраты на это будут в разы меньше по сравнению с затратами на его проектирование. Конечно, такой софт есть. Например, вы создали внутреннее бизнес-приложение для какой-нибудь корпорации, оно завершено, и пользователи привязаны к нему. По завершении разработки такое ПО переходит в режим обслуживания и сопровождения.
Но большинство конкурентоспособных программных продуктов никогда не будут завершены. Если вы все еще связываете процесс разработки со строительством здания, можете сравнивать его с серией проектов. Вы можете запланировать выпуск следующей версии своего продукта через девять месяцев, но, к своему ужасу, обнаружите, что ваш конкурент внедряет улучшения каждые три.
Вы начинаете усердно работать над тем, чтобы сократить свои «проекты». И к моменту, когда у вас наконец получится выпускать продукт каждые три месяца, ваш конкурент будет внедрять обновления уже ежемесячно. Вы понимаете, к чему все идет?
Это может превратиться в бесконечную погоню за наращиванием функциональности и выпуском новых версий [49] или привести к разорению. В книге «Ускоряйся!» [29] приводятся научно подкрепленные аргументы того, что ключевым свойством, отличающим высокоэффективные команды от низкоэффективных, служит способность мгновенно обновлять и распространять информацию.
Если вы будете способны это сделать, понятие проекта разработки программного обеспечения потеряет свою актуальность.
Еще одно заблуждение, связанное с метафорой строительства: ПО нужно разрабатывать в несколько этапов. Перед началом работ архитектор создает чертеж. Далее оценивается логистика, на площадку поставляются материалы, и только после этого можно приступать к постройке здания.
В случае если метафора уместна, вы назначаете архитектора программного обеспечения, в обязанности которого входит создание плана. Только после этого можно бужет начать разработку ПО. Этот этап — этап проектирования — довольно сложный интеллектуальный процесс. Если возвращаться к аналогии со строительством, то он похож на фактический этап самих строительных работ, где разработчики — это взаимозаменяемые сотрудники4, вроде машинистов.
Но это очень отдаленное сравнение. Как указал Джек Ривз в 1992 г. [87], этап создания программного обеспечения — это когда вы компилируете исходный код. По сравнению со строительством здания этот процесс можно назвать почти бесплатным. Вся работа происходит на этапе проектирования, или, как выразился Кевлин Хенни:
«Недвусмысленное описание программы и программирование — это один и тот же процесс» [42].
В рамках разработки ПО мы не можем говорить об этапе строительства. Это не означает, что проектирование бесполезно, но указывает на то, что метафора с с постройкой здания здесь неприменима.
Строительство ведется в соответствии с определенными нормами и требованиями: сначала нужно заложить фундамент, затем возвести стены и только потом можно устанавливать крышу. Другими словами, все эти процессы взаимосвязаны и взаимозависимы.
Такая аналогия внушает ложную идею того, что зависимостями можно управлять. Я знаком с менеджерами, которые для планирования проекта составляли сложные диаграммы Ганта.
Я работал со многими командами, и большинство из них начинают любой проект с разработки схемы реляционной базы данных (БД). БД — основа большинства онлайн-сервисов, и ни один разработчик не будет спорить с тем, что можно спроектировать пользовательский интерфейс еще до появления базы данных.
Некоторым командам иногда даже не удается создать полностью рабочее ПО. После того как БД спроектирована, они решают, что необходимо создать так называемый каркас приложения, или фреймворк. Они продолжают заново изобретать ORM (Object-Relational Mapping, объектно-реляционное отображение), этот Вьетнам computer science [70].
Метафора строительства дома вредна — она заставляет вас думать о разработке ПО определенным образом. Вы упустите возможности, которых не видите из-за того, что ваша точка зрения не совпадает с реальностью. Образно говоря, разработку программного обеспечения вы можете начать с установки крыши. Немного позже я подкреплю эти слова примером.
Мы выяснили, что аналогия со строительством не подходит, но, возможно, другие подойдут больше. В 2010-х годах становится популярной метафора возделывания сада. Не случайно Нат Прайс и Стив Фримен назвали свою книгу Growing Object-Oriented Software, Guided by Tests [36].
В этом примере ПО сравнивается с живым организмом, который требует особенного отношения, вложения большого количества сил и внимания. Это еще одна вполне убедительная метафора. Вы когда-нибудь думали о том, что кодовая база живет своей жизнью?
Возможно, будет правильнее рассматривать программное обеспечение именно с этой точки зрения? По крайней мере, так мы сможем не ограничиваться только строительством здания.
Теперь, в рамках аналогии с взращиванием сада, мы делаем акцент на обрезке (сокращении). Если не ухаживать за зеленью, она начнет разрастаться. Предотвратить этот процесс может садовник, избавляясь от сорняков и поддерживая культурные растения. При разработке ПО это помогает сосредоточиться на действиях, предотвращающих «загнивание» кода, таких как рефакторинг и удаление мертвого кода.
Но мне кажется, что эта метафора тоже не дает нам полного представления о процессе разработки ПО.
Мне нравится, что аналогия с садоводством делает упор на действиях, предотвращающих беспорядок. Точно так же, как вы должны ухаживать за своим садом, вам необходимо проводить рефакторинг и погашать технический долг в своих кодовых базах.
С другой стороны, эта метафора мало говорит о том, откуда берется код. В саду растения растут сами по себе: все, что им нужно, — удобрения, солнечный свет и вода. ПО само по себе развиваться не будет. Вы не можете просто забросить компьютер, чипсы и колу в темную комнату и ожидать, что из этого вырастет программное обеспечение. Все это не будет работать без самой важной составляющей — программистов.
Код должен быть написан кем-то. Это активный процесс, и здесь аналогия с садом становится уже не такой актуальной. Как вы решаете, что писать, а что — нет? Как принимаете решение о том, как структурировать код?
Мы должны ответить на эти вопросы, если хотим улучшить индустрию разработки программного обеспечения.
Для разработки ПО есть и другие метафоры. Например, термин «технический долг», который я упоминал ранее, можно сравнить с финансовым кредитом. А процесс написания кода напоминает некоторые виды авторской деятельности. Все эти аналогии в какой-то степени верны, но ни одна из них не будет абсолютно правильной.
Но я начал эту книгу именно с аналогии со строительством здания. И на то есть несколько причин. Во-первых, это сравнение довольно распространено. Во-вторых, оно кажется настолько неправильным, что его уже невозможно спасти.
К выводу, что аналогия со строительством вредна, я пришел много лет назад. И как правило, после отказа от одной теории вы обычно начинаете искать другую. Я нашел ее в ремесле программного обес-печения.
Давайте рассмотрим разработку ПО как ремесло, ведь, по сути, это и есть квалифицированный труд. Вы можете получить образование в области computer science, но это вовсе не обязательно. У меня, например, его нет5.
Навыки, необходимые профессиональным разработчикам ПО, обычно зависят от ситуации. Изучите, как устроена конкретная кодовая база, научитесь использовать конкретный фреймворк, потратьте время на исправление ошибок в продакшене. От вас будет требоваться что-то вроде этого.
Чем больше вы что-то делаете, тем опытнее вы становитесь. Если вы останетесь в одной компании и будете годами работать с одной и той же кодовой базой, вы можете стать специалистом. Но как это поможет вам при устройстве на другую работу?
Вы будете развиваться быстрее, переходя от одной кодовой базы к другой. Освойте бэкенд- и фронтенд-разработку. Изучите программирование игр или машинное обучение. Так вы гарантированно сможете накопить полезный опыт.
Становление разработчика ПО подобно старой традиции странствующего подмастерья в Европе. Ремесленник, плотник или кровельщик путешествовал по разным городам и странам, вкладывая все свои силы в ремесло. Все это открывало большие возможности и позволяло оттачивать свои навыки. В книге «Программист-прагматик» даже есть раздел «Путь от подмастерья к мастеру» [50].
Если это утверждение верно, мы должны соответствующим образом структурировать нашу отрасль. У нас должны быть ученики, работающие вместе с мастерами. Мы могли бы даже организовать гильдии.
Так ведь?
Программирование как ремесло — еще одна метафора. Это похоже на ослепляющий свет истины, но он может таить в себе тени скрытого подтекста. Как говорится, чем ярче свет, тем темнее кажутся тени (рис. 1.1).
Рис. 1.1. Чем ярче освещена фигура, тем темнее отбрасываемая ею тень
Кажется, на рисунке все еще чего-то не хватает.
Годы, когда я занимался разработкой ПО, в некотором смысле были периодом полнейшего разочарования. Я рассматривал ремесло исключительно с точки зрения накопления опыта. Мне казалось, что нет никаких методологий и правил, что все зависит только от обстоятельств. Я думал, что не существует правильного или неправильного способа что-то делать.
Программирование было своего рода творчеством, что меня вполне устраивало. Мне всегда нравилось искусство. В молодости я даже хотел стать художником6.
С этой точкой зрения проблема кажется невероятно сложной. Чтобы «взрастить» новых программистов, вам придется их обучать. А на то, чтобы преодолеть путь от подмастерья до мастера, у них может уйти несколько лет.
Еще одна проблема, связанная с отношением к программированию как к искусству или ремеслу, состоит в том, что эта аналогия тоже не соответствует действительности. Примерно в 2010 году я начал задумываться над тем [106], что все то время, когда программировал, я следовал эвристике — эмпирическим правилам и рекомендациям.
Поначалу я не придал этому большого значения. Но в дальнейшем, в процессе обучения других разработчиков, я часто определенным образом формулировал доводы для написания кода.
Я начал понимать, что ошибался в своих смелых утверждениях, и понял: рекомендации могут стать ключом к превращению программирования в техническую дисциплину.
О программной инженерии заговорили ближе к концу 1960-х годов7. Это было связано с кризисом ПО того времени — с появлением идеи о том, что программировать сложно.
На тот момент программисты действительно хорошо понимали, что делают. Многие выдающиеся деятели нашей отрасли трудились в то время: Эдсгер Дейкстра, Тони Хоар, Дональд Кнут, Алан Кей. Если бы вы тогда у них спросили, станет ли в 2020-х годах программирование отдельным предметом для изучения, вероятно, они бы ответили утвердительно.
Вы могли заметить, что я рассматриваю разработку ПО как амбициозную цель, а не как повседневную рутину. Вполне возможно, что в мире есть центры реальной разработки программного обеспечения8, но, по моему опыту, бо́льшая часть разработки программного обеспечения ведется в иной манере.
Я не одинок, предполагая, что разработка ПО — это наше будущее.
Адам Барр сказал следующее:
«Если вы похожи на меня, то вы мечтаете о том дне, когда разработка программного обеспечения будет изучаться вдумчиво и методично, а руководство, предоставленное программистам, будет основываться на экспериментальных результатах, а не на зыбучих песках индивидуального опыта» [4].
Адам Барр объясняет, что программная инженерия стремительно развивалась, но затем появилось нечто, что помешало ей, — персональные компьютеры. Благодаря их развитию стали появляться разработчики, которые научились программировать самостоятельно. Поскольку они сами могли разбираться с компьютерами, они оставались в неведении относительно уже существовавших знаний.
Такая ситуация сохраняется и по сей день. Алан Кей описывает компьютерную поп-культуру так:
«Поп-культура презирает историю. Она дает ощущение самобытности и вовлеченности, причастности. Это не имеет ничего общего с сотрудничеством, прошлым или будущим, — это жизнь в настоящем. Я думаю, то же относится и к большинству людей, которые пишут код за деньги. Они понятия не имеют, откуда взялась их культура» [52].
Возможно, мы потеряли полвека, добившись незначительного развития программной инженерии, но я думаю, что мы могли достичь прогресса в других направлениях.
Что делает инженер? Проектирует и контролирует каждый этап строительных работ, начиная от больших сооружений, таких как мосты (рис. 1.2), туннели, небоскребы и электростанции, до крошечных объектов, таких как микропроцессоры9. Инженер помогает создавать физические объекты.
Рис. 1.2.Мост королевы Александрины (Queen Alexandrine Bridge) — арочный мост через пролив Ульвсунн между островами Зеландия и Мён в Дании. Был открыт в 1943 году
Но программисты так не делают, ведь ПО неосязаемо. Как сказал Джек Ривз [87], поскольку физического объекта нет, проектирование не будет ничего вам стоить. Разработка программного обеспечения — это прежде всего проектная деятельность. Написание кода больше похоже на построение плана инженером, а не на работу строителей на объекте.
Настоящие инженеры следуют методологиям, которые, как правило, приводят к успешным результатам. Мы, программисты, тоже хотим так делать. Но мы должны быть предельно внимательны и выполнять только те действия, которые будут целесообразны в нашем контексте. Когда проектируется физический объект, реальная конструкция стоит дорого. Вы не можете просто взять и попробовать построить мост, проверить его в течение какого-то времени, а потом решить, что он не особо хорош, разрушить его и начать все сначала. Поскольку на реальное строительство уходит много средств, инженеры изначально занимаются расчетами и моделированием. Для расчета прочности моста нужно меньше времени и материалов, чем для его строительства.
Есть целая инженерная дисциплина, связанная с логистикой. Люди занимаются тщательным планированием — самым безопасным и наименее затратным способом создания физических объектов.
Это часть инженерии, которую нам не нужно копировать.
Но есть и много других приемов, которые могут нас вдохновить. Инженеры способны и на творческую работу, но она, как правило, четко структурирована. За одними конкретными действиями должны следовать другие. Специалисты контролируют и утверждают работу друг друга, следуют контрольному списку (чек-листу) [40].
Вы тоже можете так сделать.
Я считаю, что изучение эвристики — весьма полезное и занимательное занятие, но в то же время и очень сложное. Адам Барр называет это зыбучими песками индивидуального опыта.
Я считаю, что это отражает текущее состояние нашей отрасли. Любой, кто полагает, что у нас есть четкие научные доказательства, должен прочесть The Leprechauns of Software Engineering («Лепреконы программной инженерии») [13].
Думая об истории разработки ПО, вы, вероятно, представляете себе успешное развитие отрасли и большое количество достижений. Но многие из этих достижений связаны с аппаратным, а не с программным обеспечением. И все-таки в разработке ПО за последние 50 лет мы добились существенного прогресса.
Сегодня у нас есть гораздо более продвинутые языки программирования, чем полвека назад, доступ к интернету (включая сервисы взаимопомощи наподобие Stack Overflow), объектно-ориентированное и функциональное программирование, автоматизированные среды тестирования, Git, интегрированные среды разработки и пр.
С другой стороны, мы все еще боремся с программным кризисом. Хотя можно ли назвать кризисом то, что длится уже полвека?
Несмотря на серьезные усилия, индустрия разработки ПО все еще не похожа на инженерную дисциплину. Между инженерией и программированием есть некоторые фундаментальные различия, и пока мы этого не поймем, мы не сможем добиться прогресса.
Хорошая новость в том, что программисты могут многое почерпнуть у инженеров: образ мыслей и набор процессов, которым можно следовать.
Как отметил научный фантаст Уильям Гибсон, будущее уже наступило, просто оно еще неравномерно распределено10.
Как говорится в книге «Ускоряйся!», одни организации сегодня используют передовые методики, а другие отстают [29]. Будущее действительно распределено неравномерно. Хорошая новость в том, что прогрессивные возможности — в свободном доступе и, как вы будете их использовать, зависит только от вас.
В главе 2 вы познакомитесь с конкретными методами, которые сможете применить на практике.
3 Эта книга сверстана в LaTeX — ПО, первая версия которого была выпущена в 1984 году!
4 Ничего не имею против строителей — мой отец был каменщиком.
5 Если вам любопытно, у меня есть высшее образование в сфере экономики, но, кроме как для работы в министерстве экономики Дании, оно мне больше не пригодилось.
6 Я давно мечтал стать художником комиксов в европейской традиции. Позже, будучи подростком, я взял в руки гитару и решил стать рок-звездой. Но выяснилось, что, хотя мне нравилось и рисовать, и играть, я не был особо талантлив.
7 Термин может быть старше. Я не могу ничего об этом рассказать, так как тогда я еще не родился. Но тот факт, что две конференции НАТО, в 1968 и 1969 годах, популяризировали термин «программная инженерия», не вызывает сомнений [4].
8 НАСА выглядит достаточно близким к тому, чтобы быть одним из таких центров.
9 У меня когда-то был друг, инженер-химик по образованию. После окончания университета он стал пивоваром в Carlsberg. Так что инженеры могут даже варить пиво.
10 Это довольно расплывчатая цитата. Идея и формулировка в целом принадлежат У. Гибсону, но неясно, когда именно он впервые заявил об этом [76].
Как программисту стать инженером-программистом? Я не утверждаю, что в книге есть однозначный ответ на этот вопрос, но надеюсь, что, прочитав ее, вы сможете выбрать верный для себя путь.
Что касается разработки ПО, то я думаю, что многое нам еще не дано понять. С другой стороны, мы не можем ждать, пока во всем разберемся. Мы извлекаем уроки и учимся на собственном опыте. Действия и методологии из этой книги уже давно придуманы великими людьми11. Эти практики до сих пор актуальны для меня и многих специалистов, которых я обучал. Надеюсь, что они будут полезными для вас или вдохновят вас на разработку своих, более совершенных методов.
Основная проблема разработки ПО в том, что происходит огромное количество процессов, а наш мозг не способен решать несколько задач одновременно.
Еще мы склонны игнорировать дела, которые не кажутся нам важными в данный момент.
Проблема не в том, что вы не знаете, как делать, а в том, что вы забываете это сделать, хотя знаете, что должны.
Эта проблема касается не только программирования. От этого страдают и, например, пилоты. Последние придумали простое решение проблемы: чек-листы.
Я понимаю, что это звучит невероятно скучно, но советую вам ознакомиться с историей происхождения чек-листа. Согласно Атулу Гаванде [40], идея чек-листов появилась в 1935 году, когда во время испытаний разбился прототип бомбардировщика B-17, что едва не привело к закрытию проекта. По сравнению с предыдущими самолетами В-17 оказался слишком сложным и дорогим в производстве. Управлять бомбардировщиком было непросто, что привело к трагедии, в результате которой погибли два члена экипажа, включая пилота.
Расследование авиакатастрофы показало, что причиной крушения стала ошибка пилота. Учитывая, что пилот был одним из самых опытных летчиков-испытателей армейской авиации, вряд ли это можно было бы списать на непрофессионализм. Как позже написали в одной из газет, самолет был слишком сложен, чтобы на нем мог летать один человек [40].
В результате группой летчиков-испытателей было придумано простое решение: создать чек-лист основных операций выполнения этапов взлета и посадки.
Простые чек-листы значительно расширяют возможности квалифицированных специалистов, таких как пилоты. При решении сложной задачи вы неизбежно забываете учитывать одно или несколько действий. Контрольный список поможет вам сосредоточиться на сложных частях вашей задачи, отвлекая внимание от разных мелочей. Вам не нужно будет прилагать усилия для выполнения всех простых действий — вы просто будете следовать пунктам.
Важно понимать, что чек-листы должны помогать, поддерживать и освобождать специалиста. Они не предназначены для мониторинга или аудита. Сила таких списков в том, что работа с ними всегда выполняется качественно, единообразно и результативно. Хороший чек-лист поможет добиться необходимого результата и избежать ошибок. Это могут быть просто списки на плакате, в буфере обмена, в скоросшивателе и т.д.
Чек-листы не должны ограничивать вас в действиях. Они предназначены для улучшения организации процесса и повышения качества достигаемого результата.
Американский хирург и общественный деятель Атул Гаванде разработал чек-лист для врачей и медперсонала, который напоминает мыть руки перед операцией, проверять, давно ли введен антибиотик, и проводить рабочие совещания. Результаты оказались впечатляющими [40].
Если пилоты и хирурги смогли использовать чек-листы, то сможете и вы. Суть в том, чтобы улучшить результат, не улучшая навыки.
Далее я периодически буду приводить примеры чек-листов. Это не единственный «инженерный подход», который вы изучите, но он самый простой. Пусть это будет хорошим началом!
Контрольный список просто помогает вам не забыть о чем-то. Он не должен ограничивать вас — он существует, чтобы помочь вам не забывать выполнять тривиальные, но важные действия, такие как мытье рук перед операцией.
Чек-листы из этой книги основаны на моем подходе к программированию и носят рекомендательный характер. Ваши ситуации могут отличаться, поэтому мои рекомендации могут подойти вам только частично. Так же как чек-лист по проверке взлета Airbus A380 отличается от чек-листа для B-17.
Так что просто ознакомьтесь с предложенными примерами и используйте наиболее подходящие для вашей конкретной ситуации либо создавайте свои наподобие.
Вот чек-лист для запуска новой кодовой базы.
1. Использовать Git.
2. Автоматизировать сборку.
3. Включить все сообщения об ошибках.
Я преднамеренно создал такой короткий список. Чек-лист — это не сложная блок-схема с подробными инструкциями. Это простой перечень, который вы можете охватить за несколько минут.
Чек-листы бывают двух видов: «прочитал — сделал» и «сделал — отметил» [40]. Цель первого — читать каждый пункт и выполнять действия строго друг за другом. Во втором вы выполняете все действия, а затем проверяете и подтверждаете завершенные отметкой.
Я намеренно оставил приведенный выше список расплывчатым и абстрактным, но, так как в нем использовано повелительное наклонение, он будет считаться чек-листом «прочитал — сделал». Но вы можете легко сделать из него чек-лист «сделал — отметил», и я настоятельно советую, чтобы его просмотрел другой человек. Именно так делают пилоты: один читает чек-лист, а другой подтверждает. В одиночку очень легко пропустить важный пункт, но товарищ всегда может вас подстраховать.
Как именно использовать Git, автоматизировать сборку и включать все сообщения об ошибках, зависит от вас. Далее мы разберем пример создания более конкретного чек-листа на основе списка, представленного выше.
Git — стандартная система контроля версий для проектов с открытым исходным кодом, поэтому я рекомендую использовать именно его12.
По сравнению с централизованными системами управления версиями, такими как CVS или Subversion, распределенная система (Git) дает вам огромное преимущество. Но Git может быть полезна, только если вы знаете, как ее использовать.
Это не самая удобная система в мире, но вы — программист. Вам удалось выучить как минимум один язык программирования, и на фоне этого опыта изучить основы Git будет для вас проще простого. Но обязательно потратьте на это время. Не на изучение графического пользовательского интерфейса, а на изучение основного функционала Git, того, как система работает на самом деле.
Git дает возможность смело экспериментировать с кодом. Вы можете написать код и, если он не сработает, просто отменить изменения. Именно способность работать в качестве системы контроля версий на вашем жестком диске ставит Git выше централизованных систем.
У Git еще есть несколько графических пользовательских интерфейсов (GUI), но в этой книге я остановлюсь на командной строке. Это не только основа Git, но и способ, которым я обычно предпочитаю с ним работать. И так как моя ОС — Windows, я работаю в командной строке Git Bash.
Первое, что нужно сделать в новой кодовой базе, — инициализировать локальный репозиторий Git13. Откройте окно командной строки в папке, в которую хотите поместить код. Сейчас вам не нужно беспокоиться об онлайн-сервисах Git вроде GitHub. Вы всегда можете подключить репозиторий позже. Затем пропишите следующую команду14:
$ git init
Вот и все. Вы можете последовать совету моего друга Энрико Компидоглио [17] и добавить пустой коммит:
$ git commit --allow-empty -m "Initial commit"
Обычно я тоже так делаю, поскольку это позволяет мне переписать историю моего репозитория, прежде чем я опубликую его в онлайн-сервисе Git. Но так делать вам совсем не обязательно.
Когда у вас почти нет кода, легко автоматизировать компиляцию, тестирование и развертывание. Попытка же приспособить непрерывную доставку (continuous delivery, CD, CDE) [49] к существующей кодовой базе может показаться сложной задачей. Поэтому мы с вами займемся этим прямо сейчас.
Сейчас у вас нет кода, есть только репозиторий Git. Вам нужно сделать небольшое приложение, чтобы было что компилировать. Создайте минимальный объем кода, который сможете развернуть. Эта концепция похожа на «ходячий скелет» [36], но на один шаг раньше в процессе разработки (рис. 2.1).
Рис. 2.1. Чтобы создать оболочку приложения, закоммитить ее и развернуть, используйте мастер или программу формирования шаблонов. Далее используйте автоматизированный тест для создания «ходячего скелета» [36], с которым вы будете совершать эти же действия
«Ходячий скелет» (Walking Skeleton) — это реализация наименьшей возможной функциональности, которую вы можете автоматически создавать, развертывать и тестировать от начала до конца [36]. Вы можете сделать это следующим шагом, но я думаю, что лучше сначала установить конвейер развертывания [49].
Распространенные проблемы, связанные с созданием конвейера развертывания
Что делать, если вы не можете настроить конвейер развертывания? Возможно, у вас нет сервера непрерывной интеграции. Если это так, то его нужно приобрести. Вовсе не обязательно покупать реальный сервер — сейчас есть множество облачных сервисов непрерывной доставки.
Возможно, у вас нет продакшен-среды (production environment, PROD)? Решить эту проблему можно, настроив конвейер развертывания так, чтобы вы могли выпускать его в тестовой среде. Желательно тот, который максимально похож на продакшен-среду. Даже если вы не можете получить аппаратное обеспечение, похожее на продакшен-среду, попробуйте смоделировать топологию сети продакшен-системы. Вы можете использовать машины поменьше, виртуальные машины или контейнеры.
Большинство методов, которые я предлагаю здесь, бесплатны. Самые большие суммы обычно идут на оплату работы серверов, ПО или облачных сервисов. Эти затраты обычно составляют лишь малую часть от зарплаты программиста, поэтому, по сравнению с общей стоимостью разработки ПО, эти деньги будут потрачены не зря.
Перед настройкой конвейера развертывания важно убедиться, что вы можете легко скомпилировать код и запустить тесты для разработчиков. В этом случае вам понадобится код.
Эта книга построена вокруг одного основного примера: разработки простой системы онлайн-бронирования ресторанов на языке C#. И прямо сейчас нам нужен веб-сервис, который будет обрабатывать HTTP-запросы.
Самый простой способ начать двигаться в этом направлении — создать веб-проект на ASP.NET Core. Для этого я буду использовать среду разработки Visual Studio15. Хотя мне нравится использовать интерфейсы командной строки для часто выполняемых взаимодействий, я считаю полезным и руководство по IDE, которое помогает мне в решении моих задач. По желанию вы можете использовать вместо этого инструмент командной строки, но результат должен быть тем же: несколько файлов и работающий веб-сайт. В листингах 2.1 и 2.2 показаны16 примеры файлов, созданных Visual Studio.
После запуска сайта вы увидите, что он содержит следующий текстовый файл:
Hello World!
Сейчас нам этого достаточно, поэтому сделайте коммит своего кода в Git.
Листинг 2.1. Точка входа веб-сервиса ASP.NET Core по умолчанию, созданная Visual Studio (Restaurant/f729ed9/Restaurant.RestApi/Program.cs)
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Цель этого шага — автоматизация сборки. Вы можете открыть свою IDE и использовать ее для компиляции кода, но это нельзя будет автоматизировать. Создайте файл сценария, выполняющего сборку, и тоже отправьте коммит в Git. На начальном этапе все так же просто, как в листинге 2.3.
Несмотря на то что я работаю в Windows, я все время использую командную строку в Bash, поэтому я определил сценарий оболочки. Вместо этого вы можете создать файл .bat или скрипт PowerShell17. Важно то, что прямо сейчас должна быть вызвана команда dotnetbuild. Обратите внимание: я настраиваю релизную сборку. Автоматизированная сборка должна отражать то, что в конечном итоге будет запущено в производство.
По мере добавления шагов сборки их следует добавлять и в скрипт. Он должен стать простым инструментом, который разработчики могут запускать на своей машине. Если скрипт сборки выполняется на компьютере разработчика, можно отправлять изменения на сервер непрерывной интеграции.
Листинг 2.2. Файл по умолчанию Startup, сгенерированный Visual Studio. Чтобы строки с комментариями выглядели более эстетично и компактно, я их отредактировал (Restaurant/f729ed9/Restaurant.RestApi/Startup.cs)
public class Startup
{
// This method gets called by the runtime. Use this method to add
// services to the container.
// For more information on how to configure your application,
// visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method
// to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app,
IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
Листинг 2.3. Скрипт сборки (Restaurant/f729ed9/build.sh)
#!/usr/bin/env bash
dotnet build --configuration Release