## 1. API
API - это публичный интерфейс сервиса: то, чем потребитель сервиса может пользоваться.
Примеры:
- На ПлюсАгенте есть бэкенд (код на сервере) и фронтенд (код в браузере). Бэкенд предоставляет различные адреса, по которому фронтенд может сделать запрос и получить ответ (например, получение списка агентов). Это и называется API бэкенда ПлюсАгент.
- Сервис GreenApi предоставляет различные адреса, по которому можно делать запросы для взаимодействия с WhatsApp (например, отправить сообщение). Это - API сервиса GreenApi.
Если описаны инструкции по тому, какие именно запросы поддерживаются, то это - документация к API.
## 2. HTTP
HTTP - это протокол взаимодействия по сети. Чаще всего API сервиса подразумевает взаимодействие по HTTP (из примеров выше: и бекенд ПлюсАгент, и GreenApi работают по HTTP).
HTTP запрос состоит из следующих частей:
- HTTP Метод:
- GET запрос обычно делается для получения информации
- POST запрос обычно делается для изменения информации
- подробнее о методах в разделе про REST
- Путь запроса - например `/api/agent`; похоже на путь к файлу в файловой системе
- Заголовки запроса - в них передаётся различная служебная информация; нам они сейчас не обязательны
- Тело запроса - здесь передаётся информация, которую нам надо записать (например, текст сообщения для WhatsApp); у GET-запросов нет тела, так как они ничего не записывают
Пример: браузеры и сайты тоже общаются по HTTP; поэтому, когда мы что-то ищем в Гугле, то мы делаем вот такой запрос:
- HTTP метод GET, так как мы получаем информацию
- Путь запроса: https://www.google.com/search?q=Сургут (здесь `q=Сургут` - это параметр запроса)
- Заголовки запроса: разная служебная информация, например, версия нашего браузера
- Тело запроса: пустое, потому-что GET
В результате отправки HTTP запроса мы получаем HTTP ответ (логично). У ответа есть "статус" - это числовой код, по которому можно понять, успешен ли запрос. Топ 3 статусов:
- 200: всё хорошо
- 404: ресурс не найден
- 500: ошибка на сервере
## 3. REST
REST - это стиль построения API, основанный на использовании HTTP с дополнительными ограничениями. Чтобы было понятнее, я сначала приведу пример REST и не-REST API.
Пример: скажем, мы делаем бэкенд для ПлюсАгент и создаём возможность создать агента и получить информацию об агентах.
REST подход:
- Получение списка агентов: `GET /api/agent`
- Получения данных агента с ID 123: `GET /api/agent/123`
- Создание агента: `POST /api/agent` (в теле запроса - данные об агенте)
- Обновление данных агента с ID 123: `PUT /api/agent/123` (в теле запроса - данные об агенте)
- Удаление риелтора с ID 123: `DELETE /api/agent/123`
Не-REST подход:
- Получение списка агентов: `GET /api/get-agents`
- Получения данных агента с ID 123: `GET /api/get-agent?id=123`
- Создание агента: `POST /api/create-agent` (в теле запроса - данные об агенте)
- Обновление данных агента с ID 123: `POST /api/update-agent?id=123` (в теле запроса - данные об агенте)
- Удаление риелтора с ID 123: `POST /api/delete-agent?id=123`
Правила REST:
- Путь запроса - это путь к какому-то ресурсу (напрмер, `/api/agent`; обычно - это существительное)
- Мы описываем то, что мы хотим сделаем с помощью HTTP метода (это глагол):
- GET - получить данные о ресурсе
- POST - создать ресурс
- PUT - обновить ресурс
- DELETE - удалить ресурс
- Сервер не обязан хранить информацию о предыдущем запросе - каждый запрос должен содержать достаточно информации, чтобы его обработать (поэтому говорят, что "REST - это протокол без состояния")
## 4. SQL
Основные запросы:
- Создать таблицу агентов: `CREATE TABLE agents (id INT PRIMARY KEY, name VARCHAR(), createdAt TIMESTAMP())`
- Получить всех агентов: `SELECT * FROM agents`
- Получить одного агента: `SELECT * FROM agents WHERE id = 1`
- Добавить агента: `INSERT INTO agents (id, name, createdAt) VALUES (1, "Александр", "2022-10-02 17:00:00")`
- Обновить агента: `UPDATE agents SET name = "Алексей" WHERE id = 1`
- Удалить агента: `DELETE FROM agents WHERE id = 1`
## 5. ООП
ООП - это парадигма программирования (подход к программирования), в которой объединяются данные и поведение.
Это реализуется с помощью классов. Класс - это описание какой-либо сущности в программе - то, какие в нём есть данные (в ОПП это называется "свойства"; ближайший аналог - переменная) и какое у него есть поведение (в ООП это называется "метод"; ближайший аналог - процедура).
Пример: класс "круг"; у него объявлено:
- Свойства "x" (число), "y" (число), "радиус" (число)
- Метод "получить площадь" (возвращает число; это процедура, которая рассчитывает формулу π × r^2)
В псевдо-коде это выглядит так:
```
класс Круг {
x: число
y: число
радиус: число
получитьПлощадь(): число {
вернуть 3,1415 * радиус * радиус
}
}
```
Объект - это экземпляр класса. В объекте те свойства, что объявлены в классе могут получать конкретные данные; например:
```
мойКруг = новый Круг()
мойКруг.x = 1
мойКруг.y = 1
```
ООП имеет 3 свойства:
1. Инкапсуляция (от слова капсула) - это как раз и есть объединение данных и поведения в одном месте.
Также, в некоторых ООП-языках поддерживается "сокрытие" - возможность объявить некоторые методы и свойства приватными. Приватные методы недоступны "снаружи" класса. Это делается для того, чтобы дать программисту создателю-класса возможность обозначить "внутренности" класса от его публичного интерфейса. Тогда другому програамисту для понимания того, что можно сделать к этим классом, достаточно посмотреть только на публичные методы и свойства.
Пример: мы убрали операцию возведения в степень в отдельную функция. Однако программисту, который будет пользоваться классом "Круг" не обязательно знать, что у класса есть такой метод, так что сделаем его приватным:
```
класс Круг {
x: число
y: число
радиус: число
получитьПлощадь(): число {
вернуть 3,1415 * вСтепень(радиус)
}
приватно вСтепень(a: число) {
вернуть a * a
}
}
```
2. Наследование - возможность наследовать классы от других классов; при наследовании классы автоматически получают свойства и методы от родительских классов; пример:
```
класс Фигура {
x: число
y: число
}
класс Круг расширяет Фигура {
радиус: число
}
```
В этом примере у класса Круг будут свойства `x` и `y`.
3. Полиморфизм - возможность использвать наследников вместо родительских классов.
Пример - у в программе нас есть метод для определения координатной четверти центра фигуры:
```
получитьЧетверть(фигура: Фигура): число {
если (x > 0 и y > 0) то вернуть 1
...
}
```
Мы легко можем отправить в этом метод наш Круг, если он наследуется от класса Фигура:
```
мойКруг = новый Круг()
мойКруг.x = 1
мойКруг.y = 1
получитьЧетверть(мойКруг) <-- вернёт 1 четверть
```