Для регистрации на github НЕ используйте почту с российским доменом (например, yandex.ru), иначе после прохождения капчи вас вернет обратно на начальный этап регистрации.

Шаг 1: Генерация SSH-ключа (алгоритм ED25519)

  1. Откройте PowerShell.
  2. Сгенерируйте SSH-ключ: ssh-keygen -t ed25519 -C "your_email@example.com"

Ключи по умолчанию будут сохранены в C:\Users\YourUserName\.ssh\id_ed25519.

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

Шаг 2: Настройка файла known_hosts

  1. Создайте или откройте файл known_hosts: Откройте файл known_hosts в текстовом редакторе, который поддерживает UTF-8, например, в Notepad++ или Visual Studio Code. По умолчанию файл должен находиться в директории C:\Users\YourUserName\.ssh\.
  2. Используйте ssh-keyscan с преобразованием кодировки: Выполните команду в PowerShell, чтобы добавить fingerprint в known_hosts с корректной кодировкой:
ssh-keyscan github.com | Out-File -Encoding utf8 ~/.ssh/known_hosts

Эта команда добавляет fingerprint для GitHub и сохраняет его в файл known_hosts в правильной кодировке UTF-8.

Примечание: Если вы хотите добавить несколько хостов, выполните команду для каждого из них:

ssh-keyscan host1.com | Out-File -Append -Encoding utf8 ~/.ssh/known_hosts
ssh-keyscan host2.com | Out-File -Append -Encoding utf8 ~/.ssh/known_hosts

Шаг 3: Настройка файла config

  1. Создайте или отредактируйте файл config: Откройте ~/.ssh/config (обычно C:\Users\YourUserName\.ssh\config) и добавьте:
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519

Если добавляете другие хосты (например, для собственного git-сервера), создавайте отдельные секции Host для каждого из них.

Шаг 4: Добавление SSH-ключа в GitHub

  1. Скопируйте публичный ключ:
Get-Content ~/.ssh/id_ed25519.pub | Set-Clipboard
  1. Добавьте ключ на GitHub:

Шаг 5: Тестирование подключения

  1. Проверьте подключение:
ssh -T git@github.com

Успешное подключение отобразит сообщение: Hi username! You've successfully authenticated, but GitHub does not provide shell access.

Рабочий план дисциплины

Часть 1: Введение в основы

Лабораторная работа 1: Основы HTML

  • Тема: Создание веб-страницы визитки
  • Задание: Создать личный сайт-визитку. Использовать HTML-теги для структуры страницы: заголовки, параграфы, изображения, списки и ссылки.
  • Разделы сайта: "О себе", "Навыки", "Образование", "Контакты".

Требования:

  • Применить теги: <h1>, <p>, <ul>, <img>, <a>.
  • Использовать таблицу для раздела "Навыки" с категориями (например, технические и управленческие навыки).
  • Включить атрибуты для выравнивания изображений и добавления ссылок на социальные сети.

Лабораторная работа 2: Введение в CSS и создание навигации

  • Тема: Стилизация сайта-визитки и создание навигационной панели
  • Задание: Стилизовать сайт-визитку с использованием CSS. Создать навигационное меню (navbar) для перехода между разделами.

Требования:

  • Подключить внешний файл стилей.
  • Использовать классы и идентификаторы для стилизации секций сайта.
  • Реализовать навигационную панель с помощью тегов <nav>, <ul>, <li> и настроить ссылки на внутренние разделы сайта.

Лабораторная работа 3: Введение в JavaScript и формы

  • Тема: Добавление формы обратной связи и обработка данных с использованием JavaScript
  • Задание: Реализовать форму обратной связи на сайте, где пользователь может ввести имя, email и сообщение.

Требования:

  • Использовать JavaScript для валидации данных формы.
  • Проверить наличие заполненных полей и корректность введённых данных.
  • Реализовать реакцию на успешную или неуспешную отправку формы:
    • Успешная отправка: сообщение "Спасибо за обратную связь, [имя]! С вами свяжутся в ближайшее время"
    • Ошибка: предупреждение "Пожалуйста, введите корректный email"

Лабораторная работа 4: Расширенный CSS, Позиционирование

  • Тема: Углубленное изучение CSS — позиционирование, контейнеры, медиазапросы
  • Задание: Добавить к сайту сложные CSS-правила: позиционирование (relative, absolute), использование контейнеров (flex, grid, inline-block), медиазапросы для адаптивности.

Требования:

  • Стилизовать сайт для разных разрешений экранов с помощью медиазапросов.
  • Использовать flex и grid для создания адаптивных макетов.
  • Позиционировать элементы с помощью свойств relative и absolute.
  • Применить нововведения CSS3 и правила для вложенных селекторов.

Часть 2: Bootstrap 5 и повышение скорости загрузки страницы

Лабораторная работа 5: Введение в Bootstrap 5

  • Тема: Основы Bootstrap 5 и сеточная система
  • Задание: Создать страницу портфолио с использованием сеточной системы Bootstrap.

Требования:

  • Применить сеточную систему Bootstrap для адаптации макета под разные экраны.
  • Использовать контейнеры для организации контента.
  • Добавить стилизованные кнопки, формы и элементы интерфейса с использованием Bootstrap-компонентов.

Лабораторная работа 6: Оптимизация сайта

  • Тема: Адаптивная версия сайта для мобильных устройств и оптимизация загрузки ресурсов
  • Задание: Оптимизировать сайт для мобильных устройств и планшетов.

Требования:

  • Использовать медиазапросы для адаптации сайта под мобильные устройства.
  • Применить формат изображений .webp для оптимизации загрузки.
  • Сравнить скорость загрузки шрифтов через CDN и локальное подключение с помощью @font-face.
  • Ознакомиться с тегом <link rel="preload"> для предварительной загрузки ресурсов.

Проанализировать другие возможные оптимизации: minification CSS/JS, lazy-loading изображений, сжатие файлов.

Часть 3: Работа с DOM и поисковая оптимизация веб-страниц

Лабораторная работа 7: Работа с DOM и динамическое изменение контента

  • Тема: Динамическое добавление изображений с использованием API
  • Задание: Реализовать сайт с галереей изображений с использованием TheCatApiService.

Требования:

  • Использовать API для получения изображений и добавления их на страницу.
  • Реализовать панель управления для добавления картинок.
  • При клике на изображение должен запускаться слайдер с полноразмерным просмотром.

Добавить скелетон-лоадинг для визуализации загрузки контента.

Лабораторная работа 8: Модальные окна

  • Тема: Создание модальных окон двумя способами
  • Задание: Реализовать два варианта создания модальных окон на сайте:
    1. С использованием классического CSS и JavaScript.
    2. С использованием тега <dialog>.

Требования:

  • Создать модальное окно с использованием стилей CSS и JavaScript для его управления.
  • Реализовать второй вариант с помощью тега <dialog>.
  • Оба окна должны поддерживать закрытие по кнопке или клику вне модального окна.
  • Сравнить подходы и сделать выводы.

Лабораторная работа 9: Поисковая оптимизация и настройка отображения в соц. сетях

  • Тема: Оптимизация страницы для поисковых систем и социальных сетей
  • Задание: Настроить страницу для улучшения SEO и правильного отображения при отправке ссылки в соц. сети.

Требования:

  • Добавить мета-теги, связанные с SEO и социальными сетями (например, Open Graph и Twitter Cards).
  • Настроить заголовки, описания, ключевые слова и изображения для предпросмотра в социальных сетях.
  • Настроить файл robots.txt и sitemap.xml для правильной индексации сайта.
  • Добавить иконку для сайта.
  • Настроить предпросмотр страницы с помощью Open Graph тегов.

Ознакомиться с Яндекс Метрикой и Google Search Console.

Часть 4: Закрепление знаний

Лабораторная работа 10: Закрепление изученного материала

  • Тема: Создание полноценного проекта с использованием всех изученных технологий
  • Задание: Разработать многостраничный веб-сайт на основе полученных знаний.

Требования:

  • Сайт должен быть полностью адаптивным, с использованием Bootstrap 5.
  • Реализовать динамическое добавление контента через API.
  • Добавить форму обратной связи с валидацией и модальными окнами.
  • Произвести оптимизацию загрузки ресурсов и проверить корректность отображения сайта на мобильных устройствах и планшетах.

📘 Установка и настройка Visual Studio Code для веб-разработки на Windows

1. 🛠 Скачивание и установка Visual Studio Code

  1. Перейдите на официальный сайт Visual Studio Code.
  2. Нажмите на кнопку Download for Windows.
  3. Откройте загруженный установочный файл и следуйте инструкциям на экране:
    • Примите условия лицензии.
    • Выберите папку для установки.
    • Опционально: добавьте VS Code в контекстное меню Windows (рекомендуется).
    • Нажмите Установить.
  4. После установки запустите VS Code.

VS Code

2. 🧩 Установка рекомендуемых расширений

Чтобы сделать работу с VS Code еще более удобной для веб-разработки, рекомендуется установить следующие расширения (не обязательно, но сделает вашу жизнь проще, попробуйте):

2.1. 🛤 Path Intellisense

Это расширение от Christian Kohler автоматически подсказывает пути к файлам и папкам при их написании в вашем коде. Например, при написании пути к изображению оно предложит автозаполнение на основе структуры вашего проекта.

2.2. 🌐 Live Server

Live Server запускает локальный сервер прямо из вашего проекта и автоматически обновляет браузер при изменении файлов HTML, CSS или JavaScript. Это крайне удобно для быстрого тестирования и просмотра изменений в реальном времени.

2.3. 🎨 Catppuccin Theme

Catppuccin — приятная тема, созданная для разработчиков, c приятной палитру цветов, которая снижает нагрузку на глаза и помогает сосредоточиться на работе.

2.4. 🖼 Catppuccin Perfect Icons

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

Список расширений не окончательный, вы всегда можете сами зайти в магазин расширений и установить то, которое сделает вашу работу быстрее и удобнее. Например, className Completion in CSS, formate: CSS/LESS/SCSS formatter и т.д.

3. 🖥 Настройка среды разработки

3.1. ⚙ Настройка Live Server

После установки Live Server:

  1. Откройте ваш HTML файл.
  2. Кликните правой кнопкой мыши по файлу и выберите опцию Open with Live Server.
  3. Ваш браузер автоматически откроется с локальной версией проекта. Все изменения в файлах будут моментально отображаться.

3.2. 🔄 Настройка автосохранения

Чтобы не терять изменения, активируйте функцию автосохранения:

  1. Откройте Settings (Ctrl + ,).
  2. В поле поиска введите Auto Save.
  3. Выберите опцию After Delay или On Window Change для автоматического сохранения файлов.

4. 🎨 Персонализация интерфейса

  • После установки Catppuccin Theme перейдите в Settings и выберите тему Catppuccin в разделе Color Theme.
  • В разделе иконок выберите стиль иконок Catppuccin Perfect Icons.

5. 📦 Создание первого веб-проекта

Теперь, когда ваша среда настроена, создайте новый проект:

  1. Создайте папку на вашем компьютере и откройте ее в VS Code.
  2. Создайте файл index.html и напишите следующий базовый код:
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Мой первый проект</title>
</head>
<body>
    <h1>Привет, мир!</h1>
</body>
</html>
  1. Запустите Live Server и откройте проект в браузере.

🎯 Полезные советы

  • Используйте сочетание клавиш Ctrl + P для быстрого поиска и открытия файлов.
  • Для того, чтобы быстро закомментировать и раскомментировать строчку используйте сочетание клавиш Ctrl + /.
  • Для глобального поиска текста во всех файлах проекта сразу можно использовать комбинацию Ctrl + Shift + F.
  • Установите дополнительные плагины для поддержки Emmet и работы с Git.
  • Регулярно обновляйте расширения для получения новых функций и исправлений.

Теоретическая справка

Основные теги, которые используются в HTML

  1. <h1> - <h6>: Заголовки, где <h1> — это заголовок первого уровня (самый крупный), а <h6> — заголовок шестого уровня (самый мелкий).
<h1>Основной заголовок</h1>
<h2>Подзаголовок 1</h2>
<h3>Подзаголовок 2</h3>
  1. <p>: Тег для создания абзацев текста.
<p>Это мой первый параграф.</p>
<p>Это второй параграф, который описывает больше деталей.</p>
  1. <img>: Используется для вставки изображений. Основные атрибуты:
    • src — путь к изображению.
    • alt — альтернативный текст, который будет отображаться, если изображение не загрузилось.
<img src="images/photo.jpg" alt="Мое фото" width="200">
  1. <ul> и <li>: Ненумерованный список (unordered list). Тег <ul> создаёт список, а <li> определяет элементы списка. Для создания нумерованного списка используется тег <ol>.
<ul>
	<li>Первый пункт</li>
	<li>Второй пункт</li>
	<li>Третий пункт</li>
</ul>
  1. <a>: Тег для создания гиперссылок. Основной атрибут href указывает URL, куда будет направлен пользователь при нажатии на ссылку.
<a href="https://www.example.com" target="_blank">Посетить мой сайт</a>
  1. <table>: Используется для создания таблиц. Содержит строки <tr>, а каждая строка — столбцы <td>.
<table border="1">
	<tr>
		<th>Категория</th>
		<th>Описание</th>
	</tr>
	<tr>
		<td>Технические навыки</td>
		<td>HTML, CSS, JavaScript</td>
	</tr>
	<tr>
		<td>Управленческие навыки</td>
		<td>Коммуникация, тайм-менеджмент</td>
	</tr>
</table>

Создание файла index.html

Основной файл HTML имеет следующую базовую структуру:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Сайт</title>
</head>
<body>
	<!-- Код сайта -->
</body>
</html>

Описание основных тегов

  • <!DOCTYPE html>: Определяет тип документа как HTML5. Этот элемент нужен для того, чтобы браузер понял, что ему предстоит работать с HTML5.
  • <html lang="ru">: Корневой элемент документа. Атрибут lang="en" определяет основной язык страницы как английский.
  • <head>: Этот тег содержит метаданные о странице: информацию, которая не видна напрямую пользователю, но необходима для правильной работы страницы.
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Моя визитка</title>
</head>
  • <meta charset="UTF-8">: Устанавливает кодировку символов для страницы, чтобы поддерживать различные языки, в том числе кириллицу.
  • <meta name="viewport" content="width=device-width, initial-scale=1.0">: Эта строка позволяет странице быть адаптивной, то есть корректно отображаться на мобильных устройствах.
  • <title>: Устанавливает название страницы, которое отображается на вкладке браузера.
  • <body>: Основное содержимое страницы, видимое пользователям, располагается между открывающим и закрывающим тегом <body>. Пример:
<body>
	<h1>Привет! Это моя веб-страница.</h1>
	<p>Здесь вы узнаете обо мне и моих навыках.</p>
</body>

Базовая структура проекта

Для организации файлов и ресурсов проекта рекомендуется использовать следующую структуру директорий и файлов: `

assets/
	css/
	js/
	images/
	fonts/
index.html
  • Папка assets/: Хранит ресурсы, используемые на сайте, такие как CSS, JavaScript, изображения и шрифты.
    • Папка css/: Содержит файлы стилей, которые управляют внешним видом веб-страницы.
    • Папка js/: Содержит JavaScript-файлы, которые добавляют интерактивность на страницу.
    • Папка images/: Хранит изображения, используемые на веб-странице.
    • Папка fonts/: Используется для шрифтов, если они загружаются локально.
  • index.html: Главный файл веб-страницы, который содержит разметку страницы и ссылки на внешние ресурсы (CSS, JS).

Практическое задание: Создание веб-страницы визитки

Тема: Создание личного сайта-визитки.
Цель: Освоить базовые HTML-теги и создать веб-страницу, которая будет представлять информацию о вас: ваши навыки, образование и контакты.
Задание. Создайте личный сайт-визитку с разделами:

  1. О себе — краткое описание вашей личности или биографии.
  2. Навыки — перечень ваших ключевых навыков.
  3. Образование — список учебных заведений или курсов, которые вы окончили.
  4. Контакты — информация о ваших контактных данных и ссылки на социальные сети.

Требования:

  1. Использовать теги для организации страницы:
    • Заголовки: <h1> и <h2> для создания разделов.
    • Параграфы: <p> для текста.
    • Изображения: <img> для вставки фотографии или логотипа.
    • Списки: <ul> и <li> для организации информации в виде списка.
    • Ссылки: <a> для гиперссылок на внешние ресурсы.
  2. В разделе "Навыки" необходимо использовать таблицу для структурирования информации о ваших технических и управленческих навыках. Таблица должна иметь две колонки: "Категория" и "Навыки".
  3. Добавьте изображение на страницу с выравниванием по центру и альтернативным текстом, если изображение не загрузится.
  4. Добавьте ссылки на социальные сети.

Пример структуры HTML-документа

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Моя визитка</title>
</head>
<body>
    <h1>О себе</h1>
    <p>Привет! Я веб-разработчик с опытом работы в создании современных и адаптивных веб-сайтов.</p>

    <h2>Навыки</h2>
    <table border="1">
        <tr>
            <th>Категория</th>
            <th>Навыки</th>
        </tr>
        <tr>
            <td>Технические навыки</td>
            <td>HTML, CSS, JavaScript</td>
        </tr>
        <tr>
            <td>Управленческие навыки</td>
            <td>Управление проектами, коммуникации</td>
        </tr>
    </table>

    <h2>Образование</h2>
    <ul>
        <li>Университет XYZ, Бакалавр в области информатики</li>
        <li>Курсы веб-разработки на платформе ABC</li>
    </ul>

    <h2>Контакты</h2>
    <p>Email: myemail@example.com</p>
    <p>Социальные сети: 
        <a href="https://www.linkedin.com" target="_blank">LinkedIn</a>, 
        <a href="https://www.github.com" target="_blank">GitHub</a>
    </p>
</body>
</html>

Теоретическая справка

Основы CSS и его роль

Cascading Style Sheets (CSS) — это язык стилей, который используется для описания внешнего вида HTML-документов. С помощью CSS можно изменять цвет текста, фон, размеры элементов, отступы, рамки и многое другое. CSS помогает отделить визуальную часть сайта от его структуры.

Примечание: CSS поддерживает различные виды единиц измерения, переменные и медиа-запросы для адаптации сайта под разные экраны.


Где могут указываться стили?

Существует несколько способов добавления стилей на веб-страницу:

  1. Внутри тегов с помощью атрибута style: Этот метод позволяет добавлять стили напрямую к HTML-элементам. Пример:

    <p style="color: red; font-size: 20px;">Это текст с встроенными стилями</p>
    
  2. В секции <head> с использованием тега <style>: Этот метод применяется для определения стилей в блоке <style> в HTML-документе.

     <head>
         ...
         <style>
             p {
                 color: red;
                 font-size: 20px;
             }
         </style>
     <head>
    
  3. Подключение внешнего файла стилей: Наиболее удобный и распространённый способ. Внешний файл подключается через тег <link> в секции <head>.

    <link rel="stylesheet" href="styles.css">
    

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


Структура CSS-правил

Каждое правило в CSS состоит из двух частей: селектора и декларации. Селектор указывает элемент, а декларация описывает стилизацию.

Пример CSS-правила:

h1 {
    color: blue;
    font-size: 24px;
    text-align: center;
}

Основные CSS-свойства

Цвет текста (color)

Атрибут color определяет цвет текста элемента. Цвет может быть задан несколькими способами:

  1. HEX (шестнадцатеричный код): color: #ff5733;
  2. RGB (Red, Green, Blue): color: rgb(255, 87, 51);
  3. RGBA (с прозрачностью): color: rgba(255, 87, 51, 0.5);
  4. Ключевые названия цветов: color: blue;

Важно: Использование RGBA позволяет задать прозрачность элемента, что полезно для эффектов наложения.


Фон элемента (background)

Атрибут background позволяет задавать различные параметры фона для элемента: цвет, изображение, позиционирование и повторение изображения.

Пример использования:

background: url('background.jpg') no-repeat center center;
background-color: #f0f0f0; /* Цвет фона */

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


Отступы и поля

  • margin — внешний отступ:
h1 { margin: 20px; }
  • padding — внутренний отступ:
p { padding: 10px; }

Общий принцип расположения отступов относительно контента представлен на изображении ниже: Визуализация отступов


Шрифты и стили текста

  • font-family: задаёт семейство шрифтов.
  • font-size: размер текста.
  • font-weight: толщина текста.
  • line-height: высота строки.

Пример:

body {
    font-family: Arial, sans-serif;
    font-size: 16px;
    line-height: 1.6;
}

Состояния элементов и ссылки

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

  1. hover — состояние при наведении курсора.
  2. visited — состояние после посещения.
  3. active — состояние при нажатии.
  4. focus — состояние при фокусировке на элементе.

Пример для ссылок:

a:hover { color: red; }
a:visited { color: purple; }

Примечание: Состояния элементов позволяют стилизовать их в зависимости от действий пользователя.


Типы единиц измерения в CSS

  1. Абсолютные (px):
div { width: 200px; }
  1. Относительные (em, rem):
p { font-size: 1.5em; }
Почему чаще используются относительные единицы измерения (em и rem)?

Относительные единицы измерения, такие как em и rem, становятся предпочтительными по нескольким причинам:

  1. Адаптивность: Относительные единицы масштабируются относительно родительских элементов (em) или корневого элемента (rem), что делает их удобными для создания адаптивных макетов.
  2. Поддержка доступности: Пользователи могут изменять размер текста в браузере, и относительные единицы лучше реагируют на такие изменения.
  3. Гибкость: С помощью относительных единиц можно легко изменить размеры элементов при масштабировании, сохраняя пропорции.

Пример использования:

p {
    font-size: 1.5em; /* Размер текста относительно родителя */
}

h1 {
    font-size: 2rem; /* Размер относительно корневого элемента */
}

Примечание: rem используется чаще для определения глобальных размеров, а em — для локальной настройки шрифтов и отступов.

Навигационные панели

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

Пример структуры навигации:

<nav>
    <ul>
        <li><a href="#about">О себе</a></li>
        <li><a href="#skills">Навыки</a></li>
        <li><a href="#education">Образование</a></li>
        <li><a href="#contacts">Контакты</a></li>
    </ul>
</nav>

Практическое задание: Стилизация сайта и создание навигации

Тема: Стилизация сайта с использованием CSS и создание навигационного меню
Цель: Освоить основные свойства CSS для стилизации веб-страницы и создать удобное навигационное меню.
Задание:

  1. Подключить внешний CSS-файл к HTML-документу.
  2. Стилизовать следующие элементы:
    • Заголовки: изменить цвет и размер.
    • Абзацы: задать отступы и изменить цвет текста.
  3. Применить padding и margin для улучшения визуального восприятия элементов.

Пример сайта с подключенными стилями и навигационной панелью:

Примечание: Ознакомтесь со способами изменения положения контента на странице. Например, один из способов центрировать контент - использовать margin: 0 auto;. Таким образом мы установим внешний отступ сверху и снизу равным 0, а по бокам все доступное пространство поровну распределится между отступом слева и справа.

Теоретическая справка

Что такое JavaScript?

JavaScript (JS) — это язык программирования, исполняемый на стороне клиента (в браузере). Он позволяет добавлять интерактивность на веб-страницы, управлять поведением элементов, выполнять операции с данными, отправлять запросы на сервер и многое другое. JavaScript — интерпретируемый язык, то есть он не требует предварительной компиляции и исполняется непосредственно в браузере.

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

Переменные и типы данных в JavaScript

В JavaScript можно объявлять переменные с помощью ключевых слов var, let и const. Типы данных, с которыми работают переменные, можно разделить на примитивные и сложные.

Примитивные типы данных:

  • Числа (Number) — могут быть целыми или дробными:
let x = 10;
let pi = 3.14;
  • Строки (String) — используются для хранения текста:
let greeting = "Привет, мир!";
  • Булевы значения (Boolean) — логический тип данных с двумя возможными значениями: true или false:
let isAdmin = false;
  • Undefined — переменная, которой не было присвоено значение:
let user;
  • Null — явное отсутствие значения:
let emptyValue = null;
  • Symbol — уникальные и неизменяемые значения, полезные для создания уникальных идентификаторов.

Сложные типы данных:

  • Объекты (Object) — структуры, которые могут хранить множество значений в виде пар "ключ-значение":
let person = {
    name: "Иван",
    age: 25
};
  • Массивы (Array) — это упорядоченные коллекции данных:
let fruits = ["яблоко", "банан", "вишня"];

Пример работы с типами данных:

let number = 5;
let text = "Привет!";
let isValid = true;
let fruits = ["яблоко", "банан"];

number = number + 10; // Изменение значения переменной
text = text + " Как дела?"; // Конкатенация строк

console.log(number); // 15
console.log(text); // "Привет! Как дела?"
console.log(fruits[1]); // "банан"

Функции

Функции — это блоки кода, которые можно вызывать для выполнения определённой задачи. Они могут принимать параметры и возвращать значения.

Пример функции:

function calculateSum(a, b) {
    return a + b;
}

let result = calculateSum(5, 3); // 8

С приходом ES6 функции можно создавать с помощью стрелочных функций:

Пример стрелочной функции:

const multiply = (a, b) => a * b;

console.log(multiply(2, 4)); // 8

Нововведения в ES6

С введением ECMAScript 6 (ES6) JavaScript получил множество новых удобных функций и возможностей:

  • Шаблонные строки — позволяют использовать интерполяцию переменных:
let name = "Иван";
console.log(`Привет, ${name}!`);
  • Деструктуризация — упрощает доступ к данным массивов и объектов:
let [a, b] = [1, 2];
let {name, age} = {name: "Иван", age: 25};
  • Операторы "let" и "const" — для объявления переменных с блочной областью видимости:
let count = 10; // Переменная, которую можно изменить
const PI = 3.14; // Константа, значение которой изменить нельзя
  • Модули — возможность разделять код на отдельные файлы и импортировать их:
export const greet = (name) => `Привет, ${name}!`;
import { greet } from './greet.js';
  • Классы — синтаксический сахар для создания объектов:
class Animal {
    constructor(name) {
        this.name = name;
    }

    speak() {
        console.log(`${this.name} издаёт звук.`);
    }
}

let dog = new Animal("Собака");
dog.speak(); // "Собака издаёт звук."

Document Object Model (DOM)

DOM — это представление HTML-документа в виде дерева объектов, где каждый элемент страницы является узлом. JavaScript позволяет взаимодействовать с DOM для динамического изменения содержимого страницы, изменения стилей, добавления или удаления элементов.

Основные методы работы с DOM:

  • Поиск элементов:

    • document.getElementById("id") — поиск по идентификатору.
    • document.querySelector(".class") — поиск по селектору.

    Пример:

    let element = document.getElementById("header");
    
  • Изменение содержимого:

    • element.innerText — изменяет текст внутри элемента.
    • element.innerHTML — изменяет HTML внутри элемента.

    Пример:

    document.getElementById("header").innerText = "Новый заголовок";
    
  • Изменение стилей:

    • element.style.property — изменяет CSS-свойства элемента.

    Пример:

    document.getElementById("header").style.color = "red";
    
  • Добавление и удаление элементов:

    • document.createElement("div") — создание нового элемента.
    • parent.appendChild(child) — добавление элемента в DOM.

    Пример:

    let newDiv = document.createElement("div");
    newDiv.innerText = "Новый элемент";
    document.body.appendChild(newDiv);
    
  • Обработка событий:

    Использование addEventListener() для обработки событий (например, нажатие кнопки).

    Пример:

    document.getElementById("button").addEventListener("click", function() {
        alert("Кнопка нажата!");
    });
    

Формы в HTML

Форма — это элемент HTML, который позволяет пользователям вводить и отправлять данные на сервер для обработки. Основные элементы формы включают в себя текстовые поля, кнопки, переключатели и другие элементы управления.

Пример формы:

<form action="/submit" method="POST">
    <label for="name">Имя:</label>
    <input type="text" id="name" name="name"><br><br>

    <label for="email">Email:</label>
    <input type="email" id="email" name="email"><br><br>

    <button type="submit">Отправить</button>
</form>
  • <form> — контейнер для элементов формы.
  • <input> — элементы для ввода данных (текст, email, пароль и т.д.).
  • <textarea> — многострочный текстовый ввод.
  • <button> — кнопка для отправки формы.

Обработка данных формы

JavaScript позволяет перехватывать отправку формы и обрабатывать введённые данные до того, как они будут отправлены на сервер.

Пример валидации формы с JavaScript:

document.querySelector("form").addEventListener("submit", function(event) {
    event.preventDefault(); // Отключаем стандартную отправку формы

    let name = document.getElementById("name").value;
    let email = document.getElementById("email").value;

    if (name === "" || email === "") {
        alert("Пожалуйста, заполните все поля!");
    } else if (!email.includes("@")) {
        alert("Введите корректный email!");
    } else {
        alert("Форма успешно отправлена!");
    }
});

Практическое задание: Реализация формы обратной связи с валидацией

Цель: Научиться работать с формами и данными, введёнными пользователем. Освоить основные методы JavaScript для проверки данных формы.
Задание:

  1. Создайте форму с полями для ввода имени, email и сообщения.
  2. Используйте JavaScript для проверки, что все поля заполнены корректно:
    • Имя не должно быть пустым.
    • Email должен быть корректным.
    • Сообщение должно содержать хотя бы 10 символов.
  3. При успешной отправке формы выведите сообщение об успешной отправке. При ошибке выведите предупреждение с указанием, что необходимо исправить.

Пример веб-страницы с валидацией формы при помощи JavaScript:

Самостоятельное задание

Часть 1: Расширенная форма с валидацией и динамическими элементами

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

Форма опроса

Создайте HTML-форму для опроса, которая включает следующие элементы:

  • Поле для ввода имени.
  • Поле для ввода возраста.
  • Переключатели (radio buttons) для выбора пола.
  • Чекбоксы для указания интересов (например, спорт, музыка, кино).
  • Многострочное текстовое поле для комментариев с отображением текущего количества введённых символов и лимитом в 200 символов.
  • Кнопка для динамического добавления новых полей для ввода интересов.

Валидация формы

  • Имя не должно быть пустым.
  • Возраст должен быть числом больше 0 и не старше 120.
  • Пользователь должен выбрать хотя бы один интерес.
  • Комментарий не должен превышать 200 символов.
  • Валидация новых полей, добавленных динамически.

Вывод данных формы

После успешной валидации формы выведите введённые данные на экран в структурированном виде:

  • Имя
  • Возраст
  • Пол
  • Интересы
  • Комментарии
Добавьте кнопку для динамического добавления полей для ввода новых интересов без перезагрузки страницы.

Один из вариантов реализации:

document.getElementById("addInterest").addEventListener("click", function() {
    let newInterest = document.createElement("input");
    newInterest.setAttribute("type", "text");
    newInterest.setAttribute("name", "interest");
    newInterest.setAttribute("placeholder", "Новый интерес");
    
    let interestList = document.getElementById("interestList");
    interestList.appendChild(newInterest);
});

Подсчёт символов

Реализуйте подсчёт символов в реальном времени для текстового поля комментариев и покажите пользователю, сколько символов осталось до лимита.

Часть 2: Работа с элементами страницы и манипуляция DOM

Создание интерфейса для управления списком задач (to-do list), который позволяет добавлять, удалять и отмечать задачи.

Создание списка задач

Создайте интерфейс для управления задачами (to-do list). На странице должно быть:

  • Поле для ввода новой задачи.
  • Кнопка для добавления задачи в список.
  • Динамически обновляющийся список задач.

Перечень взаимодействий, которые необходимо реализовать:

  • Удаление задачи из списка.
  • Отметки задачи как выполненной. При этом стиль задачи должен меняться (например, зачеркивание текста или изменение фона).
  • Кнопка для фильтрации задач, чтобы пользователь мог скрывать выполненные задачи и показывать только оставшиеся.
Вариант JS кода для создания списка задач
document.getElementById("addTask").addEventListener("click", function() {
    let taskInput = document.getElementById("taskInput").value;
    if (taskInput === "") return;
    
    let taskList = document.getElementById("taskList");

    let taskItem = document.createElement("li");
    taskItem.innerText = taskInput;

    // Добавление кнопки удаления задачи
    let deleteButton = document.createElement("button");
    deleteButton.innerText = "Удалить";
    deleteButton.addEventListener("click", function() {
        taskList.removeChild(taskItem);
    });

    taskItem.appendChild(deleteButton);
    taskList.appendChild(taskItem);
    
    // Очистка поля ввода
    document.getElementById("taskInput").value = "";
});

Визуализация логики работы: TO-DO List

Анимация

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

Задачи на дополнительные баллы

  1. Создайте выпадающее меню. Реализуйте выпадающее меню с использованием JavaScript, которое отображается при наведении на элемент и исчезает при отведении курсора.
  2. Подключите локальное хранилище. Добавьте сохранение списка задач в LocalStorage, чтобы после перезагрузки страницы задачи оставались на месте.

Теоретическая справка

С тем что такое CSS и с примитивными принципами его работы мы знакомились в Лабороторной №2

Позиционирование элементов

Позиционирование в CSS — это механизм, который позволяет точно указывать, где элементы будут располагаться на странице.

В CSS позиционирование управляет расположением элементов относительно других элементов или родительских контейнеров. Свойство position задаёт способ позиционирования элемента на странице, а свойства top, right, bottom и left определяют точное смещение элементов на странице.

Синтаксис

position: static;
position: relative;
position: absolute;
position: fixed;
position: sticky;

/* Глобальные значения */
position: inherit;
position: initial;
position: revert;
position: unset;

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


Static (Статическое позиционирование)

Значение по умолчанию. Элементы, у которых установлено это значение, располагаются в потоке документа по мере их появления в HTML-разметке. Свойства top, left, right, и bottom не применяются.

Особенности:

  • Элемент находится в нормальном потоке документа.
  • Свойства смещения не оказывают влияния.
  • Не создаёт новый контекст наложения (stacking context).

Пример:

В данном примере блок с классом .static будет располагаться в потоке документа на своём обычном месте.


Relative (Относительное позиционирование)

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

Особенности:

  • Элемент остаётся на своём месте в потоке.
  • Свойства top, right, bottom, и left смещают элемент относительно его исходного положения.
  • Создаёт новый контекст наложения, если установлен z-index.

Пример:

В этом примере блок с классом .relative смещён вниз на 20px и вправо на 30px, при этом место под ним остаётся неизменным.


Absolute (Абсолютное позиционирование)

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

Особенности:

  • Элемент удаляется из нормального потока.
  • Позиционируется относительно ближайшего позиционированного родителя.
  • Создаёт новый контекст наложения, если установлен z-index.

Пример:

Здесь элемент с классом .absolute будет позиционироваться относительно его родителя с классом .relative и смещён на 50px вниз и на 20px вправо. Родитель остаётся в потоке, но дочерний элемент — нет.


Fixed (Фиксированное позиционирование)

Фиксированное позиционирование удаляет элемент из потока и закрепляет его относительно окна браузера. Элемент остаётся на одном месте на экране при прокрутке страницы.

Особенности:

  • Элемент позиционируется относительно окна браузера.
  • Не изменяет своё положение при прокрутке.
  • Создаёт новый контекст наложения, если установлен z-index.

Пример:

Элемент с классом .fixed будет закреплён в правом верхнем углу и останется на одном месте при прокрутке страницы.


Sticky (Липкое позиционирование)

Липкое позиционирование совмещает поведение статического и фиксированного позиционирования. Элемент сначала ведёт себя как обычный, но при прокрутке "залипает" на экране, если достигается определённая точка.

Особенности:

  • Элемент ведёт себя как обычный, пока не достигнет порога прокрутки.
  • После достижения порога элемент фиксируется в пределах родителя или экрана.
  • Создаёт новый контекст наложения, если установлен z-index.

Пример:

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


Глобальные значения

inherit (Наследование)

Элемент наследует значение свойства position от своего родителя.

.child {
    position: inherit;
}

initial (Инициализация)

Элемент возвращается к начальному значению свойства, как если бы оно не было установлено.

.child {
    position: initial;
}

revert (Отмена изменений)

Элемент возвращает значение свойства к тому, что оно было бы, если бы не было изменений.

.child {
    position: revert;
}

unset (Сброс)

Элемент получает либо наследуемое значение, если оно наследуемое, либо начальное значение.

.child {
    position: unset;
}

Контейнеры: Flexbox и Grid

Flexbox

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

Синтаксис

.container {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

Основные свойства Flexbox:

  • display: flex — активирует flex-контейнер.
  • flex-direction — задает направление главной оси (строка или столбец).
  • justify-content — управляет выравниванием элементов по главной оси.
  • align-items — выравнивает элементы вдоль поперечной оси.

Пример использования Flexbox:

Перед тем как приступить к практической части настоятельно рекомендую всем ознакомиться с интерактивной шпаргалкой, в которой представлены все основные свойства использующиеся в Flexbox. Ссылка на шпаргалку: Типичный верстальщик: Шпаргалка по Flexbox CSS.

Для более подробного ознакомления с контейнерами рекомендуется на выбор пройти одну из интерактивных игр:

  • Более интрересное визуальное оформление, больше информации. Единственный нюанс, что поддерживается только английский язык. Ссылка: Flex Box Adventure.

Flex Box Adventure

  • Чуть более упрощенный вариант. Есть поддержка русского языка. Ссылка: Flexbox Froggy.

Flexbox Froggy

Grid

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

Синтаксис

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
}

Основные свойства Grid:

  • display: grid — активирует Grid-контейнер.
  • grid-template-columns — определяет количество и ширину колонок.
  • grid-template-rows — определяет количество и высоту строк.
  • gap — управляет расстоянием между элементами Grid.

Пример использования Grid:

Интерактивная шпаргалка от тех же авторов, что и по Flexbox: Типичный верстальщик: Шпаргалка по Grid CSS.

Для изучения Grid также есть интерактивные игры, которые позволяют глубже понять и закрепить принципы позиционирования контента с её использованием:

  • Ссылка на более интересный и обширный вариант на английском языке: Grid Attack.

Grid Attack

  • Вариант на русском языке от создателей Flexbox Froggy: Grid Garden.

Grid Garden


Анимации в CSS

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

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

Основы CSS-transition

Транзишны позволяют анимировать изменение свойств элементов, например, перемещение или изменение цвета.

Пример

При наведении курсора кнопка плавно смещается вверх за 250 миллисекунд.

Синтаксис

transition: <свойство> <длительность> <функция-времени> <задержка>;
  • Свойство – свойство, которое изменяется.
  • Длительность – время выполнения анимации (в мс).
  • Функция-времени – характер анимации (например, linear, ease-in).
  • Задержка – время до начала анимации.

Функции времени

Функции времени управляют тем, как изменяется свойство:

  • linear – равномерное изменение.

    transition-timing-function: linear;
    
  • ease – плавное ускорение в начале и замедление в конце (по умолчанию).

  • ease-in – медленное начало, быстрое завершение.

    transition-timing-function: ease-in;
    
  • ease-out – быстрое начало, медленное завершение.

    transition-timing-function: ease-out;
    
  • ease-in-out – комбинация ease-in и ease-out.

    transition-timing-function: ease-in-out;
    
  • Кастомная кривая Безье для создания уникальных анимаций:

    transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);
    

Производительность анимаций

Важно следить за производительностью, особенно при анимации свойств, влияющих на расположение элементов (height, width). Они могут замедлять работу интерфейса.

Советы:

  1. Анимируйте свойства, которые минимально влияют на другие элементы, например, transform или opacity.
  2. Тестируйте анимации на слабых устройствах.

Можно анимировать сразу несколько свойств:

.btn {
  transition: transform 250ms, opacity 400ms;
}

Учет предпочтений пользователей

Для пользователей с чувствительностью к движениям рекомендуется учитывать системные настройки и отключать анимации, если включен режим prefers-reduced-motion:

@media (prefers-reduced-motion: reduce) {
  .btn {
    transition: none;
  }
}

Пример комплексной анимации

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

Более сложные и комплексные анимации можно создавать при помощи keyframes. Ознакомиться с тем что это такое можно в руководстве по ссылке.

Закрепление

В качестве повторения рассмотренного материала с анимациями предлагаю ознакомиться с со справкой на сайте Javascript.ru и решить 4 тестовых задачи, которые находятся внизу страницы. Ссылка: CSS-анимации.


Медиазапросы

Медиазапросы позволяют задавать разные стили для разных устройств.

@media (max-width: 768px) {
    .container {
        flex-direction: column;
    }
}

Пример веб-страницы с позиционированием и контейнерами

Практическое задание: Верстка веб-страницы по шаблону

Цель: Закрепить навыки по верстке, адаптивному дизайну и работе с компонентами на примере личного сайта разработчика. Студенты научатся создавать адаптивные страницы для различных устройств и использовать компоненты с разными состояниями.
Задание. Создайте веб-страницу личного сайта разработчика по предоставленным макетам. Требования к верстке:

  1. Корректное отображение на разных экранах (десктопная и мобильная версия).
  2. Должны быть отображены рзличные состояния компонентов (нажатие, ввод, ошибки).
  3. Убедитесь, что все интерактивные элементы, такие как ссылки и кнопки, работают корректно. Примеры:
    • Поля ввода для имени и сообщения.
    • Кнопки для отправки сообщений и ссылки на социальные сети.
  4. Не забываем подключать нужный шрифт и следить за отступами.

Шрифт, который используется на сайте, можно загрузить по ссылке.

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

Пример того что у вас должно получиться:

Сайт-визитка

Введение в Bootstrap 5

Bootstrap 5 — это мощный CSS-фреймворк, который облегчает создание адаптивных и мобильных веб-сайтов. Он включает различные компоненты, утилиты и шаблоны, которые помогают разработчикам быстро создавать интерфейсы.

Подключение Bootstrap к проекту

Чтобы использовать Bootstrap в вашем проекте, необходимо подключить CSS и JS-файлы. Это можно сделать через CDN или локально, скачав файлы с официального сайта.

Подключение через CDN

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap Example</title>

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
  </head>
  <body>

    <!-- Ваш контент -->

    <!-- Bootstrap JS -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
  </body>
</html>

Для подробного ознакомления с другими элементами и возможностями Bootstrap можно посетить официальный сайт здесь.

Сеточная система Bootstrap

Сеточная система Bootstrap состоит из контейнеров, строк и колонок. Она поддерживает адаптивные макеты с использованием брейкпоинтов, которые автоматически подстраиваются под размер экрана. Это позволяет создавать как фиксированные, так и гибкие макеты.

Колонки и брейкпоинты

Колонки в Bootstrap работают на основе 12-колоночной сетки. Они адаптируются к разным брейкпоинтам, что позволяет легко управлять адаптивностью макетов.

Пример использования брейкпоинтов:

<div class="container">
  <div class="row">
    <div class="col-sm-6 col-md-4 col-lg-3">Контент</div>
    <div class="col-sm-6 col-md-4 col-lg-3">Контент</div>
  </div>
</div>

Таблица брейкпоинтов:

Размер экранаМинимальная ширинаКласс
Extra small (xs)< 576px.col-
Small (sm)≥ 576px.col-sm-
Medium (md)≥ 768px.col-md-
Large (lg)≥ 992px.col-lg-
Extra large (xl)≥ 1200px.col-xl-
Extra extra large≥ 1400px.col-xxl-

Типы контейнеров

В Bootstrap есть несколько типов контейнеров:

  • .container: имеет фиксированную ширину для каждого брейкпоинта.
  • .container-fluid: занимает 100% ширины экрана на любом устройстве.
  • .container-{breakpoint}: фиксированная ширина, адаптируемая к определенному брейкпоинту, например, .container-md.

Пример:

<div class="container">
  <div class="row">
    <div class="col">Колонка 1</div>
    <div class="col">Колонка 2</div>
  </div>
</div>

Компоненты Bootstrap

Bootstrap предоставляет большой набор готовых компонентов для создания современных интерфейсов. Рассмотрим некоторые из них более подробно.

Кнопки и их состояния

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

Основные стили кнопок:

<button type="button" class="btn btn-primary">Primary</button>
<button type="button" class="btn btn-secondary">Secondary</button>
<button type="button" class="btn btn-success">Success</button>
<button type="button" class="btn btn-danger">Danger</button>
...

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

  • Active: делает кнопку активной. Пример: class="btn btn-primary active".
  • Disabled: делает кнопку неактивной (недоступной). Пример: class="btn btn-primary" disabled.
  • Outline: кнопки с рамкой и прозрачным фоном. Пример: class="btn btn-outline-primary".

Пример с активной и неактивной кнопками:

<button type="button" class="btn btn-primary active" aria-pressed="true">Активная</button>
<button type="button" class="btn btn-secondary" disabled>Неактивная</button>

Модальные окна

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

Пример модального окна:

Другие компоненты

Bootstrap также предоставляет множество других полезных компонентов, таких как навигационные панели, карточки, формы, уведомления и многое другое.

Для более подробного изучения всех компонентов и их возможностей посетите официальную документацию Bootstrap


Практическое задание: Адаптивный лендинг с использованием Bootstrap

Цель этого задания — познакомиться с возможностями Bootstrap и научиться использовать его для создания адаптивных веб-сайтов. Задание разделено на две части: первая для знакомства с основными возможностями Bootstrap, вторая — для создания более сложного проекта.

Часть 1: Знакомство с Bootstrap

Ваша задача — восстановить внешний вид и функционал сайта на основе предоставленной DOM модели, используя Bootstrap. Это задание поможет вам освоить стилизацию и компоненты Bootstrap для создания современных и адаптивных веб-страниц.

Файл с DOM моделью можно загузить по ссылке

Готовый вариант

На что нужно обратить внимание:

  1. Навигация
  • Добавьте классы Bootstrap для панели навигации.
  • Используйте navbar с темной темой и классами navbar-expand-lg, bg-dark и fixed-top.
  • Обеспечьте адаптивность меню с помощью collapse и toggler элементов.
  1. Главная секция
  • Примените классы для выравнивания текста в центре (например, text-center).
  • Добавьте отступы с помощью классов py-3 и mt-5 для соответствия исходной верстке.
  • Используйте стили для кнопки btn, btn-primary, btn-lg.
  1. Карусель с изображениями
  • Используйте компонент Carousel для создания слайд-шоу.
  • Убедитесь, что изображения занимают полную ширину и высоту с помощью классов card, card-img-top.
  • Добавьте кнопки prev и next для управления каруселью, используя классы carousel-control-prev и carousel-control-next.
  1. Таблица с VPN серверами
  • Используйте таблицу с классами Bootstrap table и table-bordered.
  • Включите стили progress bar для отображения нагрузки на серверы.
  • Для выравнивания текста используйте классы align-middle.
  1. Настройка шифрования VPN
  • Добавьте компонент range input с использованием стиля form-range для настройки уровня шифрования.
  • Обновляйте отображение выбранного значения с помощью JavaScript.
  1. Отзывы пользователей
  • Воспользуйтесь компонентом Carousel для переключения отзывов пользователей.
  • Используйте стили blockquote и blockquote-footer для создания отзывов.
  • Убедитесь, что слайдер работает плавно, и отзывы не накладываются друг на друга.
  1. Форма контактов
  • Примените floating labels для полей ввода формы.
  • Добавьте валидацию формы с использованием Bootstrap классов was-validated, is-invalid и is-valid.
  • Поля формы должны быть адаптивными и удобными для ввода.

Дополнительные требования

  1. Валидация формы
  • Реализуйте клиентскую валидацию формы, используя встроенные стили Bootstrap для валидации (.was-validated, .invalid-feedback).
  1. Scrollspy
  • Добавьте функциональность scrollspy, чтобы подсвечивать активные ссылки навигации в зависимости от прокручиваемой секции.

Часть 2: Создание проекта (доп. задание)

У вас есть два варианта для выполнения этой части задания:

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

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

Дополнительные требования:

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

Часть 1: Вспоминаем основы С++

Цель: повтор основных элементов и синтаксиса C++.

Краткое содержание:

  • Указатели и работа с динамической памятью
  • Функции / методы
  • Модификаторы видимости
  • Структуры
  • Классы и объекты
  • Конструкторы / деструкторы, листы инициализации

Часть 2: Введение в ООП

Цель: знакомство с основными принципами ООП.

Знакомство с ключевыми принципами ООП:

  1. Инкапсуляцией;
  2. Наследование
  3. Полиморфизм

Новые элементы синтаксиса:

  • Дружественные функции и классы
  • Статические члены класса
  • Перегрузка функций и операторов
  • Шаблоны

Часть 3: Применение ООП в практическом решении задач

Цель: закрепление знаний и навыков, полученных на прошлых занятиях.

Часть 4: Паттерны проектирования (3-4 занятия)

Принципы проектирования:

MVC (Model-View-Controller)

MVC разделяет приложение на три компонента: Model, View и Controller. Модель отвечает за управление данными и бизнес-логику, Вид отображает интерфейс пользователю, а Контроллер обрабатывает пользовательский ввод и взаимодействует с Моделью и Видом. Этот паттерн используется для того, чтобы отделить логику приложения от его интерфейса, повышая масштабируемость и удобство поддержки продукта в будущем.

Задача: разработать систему управления каталогом товаров.

  1. Упрощенный вариант (консольное приложение):

    • Создать консольное приложение, позволяющее пользователям управлять каталогом товаров.
    • Модель хранит данные о товарах (название, цена, количество).
    • Контроллер обрабатывает ввод пользователя.
    • Вид отображает данные в консоли.
  2. Усложненный вариант (GUI с использованием Qt):

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

MVP (Model-View-Presenter)

MVP схож с MVC, но отличается тем, что вся логика управления сосредоточена в Presenter. Модель отвечает за данные и логику приложения, Вид — за отображение интерфейса, а Презентер связывает их, обеспечивая взаимодействие.

Задача: система управления заявками на ремонт.

  1. Упрощенный вариант (консольное приложение):

    • Создать консольное приложение для создания и управления заявками.
    • Модель хранит информацию о заявках.
    • Презентер обрабатывает взаимодействие между моделью и представлением.
  2. Усложненный вариант (GUI с использованием Qt):

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

Порождающие паттерны

Фабричный метод

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

  • Абстрактный класс транспортного средства.
  • Реализация создания грузовика, самолета и корабля через фабричный метод.
  • Одиночка
  • Прототип

Структурные паттерны

Адаптер

Задача: интеграция старой платежной системы с новым API.

  • Старый интерфейс для операций с оплатами и балансом.
  • Создать адаптер, позволяющий новому API работать с устаревшей системой.
  • Компоновщик
  • Декоратор

Поведенческие паттерны

Наблюдатель

Задача: создать систему уведомлений для пользователей новостного сайта.

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

Часть 5: Проверка усвоенного материала

  1. Моделирование магазина добавление и удаление товаров.
  2. Управление транспортом учет транспортных средств и пробега.
  3. Банковская система: управление счетами через текстовый интерфейс.
  4. Игра "Крестики-нолики".

Задания могут быть выполненны в обычном и усложненном варианте. Обычный вариант - консольная программа. Для усложненного варианта необходимо реализовать графический интерфейс с использованием Qt или ImGui.

Как скачать и установить Qt?

1. Скачиваем установщик

Перейдите по ссылке на официальный сайт Qt. Выберите установщик, соответствующий вашей системе, и нажмите на кнопку "Qt Online Installer...".

Download Qt


2. Запускаем установку

Дождитесь завершения загрузки exe-файла и запустите его.


3. Регистрация

В открывшемся окне выберите "Зарегистрироваться".

Create Account


4. Ввод данных

Введите вашу почту, пароль, примите условия соглашения и нажмите "Далее".


5. Подтверждение почты

Перейдите в почтовый ящик, откройте письмо от The Qt Company и подтвердите регистрацию, кликнув по ссылке.


6. Заполнение профиля

Заполните данные, поставьте галочку "I am an individual person not using Qt for any company" и нажмите "Confirm".


7. Авторизация в установщике

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

Installer Settings


8. Настройка прокси

В открывшемся окне выберите "Ручная настройка прокси-сервера". В поле "HTTP прокси-сервер" введите proxy.quterussia.ru, а в поле "Порт" — 31031. Нажмите "ОК".

Proxy


9. Продолжение установки

Авторизуйтесь под своей учетной записью. Поставьте все галочки и нажмите "Далее".


10. Выбор установки

Выберите "Выборочная установка" и нажмите "Далее".


11. Выбор компонентов

Установите галочки, как показано на изображении ниже, и нажмите "Далее". Если не знаете, какой компилятор выбрать — выберите MinGW.

Components


12. Завершение установки

Примите условия лицензионного соглашения, нажмите "Далее", затем "Установить".

Часть 1. Вспоминаем основы C++

В этом разделе мы освежим в памяти ключевые определения C++: указатели, динамическое управление памятью, функции, модификаторы видимости и классы.

1. Ссылки и указатели, работа с динамической памятью

Работа с указателями и динамической памятью — одна из основ C++, так как это напрямую влияет на производительность и безопасность программ.

Умные указатели — это современная концепция в C++, которая автоматизирует управление памятью, значительно снижая вероятность утечек памяти. Базовая информация о "умных указателях" хорошо разобрана в видеоуроке.

Основные понятия:

  • Сырые указатели: Хранят прямой адрес в памяти.

    int* p = new int(10); // Динамическое выделение памяти
    delete p; // Очистка выделенной памяти
    
  • Умные указатели: Упрощают управление памятью с помощью классов std::unique_ptr и std::shared_ptr, что исключает необходимость ручного удаления памяти.

    // Память автоматически освободится при выходе за область видимости
    std::unique_ptr<int> ptr = std::make_unique<int>(10);
    

Практическое задание: решаем Задачу 3 из раздела по матрицам.

2. Подпрограмммы

Пример простой подпрограммы:

#include <iostream>

// Функция для сложения двух чисел
int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(3, 5);
    std::cout << "Сумма: " << result << std::endl;
    return 0;
}

Методы и подпрограммы: в чем разница?

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

3. Модификаторы видимости

Модификаторы видимости контролируют доступ к членам класса или структуры (переменным и функциям). C++ предоставляет три основных модификатора:

  • public: Члены класса доступны извне.
  • private: Члены класса доступны только внутри самого класса.
  • protected: Члены класса доступны внутри класса и его дочерних классов.

4. Структуры

Структуры в C++ — это пользовательские типы данных, которые группируют переменные под одним именем.

В структурах все члены по умолчанию имеют модификатор видимости public.

Пример простой структуры:

struct Point {
    int x;
    int y;
};

int main() {
    Point p;
    p.x = 10;
    p.y = 20;
    std::cout << "Точка: (" << p.x << ", " << p.y << ")" << std::endl;
    return 0;
}

5. Классы и объекты

Классы — это ключевой элемент объектно-ориентированного программирования (ООП) в C++. Они позволяют объединить данные (члены данных) и функции (методы) в одну сущность. Объекты — это конкретные экземпляры классов, которые могут обладать своими уникальными состояниями.

Конструкторы

Конструкторы — это специальные методы класса, которые вызываются автоматически при создании объекта и предназначены для инициализации его состояния. В C++ можно определить несколько типов конструкторов для разных целей.

Виды конструкторов:

1. Конструктор по умолчанию

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

class Rectangle {
private:
    int width;
    int height;

public:
    Rectangle() : width(0), height(0) {}  // Конструктор по умолчанию
};

2. Конструктор с параметрами

Принимает параметры и инициализирует члены класса конкретными значениями.

class Rectangle {
private:
    int width;
    int height;

public:
    Rectangle(int w, int h) : width(w), height(h) {}  // Конструктор с параметрами
};

3. Конструктор копирования

Создаёт новый объект на основе существующего.

class Rectangle {
private:
    int width;
    int height;

public:
    Rectangle(const Rectangle& rect) : width(rect.width), height(rect.height) {}  // Конструктор копирования
};

4. Конструктор перемещения

Перемещает ресурсы от одного объекта к другому без их копирования (C++11 и выше).

class Rectangle {
private:
    int* data;

public:
    Rectangle(Rectangle&& rect) noexcept : data(rect.data) {
        rect.data = nullptr;
    }  // Конструктор перемещения
};

Операторы присваивания

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

1. Оператор присваивания копирования

Осуществляет копирование данных одного объекта в другой.

class Rectangle {
private:
    int* data;

public:
    Rectangle& operator=(const Rectangle& rect) {
        if (this == &rect) return *this;  // Защита от самоприсваивания
        delete data;  // Очистка предыдущих данных
        data = new int(*rect.data);  // Копирование
        return *this;
    }
};

2. Оператор присваивания перемещения

Перемещает ресурсы от одного объекта к другому без копирования (C++11 и выше).

class Rectangle {
private:
    int* data;

public:
    Rectangle& operator=(Rectangle&& rect) noexcept {
        if (this == &rect) return *this;
        delete data;  // Очистка предыдущих данных
        data = rect.data;  // Перемещение данных
        rect.data = nullptr;  // Очищаем исходный объект
        return *this;
    }
};

Деструктор

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

class Rectangle {
private:
    int* data;

public:
    ~Rectangle() {
        delete data;  // Освобождение динамической памяти
        std::cout << "Прямоугольник уничтожен" << std::endl;
    }
};

Для подробного изучения конструкторов и деструкторов см. видеоурок.

Листы инициализации

Листы инициализации позволяют инициализировать члены класса до выполнения тела конструктора.

class Rectangle {
private:
    const int width;
    int height;

public:
    Rectangle(int w, int h) : width(w), height(h) {}
};

Правило "Трёх" и "Пяти"

Если класс управляет динамическими ресурсами, необходимо следовать правилу трёх или пяти:

  1. Конструктор копирования.
  2. Оператор присваивания копирования.
  3. Деструктор.
  4. Конструктор перемещения (C++11).
  5. Оператор присваивания перемещения (C++11).

Удаление стандартных конструкторов

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

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

class NonCopyable {
public:
    NonCopyable() = default;  // Конструктор по умолчанию
    NonCopyable(const NonCopyable&) = delete;  // Удалённый конструктор копирования
    NonCopyable& operator=(const NonCopyable&) = delete;  // Удалённый оператор присваивания
};

Задания для самостоятельной работы

Задание 1: Реализация класса Book

Создайте класс Book, который моделирует книгу в библиотеке.

Требования:

  1. У класса должны быть члены данных:
    • Название книги (строка).
    • Автор (строка).
    • Год издания (целое число).
    • Количество страниц (целое число).
  2. Конструктор должен принимать название книги, автора и год издания. Количество страниц задаётся по умолчанию равным 0.
  3. Реализуйте методы:
    • setPages(int pages): метод для установки количества страниц.
    • getDescription(): метод для вывода информации о книге в формате: "Название: ..., Автор: ..., Год: ..., Страниц: ...".
  4. Реализуйте конструктор копирования и оператор присваивания для класса.

Пример использования:

int main() {
    Book book1("Война и мир", "Лев Толстой", 1869);
    book1.setPages(1225);
    book1.getDescription();  // Ожидаемый вывод: Название: Война и мир, Автор: Лев Толстой, Год: 1869, Страниц: 1225

    Book book2 = book1;  // Копирование
    book2.getDescription();  // Ожидаемый вывод: Название: Война и мир, Автор: Лев Толстой, Год: 1869, Страниц: 1225
    return 0;
}
Вариант реализации (стараемся сильно не смотреть сюда):
#include <iostream>
#include <string>

class Book {
private:
    std::string m_title;
    std::string m_author;
    int m_year;
    int m_pages;

public:
    Book(const std::string& title, const std::string& author, int year, int pages = 0)
        : m_title(title), m_author(author), m_year(year), m_pages(pages) {}

    Book(const Book& other)
        : m_title(other.m_title), m_author(other.m_author), m_year(other.m_year), m_pages(other.m_pages) {}

    Book& operator=(const Book& other) {
        if (this == &other) return *this;
        m_title = other.m_title;
        m_author = other.m_author;
        m_year = other.m_year;
        m_pages = other.m_pages;
        return *this;
    }

    void setPages(int pages) {
        m_pages = pages;
    }

    void getDescription() const {
        std::cout << "Название: " << m_title
                  << ", Автор: " << m_author
                  << ", Год: " << m_year
                  << ", Страниц: " << m_pages << std::endl;
    }
};

int main() {
    Book book1("Война и мир", "Лев Толстой", 1869);
    book1.setPages(1225);
    book1.getDescription();

    Book book2 = book1;
    book2.getDescription();

    return 0;
}

Задание 2: Класс Vector с управлением ресурсами

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

Требования:

  1. Конструктор с параметром: Принимает размер массива и инициализирует его элементами (например, нулями).
  2. Конструктор копирования: Создайте конструктор копирования, который делает глубокую копию массива.
  3. Конструктор перемещения: Реализуйте конструктор перемещения, который перемещает данные из одного объекта в другой, освобождая исходный объект.
  4. Оператор присваивания копированием: Реализуйте оператор присваивания, который корректно копирует данные с проверкой на самоприсваивание.
  5. Оператор присваивания перемещением: Реализуйте оператор присваивания перемещением для оптимизации работы с временными объектами.
  6. Метод sum(): Напишите метод, который вычисляет сумму всех элементов в массиве.
  7. Деструктор: Освобождает ресурсы (память), выделенные для массива.

Дополнительные задачи (рекомендуется):

  1. Метод resize(size_t new_size): Добавьте возможность изменять размер массива. Если новый размер больше старого, новые элементы инициализируются нулями. Если меньше — лишние элементы удаляются.
  2. Метод slice(size_t start, size_t end): Реализуйте метод, который возвращает подмассив (срез) от индекса start до индекса end (включительно). Срез должен возвращаться как новый объект Vector.
  3. Итераторы: Реализуйте методы begin() и end() для поддержки диапазонных циклов (range-based for loops). Это позволит использовать объект Vector в стандартных конструкциях цикла.
  4. Метод push_back(int value): Добавьте возможность добавлять элемент в конец массива, динамически увеличивая его размер.
  5. Метод find(int value): Реализуйте метод поиска элемента. Возвращает индекс первого найденного элемента с данным значением или -1, если элемент не найден.

Пример использования:

int main() {
    Vector v1(5);  // Вектор из 5 элементов
    v1.push_back(10);  // Добавление элемента в конец
    Vector v2 = v1.slice(1, 3);  // Создание среза вектора

    Vector v3 = v2;  // Копирование
    Vector v4 = std::move(v2);  // Перемещение

    for (int x : v4) {  // Использование итераторов
        std::cout << x << " ";
    }

    std::cout << "Сумма элементов v3: " << v3.sum() << std::endl;
    std::cout << "Индекс элемента 10 в v4: " << v4.find(10) << std::endl;

    return 0;
}
Вариант реализации основных требований (стараемся сильно не смотреть сюда):
#include <iostream>
#include <algorithm>
#include <numeric>

class Vector {
private:
    int* m_data;
    size_t m_size;

public:
    Vector(size_t size) : m_size(size), m_data(new int[size]) {
        std::fill(m_data, m_data + m_size, 0);
    }

    Vector(const Vector& other) : m_size(other.m_size), m_data(new int[other.m_size]) {
        std::copy(other.m_data, other.m_data + other.m_size, m_data);
    }

    Vector(Vector&& other) noexcept : m_size(other.m_size), m_data(other.m_data) {
        other.m_data = nullptr;
        other.m_size = 0;
    }

    Vector& operator=(const Vector& other) {
        if (this == &other) return *this;
        delete[] m_data;
        m_size = other.m_size;
        m_data = new int[m_size];
        std::copy(other.m_data, other.m_data + m_size, m_data);
        return *this;
    }

    Vector& operator=(Vector&& other) noexcept {
        if (this == &other) return *this;
        delete[] m_data;
        m_data = other.m_data;
        m_size = other.m_size;
        other.m_data = nullptr;
        other.m_size = 0;
        return *this;
    }

    int sum() const {
        return std::accumulate(m_data, m_data + m_size, 0);
    }

    ~Vector() {
        delete[] m_data;
    }
};

int main() {
    Vector v1(5);
    std::cout << "Сумма элементов: " << v1.sum() << std::endl;

    Vector v2 = v1;
    std::cout << "Сумма элементов (копия): " << v2.sum() << std::endl;

    Vector v3 = std::move(v1);
    std::cout << "Сумма элементов (перемещение): " << v3.sum() << std::endl;

    return 0;
}

Задание 3: Класс Matrix с использованием Vector

Создайте класс Matrix, который будет динамически управлять двумерным массивом (матрицей) целых чисел, используя класс Vector, разработанный в задании 2, для хранения строк матрицы.

Требования:

  1. Конструктор с параметрами: Принимает количество строк и столбцов и инициализирует их элементами, используя объекты Vector для хранения строк.
  2. Конструктор копирования: Создайте конструктор копирования, который делает глубокую копию матрицы, используя глубокое копирование векторов.
  3. Конструктор перемещения: Реализуйте конструктор перемещения, который перемещает данные из одного объекта в другой, освобождая исходный объект.
  4. Оператор присваивания копированием: Реализуйте оператор присваивания, который корректно копирует данные матрицы с проверкой на самоприсваивание.
  5. Оператор присваивания перемещением: Реализуйте оператор присваивания перемещением для оптимизации работы с временными объектами.
  6. Метод transpose(): Напишите метод, который транспонирует матрицу, меняя строки и столбцы местами (выполняйте перестановку векторов).
  7. Деструктор: Освобождает ресурсы (память), выделенные для матрицы, а также освобождает все используемые векторы.

Дополнительные задачи (рекомендуется):

  1. Метод resize(size_t new_rows, size_t new_cols): Используйте метод resize() класса Vector для изменения размеров матрицы. Если новые размеры больше старых, новые элементы инициализируются нулями.
  2. Метод slice(size_t row_start, size_t row_end, size_t col_start, size_t col_end): Реализуйте метод, который возвращает подматрицу (срез), используя срезы векторов (метод slice() класса Vector).
  3. Метод determinant(): Реализуйте метод для вычисления детерминанта матрицы (для квадратных матриц).
  4. Метод multiply(const Matrix& other): Реализуйте метод, который умножает матрицу на другую матрицу. Проверьте совместимость размеров для умножения.
  5. Метод find(int value): Реализуйте метод поиска элемента в матрице, используя метод find() класса Vector. Возвращает пару индексов (строка, столбец) первого найденного элемента.

Пример использования:

int main() {
    Matrix m1(3, 3);  // Матрица 3x3
    m1.resize(4, 4);  // Изменение размера матрицы на 4x4
    Matrix m2 = m1.slice(1, 3, 1, 3);  // Создание подматрицы

    Matrix m3 = m2;  // Копирование
    Matrix m4 = std::move(m2);  // Перемещение

    m4.transpose();  // Транспонирование матрицы

    std::pair<int, int> pos = m4.find(10);  // Поиск элемента в матрице
    std::cout << "Позиция элемента 10: (" << pos.first << ", " << pos.second << ")" << std::endl;

    return 0;
}

Введение в ООП

Крайне рекомендую перед выполнения практических заданий ознакомиться с хорошей лекцией от преподавателя мехмата МГУ по ссылке. После этого можете ознакомиться с его другими лекциями по С++, информацию преподносит достаточно кратко и ёмко, зачастую упоминает интересные нюансы и особенности, на скорости x1,5 смотрится вполне комфортно.

1. Инкапсуляция

Теоретическая справка:

Инкапсуляция — это принцип ООП, который предполагает сокрытие данных и предоставление контролируемого доступа к ним через специальные методы. В C++ это достигается с помощью модификаторов доступа (private, public, protected). Приватные данные защищены от прямого изменения, и для работы с ними используются геттеры и сеттеры — специальные методы для получения и изменения значений приватных переменных.

  • Геттеры предоставляют доступ к приватным данным.
  • Сеттеры позволяют изменять приватные данные с дополнительной проверкой.

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

Синтаксис:

Пример инкапсуляции с использованием геттеров и сеттеров на примере управления складом:

class Warehouse {
private:
    int itemCount;

public:
    Warehouse(int initialCount) : itemCount(initialCount) {}

    // Геттер для получения количества товаров
    int getItemCount() const {
        return itemCount;
    }

    // Сеттер для добавления товаров с проверкой
    void addItem(int count) {
        if (count > 0) {
            itemCount += count;
        }
    }

    // Сеттер для удаления товаров с проверкой
    void removeItem(int count) {
        if (count > 0 && count <= itemCount) {
            itemCount -= count;
        }
    }
};

int main() {
    Warehouse warehouse(100);  // Создание склада с 100 единицами товара

    warehouse.addItem(50);     // Добавление товаров на склад
    warehouse.removeItem(30);  // Удаление товаров со склада

    std::cout << "Current item count: " << warehouse.getItemCount() << std::endl;  // Вывод текущего количества товаров

    return 0;
}

В этом примере класс Warehouse инкапсулирует переменную itemCount, предоставляя доступ к ней только через методы getItemCount(), addItem(), и removeItem(), что позволяет контролировать изменение количества товаров на складе.

Задача: Моделирование банковского счета

Необходимо создать класс BankAccount, который инкапсулирует данные о счете: владелец и баланс. Методы класса:

  • deposit(double amount) — пополнение счета.
  • withdraw(double amount) — снятие средств с проверкой на достаточность баланса.
  • getBalance() — геттер для доступа к балансу.
  • setOwner(std::string owner) — сеттер для изменения владельца счета.
  • displayInfo() — вывод информации о счете.

Пример работы программы:

Входные данные:

  • Создание счета для "Иван Иванов" с балансом 1000 рублей.
  • Пополнение на 500 рублей.
  • Снятие 300 рублей.
  • Снятие 1500 рублей (превышение доступного баланса).

Выходные данные:

Владелец: Иван Иванов, Баланс: 1000 руб.
На счет зачислено: 500 руб. Баланс: 1500 руб.
Со счета снято: 300 руб. Баланс: 1200 руб.
Ошибка: Недостаточно средств на счете!
Владелец: Иван Иванов, Баланс: 1200 руб.
Вариант реализации основных требований:
#include <iostream>
#include <string>

class BankAccount {
private:
    std::string owner;  // Владелец счета
    double balance;     // Баланс счета

public:
    // Конструктор для инициализации счета
    BankAccount(std::string ownerName, double initialBalance) {
        owner = ownerName;
        balance = initialBalance;
    }

    // Метод для пополнения счета
    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            std::cout << "На счет зачислено: " << amount << " руб. Баланс: " << balance << " руб.\n";
        } else {
            std::cout << "Ошибка: Некорректная сумма пополнения!\n";
        }
    }

    // Метод для снятия средств со счета
    void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
            std::cout << "Со счета снято: " << amount << " руб. Баланс: " << balance << " руб.\n";
        } else {
            std::cout << "Ошибка: Недостаточно средств на счете!\n";
        }
    }

    // Геттер для получения текущего баланса
    double getBalance() {
        return balance;
    }

    // Сеттер для изменения владельца счета
    void setOwner(std::string newOwner) {
        owner = newOwner;
    }

    // Метод для вывода информации о счете
    void displayInfo() {
        std::cout << "Владелец: " << owner << ", Баланс: " << balance << " руб.\n";
    }
};

int main() {
    BankAccount account("Иван Иванов", 1000);
    account.displayInfo();  // Владелец: Иван Иванов, Баланс: 1000 руб.
    account.deposit(500);  // На счет зачислено: 500 руб. Баланс: 1500 руб.
    account.withdraw(300);  // Со счета снято: 300 руб. Баланс: 1200 руб.
    account.withdraw(1500);  // Ошибка: Недостаточно средств на счете!
    account.displayInfo();  // Владелец: Иван Иванов, Баланс: 1200 руб.

    return 0;
}

Дополнительные задания:

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

2. Наследование

Теоретическая справка:

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

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

Синтаксис:

Пример наследования:

class Vehicle {
public:
    void start() const {
        std::cout << "Vehicle is starting.";
    }

    void stop() const {
        std::cout << "Vehicle is stopping.";
    }
};

class Car : public Vehicle {
public:
    void honk() const {
        std::cout << "Car is honking.";
    }
};

class Bicycle : public Vehicle {
public:
    void ringBell() const {
        std::cout << "Bicycle is ringing the bell.";
    }
};

int main() {
    Car myCar;
    Bicycle myBike;

    myCar.start();
    myCar.honk();
    myCar.stop();

    myBike.start();
    myBike.ringBell(); 
    myBike.stop();

    return 0;
}

Машина и велосипед могут выполнять одинаковые действия - старт и остановка. Однако, каждый из них также может реализовывать специфичные действия, автомобиль - сигналить (метод honk), а велосипед использовать звонок (метод ringBell).

Для чего используется:

  • Повторное использование кода: Наследование позволяет избежать дублирования кода, создавая общий базовый класс для связанных объектов. В системе управления заказами можно создать базовый класс Order, от которого наследуются классы OnlineOrder и OfflineOrder, добавляющие специфичные для их типов данные.
  • Создание специализированных классов: Наследование позволяет расширять функциональность базовых классов, создавая специализированные классы с добавлением новых свойств и методов. В системе учета сотрудников можно создать базовый класс Employee и производные классы Manager и Intern, у каждого из которых будут свои особенности.

Когда лучше избегать:

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

Задача: Наследование для модели животных

Создайте базовый класс Animal с методами move() и makeSound(), где move() будет одинаковым для всех животных, а метод makeSound() заменяется специфическими для каждого наследника методами: bark() для собак и meow() для кошек. Затем создайте классы-наследники Dog и Cat. Для класса Dog добавьте метод fetchStick(), чтобы собака могла приносить палку.

Пример работы программы:

Входные данные:

  • Создание объектов Dog и Cat.
  • Вызов методов move(), bark(), и fetchStick() для собаки.
  • Вызов методов move() и meow() для кошки.

Выходные данные:

Животное двигается.
Собака лает.
Собака приносит палку.

Животное двигается.
Кошка мяукает.
Вариант реализации основных требований:
#include <iostream>
#include <string>

// Базовый класс Animal
class Animal {
public:
    // Метод для звуков, общий для всех животных
    void makeSound() const {
        std::cout << "Животное издает звук.\n";
    }

    // Метод для движения, общий для всех животных
    void move() const {
        std::cout << "Животное двигается.\n";
    }
};

// Класс Dog (Собака), наследник Animal
class Dog : public Animal {
public:
    // Специфический метод для собаки - принести палку
    void fetchStick() const {
        std::cout << "Собака приносит палку.\n";
    }

    // Специфический звук собаки
    void bark() const {
        std::cout << "Собака лает.\n";
    }
};

// Класс Cat (Кошка), наследник Animal
class Cat : public Animal {
public:
    // Специфический звук кошки
    void meow() const {
        std::cout << "Кошка мяукает.\n";
    }
};

int main() {
    Dog myDog;
    Cat myCat;

    myDog.move();         // Животное двигается.
    myDog.bark();         // Собака лает.
    myDog.fetchStick();   // Собака приносит палку.

    myCat.move();        // Животное двигается.
    myCat.meow();        // Кошка мяукает.

    return 0;
}

Дополнительные задания:

  1. Добавьте класс Bird, который наследует класс Animal, и добавьте для него метод fly(), который будет выводить сообщение о полете птицы.
  2. Реализуйте методы для типичных действий животных в базовом классе Animal, такие как eat() или sleep(), и добавьте для каждого наследника специфические действия (например, кошка охотится).
  3. Добавьте проверку состояния животного (например, усталость или голод), чтобы некоторые действия (например, движение или игра) могли быть недоступны, если животное устало или голодно.

3. Полиморфизм

Теоретическая справка:

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

В С++ полиморфизм реализуется при помощи двух ключевых слов:

  • virtual — используется для указания того, что метод в базовом классе может быть переопределён в производных классах.
  • override — применяется в производных классах для явного указания того, что метод переопределяет метод базового класса. Это помогает избежать ошибок, если метод базового класса не является виртуальным или если в сигнатуре метода допущена ошибка.

Синтаксис:

Пример полиморфизма с использованием виртуальных методов:

class Animal {
public:
    virtual void sound() {
        std::cout << "Animal makes a sound" << std::endl;
    }
};

class Dog : public Animal {
public:
    void sound() override {
        std::cout << "Dog barks" << std::endl;
    }
};

class Cat : public Animal {
public:
    void sound() override {
        std::cout << "Cat meows" << std::endl;
    }
};

int main() {
    Animal* animal1 = new Dog();
    Animal* animal2 = new Cat();

    animal1->sound();  // Вызывает метод Dog::sound()
    animal2->sound();  // Вызывает метод Cat::sound()

    delete animal1;
    delete animal2;
    return 0;
}

В этом примере базовый класс Animal имеет виртуальный метод sound, который переопределяется в классах-наследниках Dog и Cat. При вызове метода через указатель на базовый класс вызывается метод конкретного объекта.

Для чего используется:

  • Унификация интерфейса: Полиморфизм позволяет создавать системы, где объекты разных типов могут использоваться через общий интерфейс. В системе обработки данных разных типов отчетов (финансовые, аналитические) можно использовать общий интерфейс Report, с помощью которого можно обрабатывать все отчеты, не заботясь о конкретной реализации.
  • Упрощение поддержки и расширяемости: Полиморфизм позволяет легко добавлять новые классы без изменения существующего кода. В системе управления персоналом можно добавить новый класс Intern, унаследованный от Employee, с переопределением методов расчета заработной платы или рабочего времени.

Когда лучше избегать:

  • Сложность понимания: Если слишком активно использовать полиморфизм, код может стать сложным для понимания, особенно для новых разработчиков. В системе управления заказами чрезмерное использование полиморфизма для разных типов продуктов может затруднить понимание и сопровождение кода.
  • Неоправданная сложность: В проектах с четко определенными типами объектов может не требоваться полиморфизм. В небольшом приложении для учета задач полиморфизм может быть излишним, если все задачи имеют одну и ту же структуру и функционал.

Задача: Полиморфизм для геометрических фигур

Создайте базовый класс Shape с виртуальным методом getArea(). Далее создайте два производных класса: Circle и Rectangle, которые будут реализовывать метод getArea() для вычисления площади. Ваша задача — создать массив фигур и вычислить их площади через указатель на базовый класс.

Пример работы программы:

Входные данные:

  • Создание объектов Circle с радиусом 5 и Rectangle с размерами 4x6.
  • Вычисление и вывод площади для каждой фигуры.

Выходные данные:

Площадь круга: 78.54 кв. ед.
Площадь прямоугольника: 24 кв. ед.
Вариант реализации основных требований:
#include <iostream>
#include <cmath>

// Базовый класс Shape
class Shape {
public:
    // Виртуальный метод для вычисления площади
    virtual double getArea() const = 0;  // Чисто виртуальная функция

    // Виртуальный деструктор
    virtual ~Shape() {}
};

// Класс Circle (Круг), наследник Shape
class Circle : public Shape {
private:
    double radius;  // Радиус круга

public:
    // Конструктор для инициализации радиуса
    Circle(double r) : radius(r) {}

    // Переопределение метода getArea() для вычисления площади круга
    double getArea() const override {
        return M_PI * radius * radius;
    }
};

// Класс Rectangle (Прямоугольник), наследник Shape
class Rectangle : public Shape {
private:
    double width, height;  // Ширина и высота прямоугольника

public:
    // Конструктор для инициализации ширины и высоты
    Rectangle(double w, double h) : width(w), height(h) {}

    // Переопределение метода getArea() для вычисления площади прямоугольника
    double getArea() const override {
        return width * height;
    }
};

int main() {
    Shape* shapes[2];

    shapes[0] = new Circle(5);           // Круг с радиусом 5
    shapes[1] = new Rectangle(4, 6);     // Прямоугольник с размерами 4x6

    for (int i = 0; i < 2; ++i) {
        std::cout << "Площадь фигуры: " << shapes[i]->getArea() << " кв. ед.\n";
    }

    for (int i = 0; i < 2; ++i) {
        delete shapes[i];  // Вызов виртуального деструктора
    }

    return 0;
}

Дополнительные задания:

  1. Добавьте метод для вычисления периметра в каждом классе.
  2. Реализуйте класс для треугольника и добавьте его в массив фигур.
  3. Добавьте метод для вычисления и сравнения площадей между фигурами (например, сравнение площади круга и прямоугольника).

4. Различия между ООП и процедурным подходом

Теоретическая справка:

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

Задача: Система управления транспортными средствами

Создайте две версии программы для управления транспортными средствами:

  1. Процедурный подход: создайте функции для управления машиной и велосипедом, которые выполняют действия, такие как движение и заправка.
Пример решения задачи с использованием процедурного подхода
#include <iostream>

// Процедура для управления машиной
void driveCar(double& fuel, double distance) {
    double fuelConsumptionPerKm = 0.1;
    double requiredFuel = distance * fuelConsumptionPerKm;

    if (fuel >= requiredFuel) {
        fuel -= requiredFuel;
        std::cout << "Машина проехала " << distance << " км. Осталось топлива: " << fuel << " л.\n";
    } else {
        std::cout << "Недостаточно топлива для поездки на " << distance << " км.\n";
    }
}

// Процедура для заправки машины
void refuelCar(double& fuel, double amount) {
    fuel += amount;
    std::cout << "Машина заправлена на " << amount << " л. Осталось топлива: " << fuel << " л.\n";
}

// Процедура для управления велосипедом
void rideBicycle(double distance) {
    std::cout << "Велосипед проехал " << distance << " км.\n";
}

int main() {
    double carFuel = 5.0;
    driveCar(carFuel, 50);  // Машина двигается на 50 км
    refuelCar(carFuel, 10); // Машина заправляется на 10 л топлива

    rideBicycle(20);  // Велосипед двигается на 20 км

    return 0;
}
  1. ООП подход: создайте базовый класс Vehicle с общими методами и классы-наследники Car и Bicycle с их специфическими методами.
Пример решения задачи с использованием ООП подхода
#include <iostream>

// Базовый класс для транспортных средств
class Vehicle {
public:
    virtual void move(double distance) const = 0;
    virtual ~Vehicle() {}
};

// Класс Car (Машина), наследует класс Vehicle
class Car : public Vehicle {
private:
    double fuel;  // Текущий уровень топлива
    double fuelConsumptionPerKm;  // Расход топлива на 1 км

public:
    // Конструктор для инициализации машины
    Car(double initialFuel) : fuel(initialFuel), fuelConsumptionPerKm(0.1) {}

    // Метод для движения
    void move(double distance) const override {
        double requiredFuel = distance * fuelConsumptionPerKm;
        if (fuel >= requiredFuel) {
            std::cout << "Машина проехала " << distance << " км. Осталось топлива: " << fuel - requiredFuel << " л.\n";
        } else {
            std::cout << "Недостаточно топлива для поездки на " << distance << " км.\n";
        }
    }

    // Метод для заправки машины
    void refuel(double amount) {
        fuel += amount;
        std::cout << "Машина заправлена на " << amount << " л. Осталось топлива: " << fuel << " л.\n";
    }

    // Деструктор
    ~Car() override = default;
};

// Класс Bicycle (Велосипед), наследует класс Vehicle
class Bicycle : public Vehicle {
public:
    // Метод для движения велосипеда
    void move(double distance) const override {
        std::cout << "Велосипед проехал " << distance << " км.\n";
    }
};

int main() {
    Car myCar(5);
    myCar.move(50);
    myCar.refuel(10);

    Bicycle myBicycle;
    myBicycle.move(20);

    return 0;
}

Пример работы программы:

Входные данные:

  • Машина двигается на 50 км, велосипед на 20 км.
  • Машина заправляется на 10 литров топлива.

Выходные данные:

Машина проехала 50 км. Осталось топлива: 5 л.
Машина заправлена на 10 л. Осталось топлива: 15 л.
Велосипед проехал 20 км.

Дополнительные задания:

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

5. Перегрузка функций и операторов

Теоретическая справка:

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

Перегрузка операторов позволяет изменять поведение стандартных операторов (например, +, -, *, ==) для пользовательских типов данных (классов). Это полезно, когда вы хотите, чтобы стандартные операторы могли работать с вашими объектами, например, для арифметических операций или сравнения объектов.

Синтаксис:

Пример перегрузки функции:

class MathOperation {
public:
    int add(int a, int b) {
        return a + b;
    }

    double add(double a, double b) {
        return a + b;
    }

    int add(int a, int b, int c) {
        return a + b + c;
    }
};

int main() {
    MathOperation math;
    int sum1 = math.add(3, 4);        // Перегрузка для целых чисел
    double sum2 = math.add(2.5, 3.5); // Перегрузка для вещественных чисел
    int sum3 = math.add(1, 2, 3);     // Перегрузка для трех аргументов
    return 0;
}

Пример перегрузки оператора:

class ComplexNumber {
private:
    double real, imag;

public:
    ComplexNumber(double r = 0, double i = 0) : real(r), imag(i) {}

    // Перегрузка оператора +
    ComplexNumber operator+(const ComplexNumber& other) {
        return ComplexNumber(real + other.real, imag + other.imag);
    }

    void display() {
        std::cout << real << " + " << imag << "i" << std::endl;
    }
};

int main() {
    ComplexNumber num1(3.0, 4.0), num2(1.0, 2.0);
    ComplexNumber sum = num1 + num2;  // Использование перегруженного оператора +
    sum.display(); // Вывод: 4.0 + 6.0i
    return 0;
}

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

Для чего используются:

  • Обеспечение удобного интерфейса для пользователя: Перегрузка функций позволяет пользователям кода вызывать одну и ту же функцию для разных типов данных, что делает API более интуитивным. Пример: В системе управления учебными курсами перегруженная функция может использоваться для обработки различных типов данных студента (целочисленные идентификаторы, строки с именем и фамилией).
  • Работа с пользовательскими типами данных: Перегрузка операторов позволяет пользователям определять естественное поведение операторов для объектов. Пример: В системе учета финансов перегруженный оператор + может использоваться для сложения объектов класса Money, который содержит информацию о валюте и сумме.

Когда лучше избегать:

  • Чрезмерное использование перегрузки: Если перегружать слишком много операторов или функций, это может запутать пользователей кода и привести к сложностям в его понимании. Пример: В приложении для управления инвентарем слишком частое использование перегрузки операторов может привести к путанице, так как пользователи могут не понимать, как операторы работают с объектами инвентаря.
  • Сложность отладки: Перегрузка операторов может затруднить отладку программы, так как она изменяет стандартное поведение операторов. Пример: В системе для управления проектами перегрузка операторов сравнения (== или <) может привести к непредсказуемым результатам, если не реализована корректно.

Задача: Перегрузка операторов для работы с комплексными числами

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

  • Приватные члены: действительная и мнимая часть числа.
  • Публичные методы для получения и изменения частей комплексного числа.
  • Перегруженные операторы:
    • + для сложения двух комплексных чисел.
    • - для вычитания.
    • == для сравнения двух комплексных чисел.
    • << для вывода комплексного числа.

Пример работы программы:

Входные данные:

  • Создание двух комплексных чисел 3 + 4i и 1 + 2i.
  • Сложение и вычитание этих чисел.
  • Сравнение двух чисел.

Выходные данные:

Первое число: 3 + 4i
Второе число: 1 + 2i
Результат сложения: 4 + 6i
Результат вычитания: 2 + 2i
Вариант реализации основных требований:
#include <iostream>

class Complex {
private:
    double real;  // Действительная часть
    double imag;  // Мнимая часть

public:
    Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}

    // Метод для получения действительной части
    double getReal() const {
        return real;
    }

    // Метод для получения мнимой части
    double getImag() const {
        return imag;
    }

    // Метод для изменения действительной части
    void setReal(double r) {
        real = r;
    }

    // Метод для изменения мнимой части
    void setImag(double i) {
        imag = i;
    }

    // Перегрузка оператора + для сложения двух комплексных чисел
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }

    // Перегрузка оператора - для вычитания двух комплексных чисел
    Complex operator-(const Complex& other) const {
        return Complex(real - other.real, imag - other.imag);
    }

    // Перегрузка оператора == для сравнения двух комплексных чисел
    bool operator==(const Complex& other) const {
        return (real == other.real) && (imag == other.imag);
    }

    // Перегрузка оператора << для вывода комплексного числа
    friend std::ostream& operator<<(std::ostream& out, const Complex& c) {
        out << c.real;
        if (c.imag >= 0) {
            out << " + " << c.imag << "i";
        } else {
            out << " - " << -c.imag << "i";
        }
        return out;
    }
};

int main() {
    Complex num1(3, 4);
    Complex num2(1, 2);

    std::cout << "Первое число: " << num1 << "\n";
    std::cout << "Второе число: " << num2 << "\n";

    Complex sum = num1 + num2;
    std::cout << "Результат сложения: " << sum << "\n";

    Complex difference = num1 - num2;
    std::cout << "Результат вычитания: " << difference << "\n";

    if (num1 == num2) {
        std::cout << "Числа равны.\n";
    } else {
        std::cout << "Числа не равны.\n";
    }

    return 0;
}

Дополнительные задания:

  1. Реализуйте перегрузку оператора * для умножения комплексных чисел.
  2. Добавьте оператор != для проверки неравенства.
  3. Реализуйте оператор [], который позволяет обращаться к действительной и мнимой частям числа по индексу (например, c[0] для действительной и c[1] для мнимой).

6. Шаблоны (Templates)

Теоретическая справка:

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

Синтаксис:

Пример работы шаблона на функции:

template <typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    int resultInt = add(3, 4);        // Работает с целыми числами
    double resultDouble = add(3.5, 2.1);  // Работает с числами с плавающей запятой
    return 0;
}

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

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

template <typename T>
class Vector {
private:
    T* data;
    int size;

public:
    Vector(int s) : size(s) {
        data = new T[size];
    }

    void setData(int index, T value) {
        if (index >= 0 && index < size) {
            data[index] = value;
        }
    }

    T getData(int index) {
        if (index >= 0 && index < size) {
            return data[index];
        }
        return T(); // Возвращаем значение по умолчанию для типа T
    }

    ~Vector() {
        delete[] data;
    }
};

int main() {
    Vector<int> intVector(5);
    intVector.setData(0, 10);

    Vector<double> doubleVector(3);
    doubleVector.setData(1, 5.5);

    return 0;
}

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

Для чего используются:

  • Универсальные контейнеры данных: Шаблонные классы, такие как Vector, можно использовать в небольших модулях для хранения и обработки данных (например, идентификаторы студентов или их оценки).
  • Гибкость с разными типами данных: В модуле вычислений шаблонные функции могут выполнять операции с различными типами данных (например, целые числа, вещественные числа, комплексные числа).
  • Повторное использование кода: Шаблоны позволяют создавать универсальные структуры данных (например, списки, очереди), что предотвращает дублирование кода.

Когда лучше избегать:

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

Задача: Шаблон класса для работы с парой данных

Создайте шаблон класса Pair, который может хранить два объекта любого типа и предоставлять методы для доступа к этим объектам. Класс должен содержать:

  • Приватные члены для хранения пары данных.
  • Публичные методы для доступа к первому и второму элементам.
  • Метод для сравнения двух объектов Pair (пара считается равной, если оба элемента равны).

Пример работы программы:

Входные данные:

  • Создание пары целых чисел (5, 10).
  • Создание пары строк ("Привет", "Мир").
  • Сравнение двух пар целых чисел.

Выходные данные:

Первая пара: 5, 10
Вторая пара: Привет, Мир
Пары равны: Нет
Вариант реализации основных требований:
#include <iostream>
#include <string>

// Шаблонный класс Pair для работы с двумя объектами любого типа
template <typename T1, typename T2>
class Pair {
private:
    // Приватные члены для хранения двух объектов
    T1 first;
    T2 second;

public:
    Pair(T1 firstValue, T2 secondValue) : first(firstValue), second(secondValue) {}

    T1 getFirst() const {
        return first;
    }

    T2 getSecond() const {
        return second;
    }

    // Метод для сравнения двух пар
    bool isEqual(const Pair<T1, T2>& other) const {
        return (first == other.first && second == other.second);
    }

    friend std::ostream& operator<<(std::ostream& os, const Pair<T1, T2>& pair) {
        os << pair.first << ", " << pair.second;
        return os;
    }
};

int main() {
    // Создание пары целых чисел
    Pair<int, int> intPair(5, 10);
    std::cout << "Первая пара: " << intPair << std::endl;

    // Создание пары строк
    Pair<std::string, std::string> stringPair("Привет", "Мир");
    std::cout << "Вторая пара: " << stringPair << std::endl;

    // Сравнение двух пар целых чисел
    Pair<int, int> anotherIntPair(5, 10);
    bool areEqual = intPair.isEqual(anotherIntPair);
    std::cout << "Пары равны: " << (areEqual ? "Да" : "Нет") << std::endl;

    return 0;
}

Дополнительные задания:

  1. Реализуйте шаблон для сравнения пар разного типа (например, пара целых чисел и пара с плавающей точкой).
  2. Добавьте возможность работы с шаблоном для трех элементов (например, Triplet).
  3. Реализуйте шаблонный метод для вывода данных пары через перегрузку оператора <<.

7. Статические члены класса

Теоретическая справка:

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

Пример:

class Example {
public:
    static int staticVar;

    static void staticMethod() {
        std::cout << "This is a static method!" << std::endl;
    }
};

int Example::staticVar = 0;

int main() {
    // Вызов статического метода
    Example::staticMethod();

    // Доступ к статической переменной
    std::cout << "Static variable: " << Example::staticVar << std::endl;
    return 0;
}

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

class Singleton {
private:
    static Singleton* instance;

    // Закрытый конструктор
    Singleton() {}

public:
    // Статический метод для получения экземпляра класса
    static Singleton* getInstance() {
        if (!instance)
            instance = new Singleton();
        return instance;
    }
};

Singleton* Singleton::instance = nullptr;

Для чего используются:

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

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

  3. Удобство в утилитарных функциях. Например, статические методы могут использоваться для валидации данных в системе электронного документооборота (СЭД). Например, метод для проверки формата email можно реализовать как статический метод, который вызывается без создания экземпляра класса пользователя.

Когда лучше избегать:

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

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

Задача: Учет количества сотрудников в компании

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

Класс должен содержать:

  • Приватные члены: имя сотрудника и идентификационный номер (ID).
  • Статический счетчик для подсчета сотрудников.
  • Статический метод для вывода общего количества сотрудников.
  • Конструктор, который увеличивает счетчик и присваивает сотруднику уникальный ID.

Пример работы программы:

Входные данные:

  • Создание трех сотрудников с именами "Иван", "Мария" и "Алексей".

Выходные данные:

Сотрудник Иван, ID: 1
Сотрудник Мария, ID: 2
Сотрудник Алексей, ID: 3
Общее количество сотрудников: 3
Вариант реализации основных требований:
#include <iostream>
#include <string>

class Employee {
private:
    std::string name;
    int id;

    // Статический счетчик для подсчета сотрудников
    static int employeeCount;
    
public:
    Employee(const std::string& employeeName) : name(employeeName) {
        employeeCount++;
        id = employeeCount;
    }

    void displayInfo() const {
        std::cout << "Сотрудник " << name << ", ID: " << id << std::endl;
    }

    // Статический метод для вывода общего количества сотрудников
    static void showEmployeeCount() {
        std::cout << "Общее количество сотрудников: " << employeeCount << std::endl;
    }
};

// Инициализация статической переменной
int Employee::employeeCount = 0;

int main() {
    Employee emp1("Иван");
    Employee emp2("Мария");
    Employee emp3("Алексей");

    emp1.displayInfo();
    emp2.displayInfo();
    emp3.displayInfo();

    Employee::showEmployeeCount();

    return 0;
}

Дополнительные задания:

  1. Реализуйте возможность удаления сотрудника. Не забудьте уменьшить общий счетчик сотрудников.
  2. Добавьте статический метод для вывода списка всех сотрудников.
  3. Добавьте методы для изменения данных сотрудника (например, изменение имени), чтобы проверить, как это влияет на работу статических методов.

8. Дружественные классы и функции

Теоретическая справка:

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

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

Синтаксис:

Чтобы сделать функцию дружественной классу, необходимо объявить её с ключевым словом friend внутри класса. Пример синтаксиса:

class ClassName {
private:
    int privateData;

public:
    // Дружественная функция имеет доступ к приватным членам этого класса
    friend void friendFunction(ClassName& obj);
};

// Определение дружественной функции
void friendFunction(ClassName& obj) {
    // Функция имеет доступ к приватным членам класса
    std::cout << "Private data: " << obj.privateData << std::endl;
}

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

class ClassA {
private:
    int privateDataA;

    // Класс ClassB является дружественным и имеет доступ ко всем приватным членам
    friend class ClassB;
};

class ClassB {
public:
    void accessClassA(ClassA& obj) {
        // ClassB может получить доступ к приватным членам ClassA
        std::cout << "Private data from ClassA: " << obj.privateDataA << std::endl;
    }
};

В этом примере класс ClassB может получить доступ к приватным данным класса ClassA напрямую, так как объявлен дружественным.

Зачем нужны дружественные функции и классы?

Для чего используются:

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

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

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

Когда лучше избегать:

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

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

Задача: Модель взаимодействия между классами "Компания" и "Сотрудник"

Создайте два класса: Company и Employee. Класс Company должен управлять сотрудниками, а класс Employee должен содержать информацию о сотрудниках. Класс Company должен быть дружественным к классу Employee, чтобы иметь возможность добавлять и удалять сотрудников.

Класс Employee содержит:

  • Приватные данные: имя и ID сотрудника.
  • Конструктор для создания сотрудника.
  • Метод для вывода информации о сотруднике.

Класс Company включает:

  • Приватные данные: массив сотрудников (или вектор).
  • Дружественные функции для добавления и удаления сотрудников.

Пример работы программы:

Входные данные:

  • Создание объекта компании.
  • Добавление двух сотрудников.
  • Вывод списка сотрудников.

Выходные данные:

Сотрудник Иван, ID: 1
Сотрудник Мария, ID: 2
Общее количество сотрудников: 2
Вариант реализации основных требований:
#include <iostream>
#include <vector>
#include <string>

class Employee {
private:
    std::string name;
    int id;
    static int employeeCount;

public:
    Employee(const std::string& employeeName) : name(employeeName) {
        employeeCount++;
        id = employeeCount;
    }

    void displayInfo() const {
        std::cout << "Сотрудник " << name << ", ID: " << id << std::endl;
    }

    static int getEmployeeCount() {
        return employeeCount;
    }

    // Делаем класс Company дружественным, чтобы он имел доступ к приватным членам Employee
    friend class Company;
};

// Инициализация статической переменной
int Employee::employeeCount = 0;

// Класс Company для управления сотрудниками
class Company {
private:
    std::vector<Employee> employees;

public:
    void addEmployee(const std::string& employeeName) {
        Employee newEmployee(employeeName);
        employees.push_back(newEmployee);
    }

    void removeLastEmployee() {
        if (!employees.empty()) {
            employees.pop_back();
        }
    }

    void listEmployees() const {
        for (const auto& employee : employees) {
            employee.displayInfo();
        }
    }

    void showEmployeeCount() const {
        std::cout << "Общее количество сотрудников: " << Employee::getEmployeeCount() << std::endl;
    }
};

int main() {
    Company myCompany;

    myCompany.addEmployee("Иван");
    myCompany.addEmployee("Мария");

    myCompany.listEmployees();
    myCompany.showEmployeeCount();

    return 0;
}

Дополнительные задания:

  1. Реализуйте возможность поиска сотрудника по имени или ID.
  2. Добавьте метод для изменения данных сотрудника через класс Company (например, изменение имени).
  3. Реализуйте дружественные функции для вывода всех сотрудников компании.

Контрольное задание: Магазин с товарами, клиентами и покупками

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

Задача: Разработка модели магазина

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

  1. Класс Product для хранения информации о товаре:
    • Приватные данные: название товара, цена, количество на складе.
    • Публичные методы для изменения количества и получения информации о товаре.
    • Перегрузите оператор == для сравнения товаров.
  2. Класс Customer для хранения информации о клиентах:
    • Приватные данные: имя клиента, баланс счета.
    • Публичные методы для пополнения счета и покупки товара.
    • Дружественная функция для доступа к данным клиента из класса магазина.
  3. Класс Store для управления покупками и товарами:
    • Приватные данные: список товаров и клиентов.
    • Статический счетчик для учета количества товаров в магазине.
    • Публичные методы для добавления товаров, покупки товаров клиентами.
    • Шаблонный метод для возврата списка товаров или клиентов.

Пример работы программы:

Входные данные:

  • Добавление товаров в магазин: "Хлеб", "Молоко", "Мясо".
  • Создание клиента с балансом 1000 рублей.
  • Покупка товара клиентом.

Выходные данные:

Товар: Хлеб, Цена: 50 руб., Остаток: 98 шт.
Товар: Молоко, Цена: 60 руб., Остаток: 97 шт.
Клиент Иван Иванов: Баланс: 940 руб.

Дополнительные задания:

  1. Реализуйте шаблонный метод для возврата информации как о товарах, так и о клиентах (например, метод, который принимает тип объекта и возвращает соответствующую информацию).
  2. Реализуйте перегрузку оператора += для увеличения количества товара на складе и оператора -= для уменьшения.
  3. Добавьте шаблонный класс для управления учетными записями сотрудников магазина, который включает информацию о сотрудниках и позволяет управлять их статусом и зарплатой.

Применение ООП в практическом решении задач

Для выполнения заданий выберите вариант решения в зависимости от номера вашей зачетной книжки. Решайте вариант по формуле: Номер варианта = (Номер зачетной книжки mod 3) + 1

Задание 1: Система поиска по документам и файлам

Описание предметной области:

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

Задание:

  1. Реализуйте базовый класс File, который будет содержать основные поля, такие как имя файла, дата создания, размер и путь к файлу (локальный). Реализуйте метод open(), который будет выводить сообщение о попытке открытия файла.
  2. Создайте производные классы для различных типов файлов:
    • TextDocument для текстовых документов.
    • PDFDocument для PDF файлов.
    • ImageFile для изображений.
    • VideoFile для видеофайлов.
    • AudioFile для аудиофайлов.
  3. Реализуйте методы поиска с возможностью фильтрации по имени, типу, размеру, дате создания и изменения.
  4. Реализуйте методы для имитации предварительного просмотра изображений и видео, а также воспроизведения аудиофайлов (вывод сообщений об этих действиях).
  5. Реализуйте возможность тегирования файлов и поиска по тегам.
  6. Система должна поддерживать сортировку результатов по различным параметрам (имя файла, дата создания, размер).

Доп. функции:

  1. Добавьте систему архивации файлов. Создайте возможность перемещать файлы в архив и выводить их в поисковых результатах отдельно.
  2. Реализуйте систему отчётов, которая выводит статистику по найденным файлам (количество файлов, средний размер, последние изменения).
  3. Создайте возможность удаления файлов с подтверждением в консоли.

Входные данные для тестирования:

Информация о файлах может быть введена с клавиатуры или считана из текстового файла. Пример ввода данных с клавиатуры:

Введите информацию о файлах (формат: имя файла, дата создания, размер, теги):

1. Report.pdf, 10.05.2023, 200 KB, [work, project]
2. Image.jpg, 15.11.2022, 1.5 MB, [vacation, family]
3. Notes.txt, 01.01.2021, 50 KB, [work, personal]
4. Video.mp4, 20.02.2020, 500 MB, []
5. Podcast.mp3, 05.04.2021, 100 MB, []

Или можно прочитать из текстового документа:

Report.pdf, 10.05.2023, 200 KB, [work, project]
Image.jpg, 15.11.2022, 1.5 MB, [vacation, family]
Notes.txt, 01.01.2021, 50 KB, [work, personal]
Video.mp4, 20.02.2020, 500 MB, []
Podcast.mp3, 05.04.2021, 100 MB, []

Запрос поиска: тип файла - "PDF", теги - "work", сортировка - по дате создания.

Выходные данные:

Результаты поиска (сортировка по дате создания):
1. Report.pdf (10.05.2023, 200 KB, Local, Теги: [work, project])

Открытие файла: Report.pdf
Файл Report.pdf открыт для редактирования.

Задание 2: Система бронирования отелей

Описание предметной области:

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

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

Задание:

  1. Реализуйте базовый класс Booking, который будет содержать информацию о бронировании (номер комнаты, тип комнаты, количество ночей, базовая цена). Создайте методы для расчета стоимости бронирования с учетом дополнительных услуг и динамического изменения цен в зависимости от загруженности отеля.
  2. Создайте производные классы для различных типов номеров:
    • SingleRoom для одноместных номеров.
    • DoubleRoom для двухместных номеров.
    • Suite для люксов.
  3. Реализуйте систему управления скидками и бонусами для постоянных клиентов. Создайте систему накопления баллов, которые можно использовать для получения скидок.
  4. Реализуйте систему динамического изменения цен в зависимости от загруженности отелей.
  5. Поддержите групповые бронирования с расчетом скидок и спецпредложений для групп.

Доп. функции:

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

Входные данные для тестирования:

Доступные номера:
1. Номер 101 - Single Room - 1000 руб/ночь
2. Номер 102 - Double Room - 1500 руб/ночь
3. Номер 201 - Suite - 3000 руб/ночь

Бонусы клиента:
Постоянный клиент, накоплено 300 баллов (5% скидка).

Запросы на бронирование:
1. Номер 102, 3 ночи, завтрак, клиент - постоянный.
2. Номер 101, групповое бронирование (2 номера), 2 ночи, обед.
Текущая загруженность отеля: 85%

Выходные данные:

Номер 102 (Double Room)
Количество ночей: 3
Дополнительные услуги: завтрак
Общая стоимость: 6500 руб (с учетом скидки)

Номер 101 (Single Room) - Групповое бронирование
Количество номеров: 2
Количество ночей: 2
Дополнительные услуги: обед
Общая стоимость: 3800 руб за номер (с учетом скидок)

Статус номеров: заняты

Ссылка на файл с лабораторными работами.

Общие требования к сдаче лабораторных работ:

  1. Среда разработки: Для выполнения всех лабораторных работ используем Visual Studio. Версию можно выбрать на свое усмотрение, но рекомендуется скачать актуальную версию с официального сайта.
  2. Единое решение (Solution): Для всех лабораторных работ создаем единый файл решения (sln). В этом файле каждый новый проект должен соответствовать отдельной лабораторной работе.
  3. Загрузка на GitHub: Полную директорию с файлом решения и всеми проектами необходимо загрузить на GitHub. Убедитесь, что все файлы и зависимости корректно загружены. Обновляем новыми лабораторками по мере их выполнения.

Ознакомиться с инструкцией по настройке SSH ключей для Github'a можно здесь.

Задание 1

  1. Скачать iso-образ ОС Ubuntu 24.04 по ссылке с официального сайта Ubuntu.
  2. Установить Ubuntu 22.04 на виртуальную машину VMWare из iso-образа.
  3. Установить (на выбор):
    • Postgresql: sudo apt install postgresql
    • MariaDB: sudo apt install mariadb-server
  4. Запустить сервер БД:
    • Для Postgresql: sudo systemctl start postgresql
    • Для MariaDB: sudo systemctl start mysql
  5. Создать тестовую БД средствами консольного клиента:
    • Для Postgresql:
      sudo su postgres
      psql
      create database test;
      
    • Для MariaDB:
      sudo mysql
      create database test;
      
  6. Присоединиться к тестовой БД:
    • Для Postgresql: \c test;
    • Для MariaDB: use test;
  7. Создать простую таблицу:
    CREATE TABLE my_table (
      id SERIAL NOT NULL,
      code VARCHAR(10) NOT NULL,
      name VARCHAR(500) NOT NULL,
      PRIMARY KEY (id)
    );
    
  8. Произвести манипуляции как в лекции:
    • Добавить колонку с текущим временем:
      ALTER TABLE my_table
      ADD datetime timestamp NOT NULL DEFAULT now();
      
    • Изменить тип данных колонки code:
      ALTER TABLE my_table
      ALTER COLUMN code TYPE varchar(40);
      
    • Удалить колонку datetime:
      ALTER TABLE my_table
      DROP COLUMN datetime;
      
    • Удалить таблицу:
      DROP TABLE my_table;
      

Отчет

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

Задание 2

  1. Произвести установку DBeaver на виртуальную машину, установленную в задании 1.
    Инструкцию по установке и само приложение можно найти на официальном сайте - https://dbeaver.io/.

  2. Произвести подключение к установленной на предыдущем занятии СУБД.

  3. Произвести манипуляции с БД, аналогичные заданию 1.

Отчет в виде скриншотов

Троичная логика в Transact-SQL

Троичная логика (или трехзначная логика) — это логическая система, которая оперирует тремя значениями:

  • TRUE (истина)
  • FALSE (ложь)
  • UNKNOWN (неизвестно)

В реляционных базах данных, таких как Microsoft SQL Server, PostgreSQL и SQLite, троичная логика используется для обработки ситуаций, когда данные могут быть неопределны или отсутствовать в принципе. Основой троичной логики является значение NULL, которое обозначает отсутствие данных. Операции с участием NULL могут приводить к результату UNKNOWN, что означает, что результат выражения не может быть определен как истинный или ложный.

Описание базы данных для тестовых операций

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

  1. Клиенты — клиенты могут регистрироваться в системе и делать заказы. Однако не все клиенты подтверждают свои учетные записи. Поле verified в таблице клиентов может быть TRUE, FALSE или NULL, если клиент еще не завершил регистрацию.

  2. Сотрудники — сотрудники работают в отделе продаж или на складе и обрабатывают заказы. Поле access_confirmed может быть TRUE, FALSE или NULL, если у сотрудника еще не подтвержден доступ к системе.

  3. Товары — на складе могут находиться разные товары, которые могут быть доступны, зарезервированы или отсутствовать. Статус товара может быть представлен как 'available', 'reserved' или 'out_of_stock'.

  4. Заказы — клиенты могут делать заказы на товары. Заказ может быть выполнен, отменен или находиться в процессе обработки. Статус заказа может быть представлен как 'completed', 'pending' или 'cancelled'.

  5. Счета — каждый заказ сопровождается счетом. Статус оплаты может быть 'paid', 'unpaid' или 'partially_paid', что позволяет отслеживать состояние оплаты заказа.

Структура базы данных:

-- Таблица клиентов
CREATE TABLE customers (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE,
    registration_date DATE NOT NULL,
    verified BOOLEAN  -- Подтверждена ли учетная запись клиента (TRUE, FALSE, NULL)
);

-- Таблица сотрудников
CREATE TABLE employees (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE,
    phone_number TEXT UNIQUE,
    access_confirmed BOOLEAN,  -- Подтвержден ли доступ сотрудника к системе
    hire_date DATE NOT NULL
);

-- Таблица товаров
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    sku TEXT UNIQUE,  -- Уникальный код товара
    quantity INT NOT NULL,  -- Количество на складе
    status TEXT CHECK (status IN ('available', 'reserved', 'out_of_stock'))  -- Статус товара
);

-- Таблица заказов
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    customer_id INT REFERENCES customers(id),
    employee_id INT REFERENCES employees(id),  -- Сотрудник, который обрабатывает заказ
    product_id INT REFERENCES products(id),
    order_date DATE NOT NULL,
    quantity INT NOT NULL,  -- Количество заказанных товаров
    status TEXT CHECK (status IN ('completed', 'cancelled', 'pending'))  -- Статус заказа
);

-- Таблица счетов
CREATE TABLE invoices (
    id SERIAL PRIMARY KEY,
    order_id INT REFERENCES orders(id),
    payment_date DATE,
    total_amount NUMERIC(10, 2) NOT NULL,  -- Общая сумма счета
    paid_amount NUMERIC(10, 2),  -- Оплаченная сумма
    payment_status TEXT CHECK (payment_status IN ('paid', 'unpaid', 'partially_paid'))  -- Статус оплаты
);

Пример тестовых данных:

-- Вставляем данные клиентов
INSERT INTO customers (name, email, registration_date, verified) VALUES
('John Doe', 'john.doe@example.com', '2021-01-20', TRUE),
('Jane Smith', 'jane.smith@example.com', '2022-04-05', FALSE),  -- Клиент не подтвердил учетную запись
('Alex Johnson', 'alex.johnson@example.com', '2023-07-12', NULL);  -- Неизвестно, подтвердил ли клиент учетную запись

-- Вставляем данные сотрудников
INSERT INTO employees (name, email, phone_number, access_confirmed, hire_date) VALUES
('Ivan Petrov', 'ivan.petrov@example.com', '1234567890', TRUE, '2020-03-15'),
('Anna Sidorova', 'anna.sidorova@example.com', '0987654321', FALSE, '2021-06-01'),
('Oleg Ivanov', 'oleg.ivanov@example.com', NULL, NULL, '2022-01-20');  -- У сотрудника нет номера телефона и доступа

-- Вставляем данные товаров
INSERT INTO products (name, sku, quantity, status) VALUES
('Laptop HP', 'LAP123', 50, 'available'),
('Smartphone Samsung', 'PHN456', 20, 'reserved'),
('Tablet Lenovo', 'TBL789', 0, 'out_of_stock');  -- Товара нет на складе

-- Вставляем данные заказов
INSERT INTO orders (customer_id, employee_id, product_id, order_date, quantity, status) VALUES
(1, 1, 1, '2023-05-15', 2, 'completed'),  -- Заказ Laptop HP для клиента John Doe
(2, 2, 2, '2023-05-20', 1, 'pending'),  -- Заказ для клиента Jane Smith в процессе
(3, 3, 3, '2023-06-01', 1, 'cancelled');  -- Отмененный заказ по товару Tablet Lenovo

-- Вставляем данные счетов
INSERT INTO invoices (order_id, payment_date, total_amount, paid_amount, payment_status) VALUES
(1, '2023-05-16', 2000.00, 2000.00, 'paid'),  -- Заказ полностью оплачен
(2, NULL, 1500.00, NULL, 'unpaid'),  -- Заказ не оплачен
(3, '2023-06-02', 500.00, 250.00, 'partially_paid');  -- Заказ частично оплачен

1. Операции с NULL и UNKNOWN

Операции с NULL — это основа троичной логики в SQL. NULL используется для обозначения отсутствующего или неопределенного значения. В троичной логике результат выражения с участием NULL может быть:

  • TRUE
  • FALSE
  • UNKNOWN (неопределенно)

UNKNOWN возникает, когда в логических выражениях участвует NULL, и система не может определить результат выражения. Это ключевая часть троичной логики, которая активно используется в Microsoft SQL Server. В таких случаях результатом выражения является не TRUE и не FALSE, а UNKNOWN.

Пример: Сравнение с NULL

В SQL нельзя просто сравнить значение с NULL с помощью оператора = или !=. Например, следующий запрос не вернет результатов, даже если есть строки с NULL:

SELECT * FROM customers WHERE verified = NULL;

Для работы с NULL нужно использовать специальные операторы:

  • IS NULL — проверяет, является ли значение NULL.
  • IS NOT NULL — проверяет, что значение не является NULL.

Пример: Поиск всех клиентов с неопределенным статусом верификации

SELECT * FROM customers WHERE verified IS NULL;

Этот запрос вернет всех клиентов, для которых статус верификации учетной записи не определен.

2. Логические операторы (AND, OR, NOT)

Логические операторы в SQL также подчиняются троичной логике. Результат выражения зависит от того, участвует ли в нем NULL. Если одно из условий в логическом выражении имеет значение NULL, результатом будет UNKNOWN.

Пример: Использование AND

SELECT * FROM employees WHERE access_confirmed = TRUE AND phone_number IS NOT NULL;

Этот запрос вернет всех сотрудников, которые подтвердили доступ и у которых указан номер телефона. Если access_confirmed или phone_number имеют значение NULL, результат будет UNKNOWN, и такие записи не попадут в результат.

Пример: Использование OR

SELECT * FROM customers WHERE verified = TRUE OR verified IS NULL;

Этот запрос вернет всех клиентов, чья учетная запись подтверждена (TRUE), а также тех, чей статус верификации не определен (NULL).

Таблица результатов логических операторов в троичной логике

ABA AND BA OR BNOT A
TRUETRUETRUETRUEFALSE
TRUEFALSEFALSETRUEFALSE
TRUENULLNULLTRUEFALSE
FALSETRUEFALSETRUETRUE
FALSEFALSEFALSEFALSETRUE
FALSENULLFALSENULLTRUE
NULLTRUENULLTRUENULL
NULLFALSEFALSENULLNULL
NULLNULLNULLNULLNULL

3. Операторы сравнения

Операторы сравнения (=, !=, >, <, и т.д.) также подчиняются троичной логике. Если одно из сравниваемых значений — это NULL, результат всегда будет UNKNOWN. Это ключевая особенность троичной логики: NULL не равно ни чему, даже самому себе.

Пример: Сравнение с NULL

SELECT * FROM products WHERE status = 'available' OR status = 'reserved';

Этот запрос вернет только те продукты, у которых статус — available или reserved, но не вернет продукты со статусом NULL, потому что сравнение с NULL всегда возвращает UNKNOWN.

Пример: Использование оператора IS DISTINCT FROM

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

SELECT * FROM customers WHERE verified IS DISTINCT FROM TRUE;

IS DISTINCT FROM сравнивает значения с учетом NULL, в отличие от обычного оператора !=, который вернет UNKNOWN, если одно из значений является NULL.

4. JOIN'ы

При работе с JOIN'ами в SQL NULL может привести к неожиданным результатам. Например, если в одной из таблиц поле, участвующее в соединении, имеет значение NULL, оно не будет участвовать в соединении при использовании INNER JOIN.

Пример: Использование LEFT JOIN для учета NULL

SELECT s.id, c.name AS customer_name, e.name AS employee_name, p.name AS product_name, s.status
FROM sales s
LEFT JOIN customers c ON s.customer_id = c.id
LEFT JOIN employees e ON s.employee_id = e.id
JOIN products p ON s.product_id = p.id;

В этом запросе используется LEFT JOIN для получения всех записей из таблицы sales, даже если у некоторых сделок нет информации о клиенте или сотруднике (например, если одно из этих полей равно NULL). INNER JOIN в данном случае исключил бы такие записи.

Пример: INNER JOIN и исключение строк с NULL

SELECT s.id, c.name, e.name, p.name
FROM sales s
JOIN customers c ON s.customer_id = c.id
JOIN employees e ON s.employee_id = e.id
JOIN products p ON s.product_id = p.id;

Здесь INNER JOIN приведет к тому, что сделки, у которых customer_id или employee_id равно NULL, не будут включены в результаты.

Заключение

Понимание принципов троичной логики в реляционных базах данных, поддерживающих Transact-SQL, является критически важным аспектом для обеспечения корректной и предсказуемой обработки данных. Способность правильно интерпретировать результаты операций с NULL и учитывать поведение логических выражений с использованием значений TRUE, FALSE и UNKNOWN позволяет избежать ошибок при выполнении запросов, особенно при работе с отсутствующими или неопределенными данными. Внимательное отношение к этим аспектам помогает проектировать более надежные и точные SQL-запросы, улучшая качество и точность обработки информации в базе данных.

Все лабораторные составлены на основании стандарта с перечнем профессиональных компотенций "Цифрового куратора". Ознакомиться с ним можно по ссылке.

Лабораторная работа 1: Основы работы с облачными презентациями (Google Slides)

Цель: Развитие навыков работы с облачными сервисами для создания презентаций и публичного выступления.

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

Практическая часть: Необходимо создать презентацию на одну из предложенных тем:

  • Защита персональных данных в интернете.
  • Противодействие фейковым новостям.
  • Основы работы с государственными онлайн-сервисами.
  • Угрозы кибербезопасности и методы защиты.

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

Лабораторная работа 2: Интерактивные образовательные материалы в Quizlet

Цель: Освоение инструментов для создания интерактивных обучающих материалов с использованием платформы Quizlet.

  • Введение в интерактивные образовательные материалы.
  • Примеры использования Quizlet для обучения и тестирования.

Практическая часть: Создание набора карточек по теме:

  • Основные угрозы в интернете (вирусы, фишинг, мошенничество, ...).

Лабораторная работа 3: Сбор и анализ информации с использованием Google Forms

Цель: Формирование навыков сбора данных и анализа информации с помощью онлайн-инструментов.

  • Принципы создания опросов.
  • Использование Google Forms / Яндекс Форм для сбора данных.
  • Методы анализа результатов.

Практическая часть:

  • Создание анкеты на тему «Уровень цифровой грамотности населения».
  • Рассылка анкеты и сбор данных среди студентов или в учебной группе.
  • Анализ полученных данных с последующим обсуждением результатов (при проведении анализа необходимо оперирровать статистическими данными, для большей наглядности лучше использовать инфографику и визуализировать полученные данные).

Лабораторная работа 4: Разработка руководства по цифровой безопасности

Цель: Формирование навыков разработки практических руководств и совместной работы в облачных сервисах.

  • Введение в информационную безопасность.
  • Способы защиты данных и цифровой грамотности.

Практическая часть:

  • Поиск и сбор информации о современных методах защиты данных.
  • Создание практического руководства по безопасному поведению в интернете с использованием Google Docs.
  • Совместное редактирование документа в группе.

Лабораторная работа 5: Организация вебинаров и дистанционных мероприятий

Цель: Освоение навыков организации и проведения онлайн-мероприятий для цифрового кураторства.

  • Обзор инструментов для проведения вебинаров (Zoom, Google Meet).
  • Основные правила модерации онлайн-мероприятий.

Практическая часть:

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

Лабораторная работа 6: Подготовка информационных листовок и буклетов

Цель: Освоение навыков создания информационных материалов для широкой аудитории с использованием доступных онлайн-инструментов.

  • Основы визуального оформления информационных материалов.
  • Использование инструментов для создания буклетов и листовок (Publisher, Figma, ...).

Практическая часть:

  • Разработка информационного буклета на тему «Как начать использовать государственные электронные сервисы». Описать преимущества использования Госуслуг.
  • Совместная работа над проектом с распределением обязанностей в группе.

Лабораторная работа 7: Создание и продвижение образовательного контента в социальных сетях

Цель: Развитие навыков продвижения образовательного контента в социальных сетях.

  • Основы продвижения образовательного контента в интернете.
  • Обзор платформ социальных сетей для цифрового кураторства.

Практическая часть:

  • Разработка и публикация серии постов по теме «Основы цифровой безопасности» в социальной сети.
  • Анализ взаимодействия пользователей с контентом.

Лабораторная работа 8: Поиск и проверка информации в интернете

Цель: Развитие критического мышления и навыков проверки информации в интернете.

  • Методы эффективного поиска информации в интернете.
  • Критерии оценки достоверности источников.

Практическая часть:

  • Поиск информации по заданной теме (например, современные угрозы в киберпространстве).
  • Анализ достоверности и источников информации с созданием краткого отчета.

Лабораторная работа: Реализация симплекс метода

Прочитать про разбор симплекс-метода можно здесь.

Обшие требования как к обычному, так и к усложненному варианту:

  1. Входные данные:
    • Целевая функция.
    • Система линейных ограничений.
  2. Обязательно должна присутствовать провера на корректность ввода и вывод сообщения для пользователя в случае невозможности решения задачи.
  3. Для реализации можно использовать следующие ЯП: JS, TS, C#, C++, Java, VBA.
  4. В программе должен быть предусмотрен блок тестов для автоматической проверки на типичных задачах. Для проверки собственной программы можно использовать онлайн калькулятор. В нижней части страницы с калькулятором присутствует общий алгоритм решения задач ЛП симплекс-методом.
  5. Должен быть обеспечен удобный ввод и вывод данных.

Простой вариант: Базовый симплекс метод

Ограничения

Решение задач линейного программирования (ЛП) с использованием симплекс метода. Условия:

  • Ограничения могут быть только вида "≤".
  • Все переменные неотрицательны.
  • Целевая функция стремится к максимуму.

Пример задачи

Максимизировать: \[ Z = 2x_1 + 3x_2 \] при условиях: \[ x_1 + 2x_2 \leq 8 \] \[ 2x_1 + x_2 \leq 6 \] \[ x_1, x_2 \geq 0 \]

С примером и разбором решения задачи базовым симплекс-методом можно ознакомиться по ссылке.

Интерфейс

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

Интерфейс симплекс-метода для консоли


Усложненный вариант: Двойственный симплекс метод

Ограничения

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

  • Задачи могут быть как на максимизацию так и на минимизацию.
  • Допускаются различные типы ограничений: "≤", "≥", "=".
  • Переменные могут быть как положительными, так и отрицательными.

Требования к решению

  • Обязательно должен быть реализован GUI.

Пример задачи

Минимизировать: \[ Z = 4x_1 + 6x_2 + 3x_3 \] при условиях: \[ x_1 + 2x_2 - x_3 \geq 5 \] \[ 3x_1 + 2x_2 + x_3 = 8 \] \[ x_1 \geq 0, \quad x_2 \leq 0, \quad x_3 \geq 0 \]

С примером и разбором решения задачи двосйственным симплекс-методом можно ознакомиться по ссылке.

Интерфейс

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

Web GUI

Техническое задание (ТЗ): Программа мониторинга состояния ПК/сервера с интерфейсом

Описание задачи:

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

1. Аппаратная часть:

  • Процессор (CPU):

    • Модель и количество ядер.
    • Частота работы.
  • Оперативная память (RAM):

    • Общий объём.
    • Используемый объём.
    • Свободный объём.
  • Жесткий диск (HDD/SSD):

    • Общий объём диска.
    • Используемое пространство.
    • Свободное пространство.
  • Графический процессор (GPU) (если не встройка):

    • Модель и основные характеристики.

2. Мониторинг системы:

  • Нагрузка на процессор:

    • Текущая загрузка CPU в процентах.
  • Использование оперативной памяти:

    • Объём использованной и свободной памяти RAM.
  • Использование диска (HDD/SSD):

    • Занятое и свободное место на диске.
  • Список всех запущенных процессов с возможностью:

    • Сортировки по объёму потребляемой оперативной памяти.
    • Сортировки по загрузке процессора.
    • Поиска по названию процесса.

3. Настройки программы:

  • Возможность включения/отключения логирования выбранных ключевых показателей. В настройках можно выбрать, какие метрики логировать (например, нагрузку на CPU, использование RAM и т.д.).

Дополнительные требования:

  • Реализовать проверку состояния SMART для HDD/SSD. SMART (Self-Monitoring, Analysis, and Reporting Technology) предоставляет информацию о состоянии накопителя и предсказывает возможные отказы. Основные показатели SMART включают:
    • Температура диска.
    • Количество переназначенных секторов.
    • Время работы диска.
    • Ошибки чтения/записи.

Ограничения:

  • Запрещено использование скриптовых языков программирования (например, Python, AWK, Bash, PowerShell и других).
  • Используемые библиотеки должны быть компилируемыми (например, на C, C++, Rust).

Крайне желательно: В интерфейсе программы должна присутствовать главная страница с Dashboard'ом с возможностью настройки отображаемых метрик. Визуализация должна быть реализована в виде графиков, диаграмм и текстовых полей, напоминающих Grafana.

Grafana Grafana

Лабораторная работа: Логгер

Ознакомиться с ТЗ можно по ссылке.

Руководство по созданию диаграмм с помощью Mermaid и PlantUML

Введение

Разберем как создавать диаграммы с помощью кода на примере Mermaid и PlantUML.


Установка и настройка

Установка Java

Для работы PlantUML необходимо установить Java:

  1. Скачайте Java: Перейдите на официальный сайт Java Downloads и скачайте последнюю версию.
  2. Установите Java: Следуйте инструкциям установщика для вашей операционной системы.
  3. Проверьте установку: В командной строке введите java -version, чтобы убедиться, что Java установлена корректно.

Установка Visual Studio Code

Скачайте и установите Visual Studio Code с официального сайта:

Установка расширений

  1. Mermaid Markdown Syntax Highlighting
  2. PlantUML (jebbs.plantuml)
  3. Markdown Preview Enhanced

Поддерживаемые диаграммы

Оба инструмента, Mermaid и PlantUML, поддерживают следующие типы диаграмм:

  • Графы
  • Блок-схемы
  • Диаграммы Ганта
  • Диаграммы последовательностей
  • ER-диаграммы (для Mermaid)
  • Диаграммы классов (для PlantUML)
  • Диаграммы состояний (для PlantUML)
  • Диаграммы активности (для PlantUML)
  • ...

С полным перечнем можно ознакомиться в официальной документации: Mermaid и PlantUML.


Создание диаграмм с помощью Mermaid

Mermaid — это простой и мощный инструмент для создания диаграмм с использованием текста.

Пример диаграммы

graph LR
    A[Начало] --> B{Вопрос?}
    B -- Да --> C[Действие 1]
    B -- Нет --> D[Действие 2]
    C --> E[Конец]
    D --> E[Конец]

Стилизация диаграмм

Диаграммы Mermaid можно стилизовать с помощью CSS и встроенных тем.

Пример стилизации:

graph LR
  A[Начало] --> B{Вопрос?}
  B -- Да --> C[Действие 1]
  B -- Нет --> D[Действие 2]
  C --> E[Конец]
  D --> E[Конец]

classDef default fill:#f9f,stroke:#333,stroke-width:2px;
class A,C,E default;

Рендеринг онлайн

Диаграммы Mermaid можно рендерить онлайн через mermaid.live.


Создание диаграмм с помощью PlantUML

PlantUML — это мощный инструмент для создания UML-диаграмм с помощью текста. PlantUML требует установки Java для рендеринга диаграмм.

Пример диаграммы последовательностей

@startuml
Alice -> Bob : Привет!
Bob --> Alice : Привет, как дела?
@enduml

Пример диаграммы классов

@startuml
class Animal {
  +String name
  +int age
  +run()
}

class Dog {
  +String breed
  +bark()
}

Animal <|-- Dog
@enduml

Пример диаграммы состояний

@startuml
[*] --> Idle
Idle --> Processing : Start
Processing --> Finished : Process complete
Finished --> [*]
@enduml

Пример диаграммы активности

@startuml
:start: -> :Request received;
if (Valid request?) then (yes) 
    -> :Process request;
    -> :Send response;
else (no)
    -> :Error;
endif
-> :End;
@enduml

Стилизация диаграмм

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

Пример стилизации:

@startuml
skinparam backgroundColor #EEEBDC
skinparam handwritten true
Alice -> Bob : Привет!
Bob --> Alice : Привет, как дела?
@enduml

Рендеринг онлайн

PlantUML диаграммы можно рендерить онлайн через PlantUML онлайн рендерер.

Техническое задание на построение DFD

Задача 1: Оформление заказа в интернет-магазине

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


Задача 2: Процесс подачи и рассмотрения заявки на кредит в банке

Клиент подает заявку на кредит через онлайн-форму на сайте банка. В заявке указываются личные данные клиента (ФИО, паспортные данные) и сумма кредита. После получения заявки система банка запрашивает кредитную историю клиента в внешней кредитной базе. После получения кредитной истории банк анализирует данные и принимает решение. Если решение положительное, клиенту отправляется уведомление с одобрением кредита и дальнейшими инструкциями. Если решение отрицательное, клиенту отправляется отказ с указанием причин.


Задача 3: Процесс найма сотрудника в компанию

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

Задача 1: Бронирование столика в ресторане

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

Пример
  • Пользователь: Выбрать ресторан, указать дату и время, подтвердить бронирование.
  • Система: Проверить наличие столиков, подтвердить бронирование, отправить уведомление.
  • Администратор ресторана: Просмотреть бронирования, изменить или отменить бронирование.

Задача 2: Управление расписанием занятий в школе

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

Пример
  • Учитель: Создать расписание, редактировать уроки, указать кабинеты.
  • Ученик: Просмотреть расписание, получить уведомление об изменениях.
  • Администратор школы: Управлять общим расписанием, утверждать расписания, отправлять уведомления.

Задача 3: Регистрация на конференцию

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

Пример
  • Участник: Выбрать тип участия, заполнить форму регистрации, оплатить взнос.
  • Система: Отправить подтверждение регистрации, предложить оплату взноса.
  • Организатор конференции: Просматривать участников, редактировать информацию, отправлять объявления.

Задача 4: Обслуживание автомобиля в автосервисе

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

Пример
  • Клиент: Выбрать тип услуги, указать данные автомобиля, записаться на обслуживание.
  • Система: Проверить доступность времени, отправить уведомление менеджеру.
  • Менеджер автосервиса: Подтвердить запись, распределить работу.
  • Механик: Внести информацию о выполненных работах, подтвердить завершение.

Задача 1: Оформление заказа в интернет-магазине

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

Задача 2: Процесс подачи и рассмотрения заявки на кредит в банке

Клиент подает заявку на кредит через онлайн-форму на сайте банка. В заявке указываются личные данные клиента (ФИО, паспортные данные) и сумма кредита. После получения заявки система банка запрашивает кредитную историю клиента в внешней кредитной базе. После получения кредитной истории банк анализирует данные и принимает решение. Если решение положительное, клиенту отправляется уведомление с одобрением кредита и дальнейшими инструкциями. Если решение отрицательное, клиенту отправляется отказ с указанием причин.

Задача 3: Регистрация пользователя на онлайн-платформе

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

Задача 4: Процесс отправки сообщения в мессенджере

Пользователь пишет и отправляет сообщение в мессенджере. Клиентское приложение передает сообщение на сервер мессенджера. Сервер проверяет наличие получателя и пересылает сообщение. Адресат получает уведомление и читает сообщение. Сервер уведомляет отправителя о доставке и прочтении сообщения.

Диаграмма WBS

Диаграмма WBS (Work Breakdown Structure), или Иерархическая Структура Работ, представляет собой инструмент проектного управления, который позволяет структурировать все работы, необходимые для достижения целей проекта.

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

Компоненты диаграммы WBS

В основе диаграммы WBS лежит принцип декомпозиции, где каждый уровень иерархии представляет более детальное разбиение работ:

  1. Проект: самый верхний уровень, представляющий весь проект в целом.
  2. Этапы или фазы: крупные блоки работ, разделяющие проект на основные части (например, планирование, разработка, тестирование).
  3. Пакеты работ: более детальные задачи внутри этапов, которые могут быть назначены конкретным исполнителям или командам.
  4. Задачи и действия: самые мелкие единицы работ, имеющие конкретные цели, сроки и ресурсы.

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

Пример применения WBS

Рассмотрим проект по организации конференции:

Проект: Организация конференции

  1. Планирование
    • Определение темы и целей конференции
    • Формирование команды
    • Составление бюджета
  2. Маркетинг и продвижение
    • Разработка маркетинговой стратегии
    • Создание рекламных материалов
    • Продвижение в социальных сетях
  3. Логистика
    • Выбор и бронирование площадки
    • Организация питания и проживания
    • Транспортная логистика
  4. Проведение конференции
    • Регистрация участников
    • Техническое обеспечение
    • Обслуживание гостей

Диаграмма WBS с PlantUML

Использование диаграммы WBS

Диаграмма WBS служит основой для многих процессов управления проектом:

  • Планирование: помогает определить полный объем работ и установить последовательность выполнения задач.
  • Управление ресурсами: облегчает идентификацию необходимых ресурсов.
  • Оценка стоимости и сроков: позволяет более точно оценить бюджет и временные рамки.
  • Управление рисками: выявляет потенциальные риски на ранних этапах.
  • Коммуникация: обеспечивает прозрачность и ясность для всех членов команды.
  • Контроль и мониторинг: предоставляет четкие критерии для отслеживания прогресса.

Применение в создании Sitemap

WBS используется в веб-разработке для создания Sitemap:

Пример структуры сайта интернет-магазина:

  1. Главная страница
  2. Каталог товаров
    • Электроника
      • Смартфоны
      • Ноутбуки
    • Одежда
      • Мужская
      • Женская
    • Дом и сад
      • Мебель
      • Декор
  3. О нас
    • История компании
    • Команда
  4. Блог
    • Статьи
    • Новости
  5. Контакты
    • Форма обратной связи
    • Карта проезда

Диаграмма WBS с PlantUML

Инструменты для создания диаграмм WBS

  • Microsoft Project — программное обеспечение для управления проектами.
  • MindManager — программа для создания ментальных карт. MindManager WBS
  • Lucidchart — онлайн-сервис для создания диаграмм. Lucidchart WBS
  • Draw.io * — бесплатный онлайн-инструмент для создания диаграмм. Draw.io
  • PlantUML * — инструмент с открытым исходным кодом для текстового описания диаграмм.

* - рекомендую обратить особое внимание

PlantUML и создание WBS

PlantUML позволяет создавать диаграммы WBS с помощью простого текстового описания. Пример:

@startwbs OnlineStore_Sitemap

skinparam backgroundColor transparent

<style>
wbsDiagram {
  arrow {
    LineColor #4CAF50
    LineThickness 0.5
  }

  :depth(0) {
    BackgroundColor #F1F8E9
    LineColor #388E3C
    LineThickness 3
  }

  :depth(1) {
    BackgroundColor #C8E6C9
    LineColor #388E3C
    LineThickness 2
  }

  :depth(2) {
    BackgroundColor #A5D6A7
    LineColor #388E3C
    LineThickness 1.5
  }

  :depth(3) {
    BackgroundColor #81C784
    LineColor #388E3C
    LineThickness 1
  }

  node {
    Roundcorner 15
    Margin 10
    MaximumWidth 275
    FontColor #212121
    FontSize 12
  }
}

legend {
  Roundcorner 15
  backgroundColor #F1F8E9
  entrySeparator #F1F8E9
}

</style>

* Проект "Модернизация IT-инфраструктуры"

** Оценка и анализ
*** Сбор данных и анализ оборудования
*** Анализ программного обеспечения

** Планирование и бюджетирование
*** Разработка плана и бюджета
*** Определение требований к оборудованию и ПО

** Закупка и внедрение
*** Выбор поставщиков и заказ оборудования
*** Установка оборудования и настройка ПО

** Тестирование и обучение
*** Тестирование и обучение персонала

** Поддержка
*** Техническая поддержка и обновления

@endwbs

Задания для тренировки:

Задание 1: Разработка мобильного приложения для фитнес-трекера

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

Основные этапы
  • Сбор требований;
  • Дизайн интерфейса;
  • Разработка функционала;
  • Тестирование;
  • Запуск и поддержка.

Задание 2: Организация выставки современного искусства

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

Основные этапы
  • Планирование и подготовка;
  • Работа с художниками;
  • Маркетинг и продвижение;
  • Логистика и установка экспонатов;
  • Мероприятие открытия и закрытия;
  • Последующие действия после выставки.

Задание 3: Строительство и запуск интернет-кафе

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

Основные этапы
  • Подготовка и планирование;
  • Ремонт и оснащение помещения;
  • Установка технического оборудования;
  • Юридические аспекты и лицензирование;
  • Подбор и обучение персонала;
  • Маркетинг и продвижение;
  • Открытие и дальнейшая деятельность.

Задание 4: Проведение научно-исследовательского проекта

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

Основные этапы
  • Планирование исследования;
  • Проведение экспериментов;
  • Анализ и интерпретация данных;
  • Подготовка публикаций;
  • Участие в конференциях;
  • Управление проектом.

Диаграмма MindMap

Диаграмма MindMap (ментальная карта) — инструмент визуализации, который помогает структурировать информацию, идеи или задачи вокруг центральной концепции. Она широко применяется в программировании и управлении проектами для документирования систем, планирования архитектуры, разработки маршрутов API и создания дорожных карт проектов.

Основные элементы и применение MindMap

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

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

MindMap нашла свое применение в различных сферах деятельности:

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

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

Особое распространение ментальная карта получила при работе в командах, поскольку она хоророшо подходит мозговых штурмов и позволяет в удобном формате представить задачи из различных систем управления проектами: Jira, Trello и др.

Примеры использования MindMap

1. Документирование архитектуры системы микросервисов

Архитектура микросервисной системы для онлайн-платформы электронной коммерции.

  • API Gateway
    • Маршрутизация запросов
    • Аутентификация
    • Балансировка нагрузки
  • Сервис управления пользователями
    • Регистрация и аутентификация
    • Профили пользователей
    • Управление ролями и правами доступа
  • Сервис каталога товаров
    • Управление товарами
    • Категоризация
    • Поиск и фильтрация
  • Сервис корзины и заказов
    • Корзина покупок
    • Оформление заказа
    • История заказов
  • Сервис платежей
    • Интеграция с платежными шлюзами
    • Обработка транзакций
    • Возвраты и возмещения
  • Сервис уведомлений
    • Email-рассылки
    • SMS-уведомления
    • Push-уведомления
  • Инфраструктура
    • Оркестрация (Kubernetes)
    • Мониторинг (Prometheus, Grafana)
    • Логирование (ELK Stack)
  • Безопасность
    • SSL/TLS шифрование
    • Защита от DDoS
    • Контроль доступа

Microservices_Architecture

2. Планирование дорожной карты проекта (Roadmap)

Дорожная карта разработки SaaS-платформы (software as a service) для управления проектами.

  • Q1 2024
    • Модуль управления задачами
      • Создание и назначение задач
      • Канбан-доска
      • Приоритеты и статусы
    • Базовая аутентификация
      • Регистрация пользователей
      • Вход по email и паролю
    • Интеграция с календарями
      • Синхронизация с Google Calendar
      • Напоминания о дедлайнах
  • Q2 2024
    • Модуль командной работы
      • Чат внутри приложения
      • Совместное редактирование документов
      • Уведомления в реальном времени
    • Улучшение безопасности
      • Двухфакторная аутентификация
      • Роль-based Access Control (RBAC)
    • Мобильное приложение
      • Версия для iOS
      • Версия для Android
  • Q3 2024
    • Модуль аналитики
      • Отчеты по производительности
      • Дашборды для менеджеров
    • Интеграции с сторонними сервисами
      • Slack
      • Jira
      • GitHub
    • Масштабирование инфраструктуры
      • Автоматическое масштабирование серверов
      • Оптимизация базы данных
  • Q4 2024
    • Модуль управления ресурсами
      • Планирование загрузки сотрудников
      • Отслеживание времени (time tracking)
    • Многоязычная поддержка
      • Локализация на основные языки
      • Поддержка разных часовых поясов
    • Подготовка к публичному запуску
      • Маркетинговая кампания
      • Обучающие материалы и документация

SaaS-Roadmap

Инструменты для создания MindMap

Существует множество инструментов для создания ментальных карт:

  • Visual Paradigm — мощный инструмент для моделирования и документирования систем.
  • Coggle — онлайн-сервис для совместной работы над MindMap.
  • Draw.io * — бесплатный онлайн-инструмент для создания диаграмм, поддерживает интеграцию с GitHub.
  • PlantUML * — инструмент для текстового описания и генерации диаграмм, поддерживает MindMap.
  • MindManager — профессиональное ПО для создания MindMap с расширенными возможностями.
  • XMind — кроссплатформенное приложение для создания ментальных карт.

* - рекомендую обратить особое внимание

Cоздание MindMap при помощи PlantUML

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

@startmindmap API
skinparam BackgroundColor transparent

title API Архитектура
left side
* /api/v1
** /login
** /register
** /users
*** /{id}
**** GET
**** PUT
right side
** /transactions
*** /
**** GET
**** POST
** /notifications
*** /email
**** POST
*** /push
**** POST
@endmindmap

API

Например, при помощи MindMap можно также отобразить навигационную структуру веб-сайта:

Sitemap_PlantUML

Задания для тренировки:

Задание 1: Разработка комплексной системы управления контентом (CMS)

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

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

Возможный вариант MindMap:
  1. Контентные модули

    • Типы контента:
      • Статьи
      • Видео
      • Подкасты
      • Галереи изображений
    • Редактор контента:
      • WYSIWYG-редактор
      • Поддержка drag-and-drop
      • Управление медиафайлами
    • Организация контента:
      • Теги
      • Категории
      • Метаданные (SEO)
  2. Управление пользователями

    • Роли и права доступа:
      • Автор
      • Редактор
      • Администратор
      • Гость
    • Аутентификация:
      • Локальная (логин/пароль)
      • SSO (OAuth2, LDAP)
    • Профили пользователей:
      • Настройки
      • Персонализация
  3. Интеграции

    • Социальные сети:
      • Facebook
      • Twitter
      • Instagram
    • Импорт/Экспорт контента:
      • RSS-фиды
      • API сторонних сервисов
    • Уведомления:
      • Email-рассылки
      • Push-уведомления
  4. Аналитика

    • Сбор метрик:
      • Просмотры
      • Лайки/Реакции
      • Комментарии
    • Отчеты:
      • Еженедельные отчеты
      • Ежемесячные отчеты
      • Дашборды для редакторов и администраторов
    • Интеграция с аналитическими сервисами:
      • Google Analytics
      • Яндекс.Метрика
  5. Безопасность и производительность

    • Безопасность:
      • SSL/TLS шифрование
      • Защита от SQL-инъекций
      • Защита от XSS-атак
      • Логирование и мониторинг
    • Производительность:
      • Кэширование:
        • Redis
        • Memcached
      • CDN для статического контента
      • Балансировка нагрузки

Задание 2: Проектирование и документирование RESTful API для финансового приложения

Предметная область: Вы разрабатываете финансовое приложение, которое предоставляет пользователям возможность управлять своими личными финансами: отслеживать доходы и расходы, устанавливать бюджеты, анализировать финансовые данные. Необходимо спроектировать и задокументировать RESTful API, которое будет использоваться мобильными и веб-клиентами.

Требования:

  • Пользователи:
    • Регистрация и аутентификация.
    • Управление профилем.
  • Счета:
    • Создание разных типов счетов (банковский, наличные, кредитная карта).
    • Получение баланса по счетам.
  • Транзакции:
    • Добавление доходов и расходов.
    • Категоризация транзакций.
    • Поддержка повторяющихся транзакций.
  • Бюджеты:
    • Установка месячных и годовых бюджетов.
    • Отслеживание превышения бюджета.
  • Аналитика:
    • Генерация отчетов по периодам.
    • Диаграммы расходов и доходов.
  • Безопасность:
    • Шифрование данных.
    • Ограничение доступа по токенам.
Возможный вариант решения:
  • Аутентификация
    • POST /api/v1/login
    • POST /api/v1/register
  • Пользователи
    • GET /api/v1/users/{id}
    • PUT /api/v1/users/{id}
  • Счета
    • GET /api/v1/accounts
    • POST /api/v1/accounts
    • GET /api/v1/accounts/{id}
    • PUT /api/v1/accounts/{id}
    • DELETE /api/v1/accounts/{id}
  • Транзакции
    • GET /api/v1/transactions
    • POST /api/v1/transactions
    • GET /api/v1/transactions/{id}
    • PUT /api/v1/transactions/{id}
    • DELETE /api/v1/transactions/{id}
  • Бюджеты
    • GET /api/v1/budgets
    • POST /api/v1/budgets
    • GET /api/v1/budgets/{id}
    • PUT /api/v1/budgets/{id}
    • DELETE /api/v1/budgets/{id}
  • Аналитика
    • GET /api/v1/reports/summary
    • GET /api/v1/reports/category
  • Безопасность
    • Использование HTTPS
    • Токены доступа (JWT)