Post

Срез 7

Изучение теории. Неделя 7

Срез 7

1. Jest, Enzyme and other tools

1.1. Основы использования Jest и Enzyme

  • Jest — это фреймворк для тестирования JavaScript, который предоставляет функции для написания тестов, проверки результатов и создания моков
  • Enzyme — это библиотека для тестирования React-компонентов, позволяющая рендерить их и взаимодействовать с ними

Вместе они используются для тестирования логики и UI.

1.2. Типы тестов в Jest

Jest поддерживает основные типы тестов:

  • Unit-тесты проверяют отдельные функции или модули изолированно
  • Integration-тесты проверяют взаимодействие нескольких модулей между собой
  • Snapshot-тесты сравнивают вывод компонента с сохраненным “снимком”

1.3. Snapshot-тестирование в Jest

Snapshot-тестирование — это мощный инструмент Jest для проверки того, что UI компонента не меняется неожиданно.

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

1.4. Симуляция событий и доступ к пропсам в Enzyme

Enzyme предоставляет простые методы для симуляции пользовательских событий, таких как click, change или submit. Для этого используется метод .simulate('eventName') на найденном элементе.

Доступ к пропсам осуществляется через методы .props() или .prop(key) для получения конкретного пропа. Это позволяет легко проверять, как компонент реагирует на ввод пользователя и корректно ли передает данные через пропсы.

1.5. Мокирование функций и модулей в Jest

Jest предоставляет мощные встроенные средства для мокирования:

  • Функции можно замокать с помощью jest.fn(), чтобы отслеживать их вызовы и возвращаемые значения
  • Модули подменяются с помощью jest.mock('module-path'), что позволяет изолировать тестируемый код от внешних зависимостей, таких как API-запросы или сторонние библиотеки

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


1.6. Тестирование состояний компонентов в Enzyme

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

1.7. Тестирование компонентов с использованием Context и HOCs

  • При тестировании компонентов с Context их нужно оборачивать в Provider и передавать нужное значение
  • HOC тестируются через проверку результата их работы — либо рендерится обёрнутый компонент, либо альтернативный UI

1.8. Шаблоны тестирования для React компонентов

Существует несколько устоявшихся шаблонов.

  • Presentational Components фокусируется только на рендеринге (UI) на основе полученных пропсов
  • Container Components проверяет, как компонент управляет состоянием и обрабатывает колбэки
  • Arrange / Act / Assert (AAA) задаёт универсальный шаблон для любого теста: настройка, выполнение действия и проверка результата

Использование этих шаблонов делает тесты последовательными и понятными.

1.9. Тестирование специфических UI элементов, таких как модальные окна

Тестирование модальных окон и других порталов имеет свою специфику. Важно проверить, что окно открывается и закрывается по правильным условиям (например, по клику на кнопку). Поскольку модальные окна часто рендерятся вне главного DOM-дерева, для их поиска в тестах может потребоваться использование методов вроде document.body.querySelector. Также нужно проверять обработчики событий, такие как закрытие по клику на оверлей или клавише Escape.

1.10. Тестирование синтетических событий и утилитарных функций в React

  • Синтетические события React можно тестировать, создавая объекты событий вручную и передавая их в обработчики. Jest позволяет проверить, был ли вызван обработчик и с правильными ли аргументами
  • Утилитарные функции, не зависящие от React, следует тестировать изолированно, как обычный JavaScript-код, передавая им входные данные и проверяя ожидаемый вывод. Это одни из самых надежных и быстрых тестов

2. Snapshot testing, components testing

2.1. Основы React: компоненты, пропсы, состояние и JSX

  • React — это библиотека для построения пользовательских интерфейсов на основе компонентов
  • Компоненты — это переиспользуемые функции, которые возвращают JSX-разметку
  • Пропсы — это входные данные, передаваемые компоненту от родителя, они доступны только для чтения
  • Состояние — это внутренние данные компонента, которые могут меняться и влияют на его рендер
  • JSX — это синтаксическое расширение, позволяющее писать HTML-подобный код внутри JavaScript, который затем преобразуется в вызовы React.createElement

2.2. Обработка событий и условный рендеринг в React

Обработка событий в React похожа на HTML, но с синтаксисом camelCase (например, onClick). В качестве обработчика передается функция, а не строка.

Условный рендеринг реализуется с помощью JavaScript-операторов внутри JSX. Можно использовать оператор if, тернарный оператор condition ? result_true : result_false или логический оператор && для рендера элементов только при выполнении определенных условий. Это позволяет динамически изменять интерфейс в зависимости от состояния приложения.

2.3. Классовые и функциональные компоненты: различия и жизненный цикл

Классовые компоненты используют ES6-классы и методы жизненного цикла, такие как componentDidMount и componentDidUpdate.

Функциональные компоненты — это функции, возвращающие JSX-разметку и использующие хуки для состояния и побочных эффектов (useState, useEffect). Хуки по сути заменили необходимость в классовых компонентах, предложив более простой и удобный способ управления логикой компонента.

2.4. Управление состоянием и виртуальный DOM

Управление состоянием — это ключевая концепция React. Когда состояние компонента меняется (через setState или useState), React планирует повторный рендер.

Виртуальный DOM — это легковесное представление реального DOM в памяти. React сравнивает предыдущую и новую версию Virtual DOM после изменения состояния и вычисляет минимальный набор операций для обновления реального DOM, что обеспечивает высокую производительность.

2.5. Списки и ключи в React

Для рендера списка элементов используется метод map(), который возвращает массив JSX-элементов.

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


2.6. Основы тестирования снимков (snapshot testing) в React

Snapshot-тестирование — это техника, при которой вывод компонента (например, его HTML-разметка) сохраняется в специальный файл и используется как эталон для последующих сравнений. При каждом запуске теста текущий вывод компонента сравнивается с сохраненным снимком. Если они различаются — тест падает, предупреждая о неожиданном изменении UI. Это позволяет быстро обнаруживать непреднамеренные изменения в интерфейсе.

2.7. Реализация и обновление снимков в тестировании компонентов

Для создания снапшота обычно используется метод .toMatchSnapshot() из Jest. При первом запуске теста создается файл снимка.

Если вывод компонента намеренно изменен, снимок нужно обновить. В Jest это делается запуском тестов с флагом --updateSnapshot или в интерактивном режиме. Важно внимательно проверять изменения в снимке перед его обновлением, чтобы не зафиксировать реальную ошибку.

2.8. Преимущества и ограничения тестирования снимков

Главное преимущество — простота и скорость написания тестов, которые эффективно отлавливают неожиданные изменения в UI.

Однако snapshot-тесты хрупки и могут падать из-за незначительных изменений (например, форматирования). Они не заменяют unit- или integration-тесты, так как не проверяют логику поведения, а лишь фиксируют вывод.

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

2.9. Инструменты и интеграция тестирования снимков в CI/CD

Jest является стандартным инструментом для snapshot-тестирования в React-приложениях. В CI/CD-пайплайне snapshot-тесты запускаются наравне с другими тестами. Если тест падает из-за различия со снимком, пайплайн может быть остановлен, что требует обязательной ручной проверки изменений. Это предотвращает деплой кода с непреднамеренными изменениями UI. Настройка должна запрещать автоматическое обновление снимков на CI-сервере.

2.10. Лучшие практики и минимизация ложных срабатываний в тестировании снимков

Чтобы минимизировать ложные срабатывания, следует использовать snapshot-тесты для относительно стабильных компонентов. Избегайте включения в снимки часто меняющихся или случайных данных (например, временных меток). Для динамических значений используйте моки или сериализаторы (serializers), чтобы стабилизировать вывод. Регулярно обновляйте снимки и удаляйте устаревшие. Не полагайтесь на них как на единственный вид тестирования.

3. React router

3.1. Использование компонента <BrowserRouter>

<BrowserRouter> — это основной роутер для веб-приложений, который использует HTML5 History API (pushState, replaceState, popState) для синхронизации UI с URL в браузере. Он позволяет создавать чистые, красивые URL без хэша (например, /about).

Этот роутер оборачивает всё приложение и предоставляет контекст, необходимый для работы остальных компонентов React Router, таких как <Route> и <Link>. Он является предпочтительным выбором для большинства современных проектов.

3.2. Основные функции компонента <Route>

Компонент <Route> является центральным в React Router. Его основная функция — рендерить определенный UI когда путь (path) в URL совпадает с его пропсом path. Он может рендерить компонент тремя способами: через проп component, проп render (для инлайн-функции) или проп children (который рендерится всегда, независимо от совпадения). <Route> также передает совпавшие параметры URL и другие свойства в рендерящийся компонент.

3.3. Передача параметров в роут

Параметры передаются непосредственно через URL. Для этого в path роута используется синтаксис с двоеточием (:paramName). Например, путь <Route path="/user/:id"> соответствует URL /user/123. Значение параметра id (в данном случае 123) затем становится доступным в компоненте, отрендеренном этим роутом, через хук useParams() или проп match.params. Это стандартный способ динамической маршрутизации.

3.4. Особенности и использование компонента <Switch>

Компонент <Switch> используется для рендера исключительно первого дочернего <Route> или <Redirect>, чей path совпадает с текущим location. Он прекращает поиск после первого совпадения, предотвращая рендер нескольких роутов одновременно. Это критически важно для создания исключающих роутов, таких как страница 404, которая рендерится только если ни один из предыдущих роутов не совпал. В v6 он заменен на <Routes>.

3.5. Перенаправление пользователя с использованием React Router

Для перенаправления используется компонент <Redirect>. Когда он рендерится, он навигационно перенаправляет пользователя на указанный в пропе to путь. Его часто используют внутри <Switch> для обработки устаревших путей или защиты маршрутов. Например, если пользователь не авторизован, <Redirect> может отправить его на страницу логина. В функциональных компонентах для программного перенаправления чаще используется хук useHistory().push().


3.6. Общее понимание работы React Router

React Router — это декларативная библиотека для маршрутизации на клиенте. Она синхронизирует UI вашего React-приложения с URL в браузере. При изменении URL (через <Link> или программную навигацию) React Router находит все совпадающие <Route> и рендерит соответствующие компоненты. Он делает это, предоставляя через контекст объекты history, location и match, которые позволяют компонентам реагировать на изменения URL.

3.7. Реализация защищённых маршрутов (protected route)

Защищенный маршрут — это паттерн, где обычный <Route> оборачивается в компонент-обертку. Эта обертка проверяет условие (например, наличие авторизации пользователя). Если условие истинно, она рендерит запрошенный компонент. Если ложно — перенаправляет на страницу логина с помощью <Redirect>. Это позволяет централизованно управлять доступом и легко повторно использовать логику проверки прав для разных роутов.

3.8. Различия между <BrowserRouter> и <HashRouter>

<BrowserRouter> использует HTML5 History API для создания чистых URL (example.com/about).

<HashRouter> использует хэш-portion URL (example.com/#/about), который сервер игнорирует, всегда отправляя одну и ту же HTML-страницу. BrowserRouter требует поддержки сервером SPA (все URL должны вести на index.html), иначе при прямом заходе или обновлении будет 404. HashRouter проще в настройке на статических серверах, но URL выглядят менее профессионально.

3.9. Использование хуков в React Router (useHistory, useLocation, useParams)

React Router предоставляет несколько хуков для удобства. useHistory() дает доступ к объекту history для программной навигации (push, replace). useLocation() возвращает объект location, представляющий текущий URL. useParams() возвращает объект с ключ/значение параметров URL текущего роута. Эти хуки позволяют легко получать необходимые данные и управлять навигацией внутри функциональных компонентов без использования HOC или пропсов.

3.10. Динамическое изменение маршрутов в React приложении

Маршруты изменяются динамически в ответ на действия пользователя или состояние приложения. Программная навигация осуществляется через history.push('/new-path') или history.replace('/new-path'). Условный рендер разных наборов <Route> или <Redirect> в зависимости от состояния (например, роли пользователя) позволяет создавать адаптивную маршрутизацию. Сам React Router не управляет состоянием, а лишь реагирует на его изменения.

4. Hooks routing

4.1. Использование хука useHistory для доступа и управления историей навигации

Хук useHistory предоставляет прямой доступ к объекту history, который позволяет управлять навигацией программно. Через него можно перенаправлять пользователя с помощью методов push(path) для добавления новой записи в историю или replace(path) для замены текущей записи. Также объект history содержит полезные методы как goBack, goForward и свойства, такие как length, для навигации по истории и анализа стека.

4.2. Использование хука useParams для получения параметров из URL

Хук useParams возвращает объект, содержащий пары ключ-значение всех параметров, определенных в URL текущего маршрута. Если роут определен как path="/user/:userId/post/:postId", то при URL /user/123/post/456 вызов useParams() вернет { userId: "123", postId: "456" }. Это наиболее простой и декларативный способ извлечения динамических сегментов пути для их использования в компоненте (например, для загрузки данных).

4.3. Использование хука useLocation для доступа к текущему пути и параметрам запроса

Хук useLocation возвращает объект location, который представляет собой текущий URL. Он содержит свойства pathname (путь), search (строку запроса с ?), hash (хэш) и state (состояние, переданное при навигации). Для удобного парсинга строки запроса (search) часто используется конструкция new URLSearchParams(useLocation().search), которая позволяет легко извлекать конкретные параметры по ключу.

4.4. Программное перенаправление пользователей с помощью хуков в React Router

Для программного перенаправления обычно используется комбинация хуков useHistory и useEffect. Внутри useEffect вы проверяете условие (например, статус аутентификации) и, если оно выполняется, вызываете history.replace('/login') или history.push('/target-path'). Это позволяет выполнять навигацию в ответ на изменения состояния или пропсов компонента, что идеально подходит для защищенных маршрутов или обработки определенных состояний приложения.

4.5. Основные понятия и принципы роутинга в React

Роутинг в React — это процесс определения того, какой компонент должен быть отображен в зависимости от текущего URL в браузере. Это реализуется на клиентской стороне, что позволяет создавать одностраничные приложения (SPA) без постоянных перезагрузок страницы. Ключевые принципы включают декларативное определение маршрутов с помощью компонентов, синхронизацию UI с URL и программное управление навигацией через History API.


4.6. Применение хука useHistory для изменения пути в приложении

Основное применение useHistory — это изменение пути в ответ на действия пользователя или логику приложения. Например, после успешной отправки формы вы можете вызвать history.push('/success') для перенаправления на страницу успеха. Или использовать history.go(-1) для возврата пользователя на предыдущую страницу. Этот хук предоставляет императивный API для навигации, дополняющий декларативные компоненты <Link>.

4.7. Извлечение и использование параметров URL через хук useParams в компонентах

Извлеченные с помощью useParams значения чаще всего используются для запросов к API или условного рендеринга. Например, получив userId из параметров, компонент может в useEffect выполнить fetch-запрос к /api/users/${userId} для загрузки данных пользователя. Важно помнить, что параметры всегда являются строками, поэтому при необходимости их нужно преобразовывать в числа или другие типы данных.

4.8. Доступ к пути и search-параметрам с помощью хука useLocation

Объект location из useLocation реагирует на каждое изменение URL, что делает его идеальным для побочных эффектов, зависящих от пути или строки запроса. Например, можно использовать useEffect с зависимостью [location.search] для выполнения нового поиска к API всякий раз, когда изменяются параметры запроса. Это позволяет синхронизировать состояние приложения с URL, создавая деликатный и удобный UX.

4.9. Создание и использование кастомных хуков для управления параметрами URL

Кастомный хук может абстрагировать логику работы с URLSearchParams. Например, хук useQueryParam может принимать ключ и возвращать текущее значение параметра и функцию для его обновления. Внутри он будет использовать useLocation для получения search и useHistory для обновления URL при изменении значения. Это делает код чище и позволяет легко повторно использовать логику работы с query-параметрами across different components.

4.10. Продвинутые техники программного роутинга в React

К продвинутым техникам относится управление состоянием навигации через history.state, создание модальных окон с уникальными URL, глубокое связывание (deep linking) и обработка сложных сценариев, таких как предупреждение пользователя о несохраненных данных при переходе. Также сюда входит предзагрузка данных для целевого маршрута до завершения навигации для ускорения воспринимаемой производительности.

5. React-router API

  • <Link> — используется для перехода между страницами
    • Работает как <a>, но без перезагрузки страницы
    • Изменяет URL и рендерит нужный компонент
    1
    2
    3
    
    import { Link } from 'react-router-dom';
    
    <Link to="/about">About</Link>
    
  • <Route> — определяет, какой компонент рендерить для определённого пути

    1
    2
    3
    
    import { Route } from 'react-router-dom';
    
    <Route path="/about" element={<About />} />
    

Базовый setup <BrowserRouter>

1
2
3
4
5
6
7
8
9
10
11
12
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);
1
2
3
4
5
6
7
8
9
10
import { Routes, Route } from 'react-router-dom';

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
    </Routes>
  );
}

5.2. Использование <Switch> для управления маршрутами

Компонент <Switch> в React Router использовался в версиях v5 и ниже для выбора первого подходящего маршрута.

В React Router v6 <Switch> удалён и заменён на <Routes>:

1
2
3
4
5
6
import { Routes, Route } from 'react-router-dom';

<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/about" element={<About />} />
</Routes>

5.3. Программное перенаправление в React-router, включая <Redirect>

Программное перенаправление в React Router — это способ изменить маршрут не по клику на ссылку, а по логике приложения (например, после логина, при ошибке, при проверке прав).

1
2
3
4
5
6
7
8
9
import { Redirect } from 'react-router-dom';

function Profile({ isAuth }) {
  if (!isAuth) {
    return <Redirect to="/login" />;
  }

  return <div>Profile</div>;
}

В React Router <Link> и <NavLink> используются для навигации, но у них разная цель.

  • <Link> — Это базовый компонент для перехода между страницами. Просто меняет URL без перезагрузки; не знает, активна ли ссылка сейчас
  • <NavLink> — Расширенная версия <Link> с поддержкой активного состояния. Дополнительно умеет определять, совпадает ли текущий URL, и автоматически добавлять стили/классы для активной ссылки

6. history, location, match

6.1. Основы маршрутизации в веб-приложениях

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

6.2. Использование React Router для маршрутизации

React Router — это стандартная библиотека для маршрутизации в React-приложениях. Она предоставляет набор компонентов (таких как BrowserRouter, Route, Link, Switch) и хуков (useHistory, useLocation, useParams), которые позволяют декларативно определять маршруты и управлять навигацией. С ее помощью можно сопоставлять различные URL с соответствующими React-компонентами, создавая структуру приложения с множеством «страниц».

6.3. Переадресация в React приложениях

Переадресация (редирект) в React часто используется для защиты маршрутов или обработки устаревших URL. Компонент Redirect из React Router при рендере немедленно перенаправляет пользователя на указанный путь. Для программного перенаправления (например, после отправки формы) используется хук useHistory с методом push() или replace(). Это позволяет динамически управлять потоком навигации на основе действий пользователя или состояния приложения.


6.4. Работа с объектом history в React Router

Работа с объектом history в React Router — это способ программно управлять навигацией (менять URL из кода).

history — это объект, который:

  • хранит историю переходов (как стек)
  • позволяет перемещаться по ней
  • управляет текущим URL

В React Router v6 history больше не используется напрямую, вместо него — useNavigate()

Объект history является центральным для программного управления навигацией. Он предоставляет методы для изменения текущего URL: push(path) для добавления новой записи в историю, replace(path) для замены текущей записи, а также goBack(), goForward() и go(n) для навигации по истории. Этот объект абстрагирует различия в браузерах и позволяет управлять историей навигации единообразно, не завися напрямую от DOM.

6.5. Использование объекта location для управления состоянием URL

location — это объект, который описывает текущий адрес страницы:

Объект location представляет собой текущий URL. Он содержит такую информацию, как pathname (путь), search (строка запроса), hash и state (произвольные данные, переданные при навигации). Его можно получить с помощью хука useLocation. Этот объект часто используется для выполнения побочных эффектов, зависящих от URL (например, загрузки данных при его изменении), или для чтения и синхронизации состояния приложения с параметрами запроса.

7. Development methodologies (agile and beyond)

7.1. Определение и необходимость методологий разработки

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

7.2. Основы Agile: принципы и цели

Гибкие методологии разработки (Agile-методологии) — обобщающий термин для целого ряда подходов и практик, основанных на ценностях Манифеста гибкой разработки программного обеспечения и 12 принципах, лежащих в его основе.

К гибким методологиям, в частности, относят экстремальное программирование, DSDM (Dynamic Systems Development Method), Scrum, Kanban, FDD (Feature driven development), BDD (Behavior-driven development) и другие.

Большинство гибких методик нацелены на минимизацию рисков путём сведения разработки к серии коротких циклов, называемых итерациями, которые обычно длятся две-три недели. Каждая итерация сама по себе выглядит как программный проект в миниатюре и включает все задачи, необходимые для выдачи мини-прироста по функциональности: планирование, анализ требований, проектирование, программирование, тестирование и документирование.

Ценности:

  1. Люди и взаимодействие важнее процессов и инструментов.
  2. Работающий продукт важнее исчерпывающей документации.
  3. Сотрудничество с заказчиком важнее согласования условий контракта.
  4. Готовность к изменениям важнее следования первоначальному плану.

Таким образом, не отрицая важности того, что справа, мы всё-таки больше ценим то, что слева.

Принципы agile:

  1. Наивысшим приоритетом является удовлетворение потребностей заказчика путём регулярной и ранней поставки ценного ПО.
  2. Изменение требований приветствуется даже на поздних стадиях разработки.
  3. Работающий продукт следует выпускать как можно чаще (лучше недели, а не за месяцы).
  4. Разработчики и представители бизнеса должны ежедневно работать вместе.
  5. Проект создается мотивированными людьми, которым следует доверять.
  6. Живое общение — лучшая форма коммуникации.
  7. Работающий продукт — основной показатель прогресса.
  8. Устойчивая разработка и способность поддерживать постоянный темп.
  9. Постоянное внимание к техническому совершенству и хорошему дизайну.
  10. Простота — искусство минимизации лишней работы — крайне необходима.
  11. Самые лучшие требования, архитектурные и технические решения рождаются у самоорганизующихся команд.
  12. Команда должна систематически анализировать возможные способы улучшения эффективности и соответственно корректировать стиль своей работы.

7.3. Основные концепции Scrum и Kanban

Scrum — это гибкая методология взаимодействия в команде.

Scrum предписывает командам разбивать работу на цели, которые должны быть завершены в рамках ограниченных по времени итераций, называемых спринтами. Каждый спринт длится не более одного месяца и обычно длится две недели. Команда оценивает прогресс с помощью ежедневных встреч (дейли) продолжительностью до 15 минут, где каждый член команды поочереди выступает с кратким отчетом о проделанной работе. В конце спринта команда проводит ещё две встречи: одна для демонстрации результатов заинтересованным лицам и получения обратной связи (демо), и ещё одна — ретроспективный анализ спринта внутри команды (ретро).

Kanban — популярная гибкая методология, центральным элементом которой является kanban-доска — визуальный инструмент, помогающий контролировать работу и повышать эффективность.

To DoIn ProgressIn ReviewQADone
    task1
task2 task2  
task3task3   
task4    
task5    

Основные характеристики доски-kanban:

  • Столбцы представляют различные этапы рабочего процесса
    • To Do, In Progress, In Review, QA, Done
  • Карточки задач представляют собой отдельные рабочие задачи. Эти карточки перемещаются по столбцам по мере выполнения
  • Количество задач в столбе In Progress, как правило, ограничено, чтобы стимулировать плавный ход работы

7.4. Использование систем управления проектами (например, Jira)

Системы управления проектами, например, Jira, являются цифровым воплощением Agile-практик. Они предоставляют инструменты для создания бэклога продукта, планирования спринтов, визуализации рабочего процесса на канбан-доске, отслеживания времени и генерации отчетов.

7.5. Основные модели жизненного цикла разработки программного обеспечения (SDLC)

SDLC (Software Development Life Cycle) — это жизненный цикл разработки программного обеспечения. Это четкий план или процесс, который используют команды разработчиков, чтобы создавать качественное ПО максимально эффективно, в срок и в рамках бюджета.

Основные этапы жизненного цикла разработки:

  1. Анализ требований
  2. Проектирование
  3. Разработка
  4. Тестирование
  5. Внедрение
  6. Поддержка

Основные модели SDLC:

  • Waterfall — продукт создается этапами, которые следуют строго друг за другом, и возврат к предыдущим этапам не предусмотрен.
  • Итеративная модель — разработка идёт через повторяющиеся циклы (итерации), в каждой из которых продукт улучшается.
  • Инкрементальная модель — продукт создаётся по частям (инкрементам), каждый из которых добавляет новую функциональность.
  • Спиральная модель — комбинация каскадной и итеративной моделей с акцентом на анализ рисков.
  • V-модель — расширение каскадной модели, где каждому этапу разработки соответствует этап тестирования.
  • Agile-методологии — используют итеративную модель, где разработка ведётся короткими циклами, и на каждой итерации проходят все этапы — от анализа до тестирования, что позволяет быстро адаптироваться к изменениям.

7.6. Применение принципов SDLC на практике

На практике принципы SDLC применяются через выбор подходящей модели для проекта. Для проектов с четкими и неизменными требованиями подойдет Waterfall. Для проектов с высокой неопределенностью и изменчивыми требованиями применяют Agile-методологии.

8. Git

8.1. Основы системы контроля версий и назначение Git

Система контроля версий (VCS) — это программное обеспечение для отслеживания изменений в файлах и координации работы нескольких людей над одним проектом.

Git — самая популярная распределенная VCS. Ее назначение — сохранять историю изменений, позволять откатываться к предыдущим версиям, а также обеспечивать возможность параллельной разработки через ветвление и слияние кода.

8.2. Основные операции с Git

К основным операциям относятся:

  • git init (создание нового репозитория)
  • git add (добавление изменений в staged)
  • git commit (фиксация изменений в истории)
  • git checkout (переход на ветку или коммит)
  • git push (отправка коммитов на удаленный репозиторий)
  • git pull (получение изменений с удаленного репозитория)
  • git clone (копирование удаленного репозитория)
  • git branch (работа с ветками)
  • git merge (слияние изменений)

8.3. Концепция и использование Gitflow

Gitflow — это соглашение о ветвлении для Git.

Оно определяет несколько типов веток со строгими правилами их использования:

  • main/master (стабильная версия)
  • develop (текущая разработка)
  • feature/* (ветки для новой функциональности)
  • release/* (ветки для подготовки релиза)
  • hotfix/* (ветки для срочных исправлений)

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

8.4. Команда git clone и ее цель

Команда git clone [url] создает полную копию удаленного репозитория на локальной машине. Она не только скачивает все файлы проекта, но и всю историю коммитов, а также настраивает удаленный репозиторий под именем origin. Это первая команда, которую выполняет разработчик, чтобы начать работу над существующим проектом.

8.5. Создание и переключение между ветками в Git

  • для создания новой ветки используется команда git branch [branch_name]
  • для переключения на существующую ветку используется команда git checkout [branch_name] или более современная команда git switch [branch_name]
  • Чтобы создать ветку и сразу переключиться на нее, используется команда git checkout -b [branch_name] или git switch -c [branch_name]
  • git switch — только переключает ветку, прерывает операцию, если она приведёт к потере локальных изменений
  • git checkout — переключает ветку

8.6. Объединение изменений с помощью git merge

Команда git merge [branch_name] объединяет изменения из указанной ветки в текущую. Git пытается автоматически совместить истории коммитов. Если изменения были в разных частях файлов, происходит автоматическое слияние. Если же изменения затронули одни и те же строки, возникает конфликт, который разработчик должен разрешить вручную, отредактировав файлы и сделав commit.

8.7. Использование тегов в Git

Теги (tags) в Git используются для отметки специфических пунктов в истории как важных, обычно для релизов (например, v1.0.0).

  • Аннотированный тег создается командой git tag -a v1.0.0 -m "Версия 1.0.0" и хранится как отдельный объект в базе Git, содержащий имя теггера, дату и сообщение.
  • Легковесный тег (git tag v1.0.0) — это просто указатель на определенный commit.

8.8. Команда git blame и ее применение

Команда git blame [file_name] показывает построчную историю файла: для каждой строки отображается автор, commit и дата последнего изменения. Это незаменимый инструмент для поиска человека, который внес изменение, и для понимания контекста появления определенного кода, особенно при анализе проблем или изучении чужого кода.

8.9. Отличие между git reset и git revert

git reset перемещает указатель текущей ветки на другой commit, удаляя последующие коммиты из истории ветки. Это опасная операция, которая меняет историю и не должна использоваться для коммитов, которые уже были отправлены в общий репозиторий.

git revert создает новый commit, который отменяет изменения, сделанные в указанном commit. Это безопасная операция, так как она не переписывает историю.

8.10. Отмена локальных изменений в Git

Для отмены локальных изменений в файлах, которые еще не были проиндексированы (не добавлены в git add), используется команда git checkout -- [file_name] или git restore [file_name].

Чтобы отменить индексацию файла (убрать его из git add), но оставить изменения в рабочей директории, используется команда git reset HEAD [file_name] или git restore –staged [file_name].

9. Design Patterns (Factory, Module, Prototype, Observer, Builder, Facade, Decorator)

9.1. Определение и классификация паттернов программирования

Паттерны проектирования — это типовые решения часто встречающихся задач при разработке ПО.

9.2. Типы паттернов проектирования: Порождающие, Структурные, Поведенческие

  • Порождающие паттерны отвечают за создание объектов
    • Singleton, Factory, Abstract Factory, Builder, Prototype
  • Структурные паттерны отвечают за организацию классов и объектов
    • Adapter, Decorator, Facade, Proxy
  • Поведенческие паттерны отвечают за взаимодействие объектов
    • Observer, Iterator, Strategy, Command

9.3. Примеры и преимущества паттерна Наблюдатель

Паттерн Наблюдатель (Observer) определяет зависимость “один-ко-многим” между объектами так, что при изменении состояния одного объекта-издателя (Subject) все зависящие от него объекты-наблюдатели (Observers) автоматически уведомляются и обновляются. По сути, паттерн Наблюдатель — это механизм подписки.

Пример: система событий в JavaScript, где элементы DOM являются Observers, ожидающими события (click, input) от Subject (сам DOM-элемент).

Преимущества:

  • слабая связанность между компонентами
  • масштабируемость
  • реактивность

9.4. Различия между паттерном Фабрика и Абстрактная фабрика

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

Абстрактная фабрика — это паттерн, который создает семейства связанных или зависимых объектов без привязки к их конкретным классам. Он создает семейство связанных продуктов.

10. JS. Regular Expressions, RegExp

10.1. Основы работы с RegExp в JavaScript

Регулярные выражения в JavaScript — это инструмент для поиска, проверки и замены текста по шаблону.

В JavaScript они реализованы в виде объекта RegExp.

Регулярное выражение можно создать:

  • с помощью литерала, заключенного в слеши const regex = /abc/;
  • с помощью конструктора const regex = new RegExp('abc');

10.2. Методы объекта RegExp

Основные методы объекта RegExp:

1
2
3
4
5
// Проверяет, есть ли совпадение
/abc/.test('abcdef'); // true

// Ищет совпадение и возвращает подробную информацию
/\d+/.exec('abc123'); // ['123', index: 3, input: 'abc123']

10.3. Применение регулярных выражений в JavaScript

Регулярные выражения применяются для:

  • Проверки данных (валидация email, телефона, пароля)
  • Поиска и извлечения информации из текста (поиск всех номеров в документе)
  • Поиска и замены части строки (замена форматирования в тексте)
  • Разбиения строк на подстроки по сложному разделителю

10.4. Создание объектов RegExp и использование флагов

Объекты RegExp создаются двумя способами:

  • Литерал: const regex = /abc/;
  • Конструктор: const regex = new RegExp('abc');

Флаги изменяют поиск и указываются после закрывающего слеша (в литерале) или как второй аргумент (в конструкторе):

  • i — case-insensitive (игнорирует регистр)
  • g — global (ищет все совпадения, а не только первое)
  • m — multiline (рассматривает начало и конец строки ^ и $ для каждой строки в многострочном тексте)

10.5. Методы работы с регулярными выражениями в строках JavaScript

Строковые методы, принимающие регулярные выражения:

1
2
3
4
5
6
7
'abc123'.match(/\d+/); // ['123']

'hello 123'.replace(/\d+/, 'NUM'); // 'hello NUM'

'hello'.search(/l/); // 2

"a,b;c".split(/[,;]/); // ['a', 'b', 'c']
This post is licensed under CC BY 4.0 by the author.