[БЕЗ_ЗВУКА] [БЕЗ_ЗВУКА] Здравствуйте, уважаемые слушатели! В этом видео я покажу вам разработку сверху вниз. Главная задача разработки сверху вниз состоит в том, чтобы управлять концентрацией внимания программиста. В том, чтобы вы не потерялись в большом количестве программного кода и исходную задачу смогли разбить аккуратно на подзадачи. Я взял задачу рисования пейзажа при помощи графической библиотеки Джона Зелле. Это очень простая библиотека из одного файла, ссылку на нее вы найдете в описании. Давайте приступим. В первую очередь я вызову эту библиотеку, вызову функцию main. Естественно, что этой функции main пока что нет. Давайте ее создавать. Я делаю функцию main. И как мне сделать ее быстрее всего, с чего начать? Я сделаю заглушку, я просто сделаю pass, и у меня функция готова. Давайте проверим, что у меня в принципе библиотека работает, все запускается. Программа стартовала и закрылась. Нет, мне так не нравится, потому что нет никакой графики, нет никакого окошка. Надо добавить рисование окна. Добавляем, что у нас создается фактическое окно, вот сюда вписываем. Вот реальное окно, я дожидаюсь события от мышки, чтобы закрыть это окошко. Вот теперь, пожалуйста, у меня программа запускается, и есть графическое окошко. Пора рисовать. Естественно, здесь должно быть содержимое. И вот в этот момент можно пойти по неправильному пути. Начинающий программист здесь возьмет, засучит свои рукава, схватится за геометрические примитивы и давай шарашить и что-то рисовать. Нет. Я хочу пойти именно сверху вниз. Я буду сейчас выделять подзадачи и отбрасывать их так. Я так это вижу. Давайте вызовем волшебника. Функцию, которая нарисует нам просто все. Естественно, что этой функции понадобится для этого окно. Она не может без окна нарисовать. Поэтому у меня фактически функция main, она будет содержать этот момент. Это момент, когда я в принципе готов почти закончить. Программа написана. Нет. Конечно же, мы прекрасно понимаем, что этой функции нет, и мне интерпретатор об этом напомнит, он скажет draw_image is not defined. Конечно же, надо же ее прописать. Тем не менее, я часть функционала уже выделил, у меня уже есть отдельно создание окна, и внутри этой функции draw_image мне уже не надо задумываться о том, как там создается это окно. Я прописываю следующим образом эту функцию. Я прописываю точно так же, как с функцией main. Я бросаю функцию-заготовку pass и TODO. Все, я сделаю потом. Это очень важный момент, потому что я опять сделал маленький прыжок. То есть я раз — и прыгнул в консистентное состояние программы, когда она не разломана. Она может быть запущена — да, ничего не изменилось, все по-прежнему, реально этот волшебник, которого я вызываю, он просто ничего не делает. Но интерфейс вызова соблюден? Соблюден. Функция вызывается? Вызывается, пожалуйста. Двигаемся дальше. Пора прописать, что такое это самое image. Давайте сочинять. Мой пейзаж будет состоять из фона и домика на этом фоне. Соответственно я прописываю две такие функции: draw_background и draw_house. Сами названия этих функций уже о многом говорят, поэтому я буду экономить на документ-строках, чего на самом деле, конечно, делать не стоит. Но в данном программном коде, чтобы это дело быстро показать, комментариев не будет, сами названия функций. Но тут интересный момент. Как только я продумываю, вот я хочу вызвать рисование домика, все-таки у меня некоторые сомнения закрадываются. Я не просто хочу разбить задачу на две подзадачи. У меня вот была исходная: вот отдельно фон, отдельно домик. Нет. Я бы хотел параметризовать задачу рисования домика. Да, я ее вызову здесь с конкретными значениями параметров, то есть я вот сюда сейчас суну какие-то конкретные... Допустим, house_x, house_y, какие-то ее координаты вставлю, house_width, house_height. Но это будут конкретные параметры, и я смогу, если что, вызвать рисование нескольких домиков, например. Это очень важно, когда мы создаем функцию, сделать ее в меру универсальной. Ну что же, мои функции прописаны, давайте допишем эти параметры. Вот у меня эти параметры, относительно которых я это все запускаю. Опять мой творческий порыв закончился. Я придумал, что такое нарисовать пейзаж, я придумал параметры домика, параметров фона у меня нет. Тем не менее, творческие действия закончены. Я сделаю сейчас такую поверхность, и я двигаюсь прыжками. Мой первый прыжок был рисование, создание функции main. Второй прыжок, когда я сделал функцию main. Реально сделал. Не просто я там pass написал, а вот я именно сделал ее. Раз — я снова прыгнул. Это был маленький. Вот этот прыжочек уже побольше. Я тут реально рассчитываю эти параметры, я тут раз — подпрыгнул, но я еще не приземлился. Мне надо сейчас прописать функции заглушки. Вот эти функции заглушки очень важно прописать до того, как я отойду от компьютера. Почему? Да потому что я как раз сейчас сконцентрировался. Была концентрация внимания, и у меня информация лежит в памяти. Мне надо ее сбросить туда, в частности, и документ-строки, может быть, вписать. Но я не буду их прописывать, тем не менее, давайте пропишем эти функции заглушки для background и house. Оп — все, сразу же у меня исчезает подчеркивание, у меня эти функции реализованы, синтаксический анализатор доволен. Можно запустить. Конечно, никакого домика, ничего я вообще не вижу, потому что у меня эти функции сейчас background и draw_house у меня лентяи, они ничего не делают. Чтобы я что-то увидел, мне нужно реальное содержимое туда положить. Давайте это быстренько сделаем для background. Я просто вставлю рисование неба и земли и сразу, как только я написал реальную реализацию одной из этих функций, пожалуйста, я уже вижу некий начальный пейзаж. Мне не надо думать, как теперь ее вызвать. Если бы я двигался снизу вверх, то даже если бы я придумал, а давайте оформим это как функцию, то я бы думал, а как теперь правильно вставить ее вызов. А тут, пожалуйста, эта функция актуальна, она насущна, ее ждали, уже была заготовка, заглушка. И вот как только реальное содержимое есть, она сразу начинает работать. Прекрасно. Что же давайте приступим к следующей крупной итерации, на которой, я уверен, вам абсолютно точно станет понятно, что же такое проектирование и движение сверху вниз. Итак, нарисовать домик. Я буду рисовать картинный, такой деревенский домик. Там основание, стены, крыша. Как мне это сделать? У меня три главные части у этой задачи. Моя задача состоит их трех подзадач. Поехали. draw_house_foundation, draw_house_walls. И что еще? draw_house_roof. Отлично. Естественно, что у каждой из этих функций должны быть параметры. Вот я об этих параметрах думаю. Так, мне надо рассчитать высоту основания, пусть ширина будет просто равна ширине этого обтягивающего прямоугольника, как бы полной ширины дома. Стены я сделал чуть уже, чем основание. Так, значит что еще? Мне нужно рассчитать высоту домика и рассчитать высоту крыши, причем так, чтобы у меня как раз полная высота была. То есть я эти параметры здесь вот прописываю, и этим функциям передаю эти параметры, чтобы они уже внутри не задумывались, а были вынуждены следовать собственному контракту и укладываться в собственные соответственно ширину и высоту. Я это дело им теперь пропишу. То есть я этим функциям теперь добавляю параметры. Отлично. И опять мой творческий порыв исчерпан, я выдыхаю, потому что я придумал, как рисовать дом, я все параметры рассчитал, может быть, я там на бумажке себе черкал и хочу выдохнуть. Могу ли я выдохнуть? Почти. Хотелось бы убежать и отдыхать сразу, но нет. Перед тем как я смогу отдыхать, я должен создать функции заглушки и даже по сути прописать документ-строки. Я не буду этого делать. Я просто создам эти функции-заглушки, давайте их быстренько бросим и проверим факт компилируемости программы. Ну не компилируемости, конечно, но факт ее запускаемости, консистентности. Итак, пожалуйста, ничего не изменилось, потому что у меня фактически все три функции, которые я тут вызываю, просто ничего не делают. Тем не менее, интерфейсы соблюдены, никаких ошибок, программа благополучно стартует, ожидает событий от мышки, все прекрасно. И теперь тоже, кстати, интересный момент: я мог бы бы сейчас рвануть и быстренько это дело прописывать. Но нет, я сейчас не так поступлю. Я скажу: хм, у меня тут как раз три функции. У каждой из этих функций прописан ее интерфейс. Я могу взять и объяснить трем своим друзьям, коллегам по работе, и сказать: «Слушай, ты пиши рисование основания, ты пиши рисование стен, ты пиши рисование крыши». Каждый прописывает свою собственную функцию, соблюдая контракт, и сливают в репозиторий. И у нас автоматически собирается программный код, который готов и работает. И каждый из них может выполнить свою работу в меру своей изощренности: сделать стену, состоящую из крипичиков, крышу с узорчиками, окна нарисовать. Это дело дальше можно реализовывать сколь угодно, детализировать, соблюдая контракт, конечно же. Давайте посмотрим на конечный результат. Я действительно окошки, пожалуй, добавлю. Вот это вот программный код. Что у нас получится? Давайте посмотрим на визуальный результат. Вот в итоге этот домик. Конечно, вы скажете, что подобный рисунок мог нарисовать какой-нибудь школьник. Да, это так. Но эта программа, во-первых, написана читабельно, она масштабируема, она прописана грамотно с точки зрения декомпозиции исходной задачи и разбиения ее на подзадачи. Понимаете? Вот в чем главная логика. Итого, пользуйтесь проектированием приложения сверху вниз, полный программный код вы найдете в материалах к этому видео. В следующем уроке мы поговорим с вами о тестировании. [ЗВУК] [БЕЗ_ЗВУКА]