<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Dmitriy D.</title><subtitle>Senior UI-engineer with 7+ years of experience. Делюсь опытом 👨‍🏫</subtitle><author><name>Dmitriy D.</name></author><id>https://teletype.in/atom/boost</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/boost?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@boost?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/boost?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-05-13T18:18:59.966Z</updated><entry><id>boost:aaa-pattern-in-unit-tests-for-javascript</id><link rel="alternate" type="text/html" href="https://teletype.in/@boost/aaa-pattern-in-unit-tests-for-javascript?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><title>AAA-паттерн в unit-тестировании на JavaScript</title><published>2024-10-29T17:52:12.887Z</published><updated>2025-03-31T10:06:04.034Z</updated><category term="patterny" label="Паттерны"></category><summary type="html">Паттерны программирования помогают разработчикам читать и понимать чужой код. AAA-паттерн в контексте unit-тестирования предлагает структурировать тесты на три секции:</summary><content type="html">
  &lt;p id=&quot;K07N&quot;&gt;Паттерны программирования помогают разработчикам читать и понимать чужой код. AAA-паттерн в контексте unit-тестирования предлагает структурировать тесты на три секции: &lt;/p&gt;
  &lt;ol id=&quot;QzEB&quot;&gt;
    &lt;li id=&quot;gxtR&quot;&gt;&lt;code&gt;Arrange&lt;/code&gt; (настрой)&lt;/li&gt;
    &lt;li id=&quot;qYTb&quot;&gt;&lt;code&gt;Act&lt;/code&gt;  (действуй)&lt;/li&gt;
    &lt;li id=&quot;v0FE&quot;&gt;&lt;code&gt;Assert&lt;/code&gt; (проверь)&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h2 id=&quot;Djv2&quot;&gt;Настрой&lt;/h2&gt;
  &lt;p id=&quot;nMxc&quot;&gt;На этапе настройки подготавливаются все зависимости теста:&lt;/p&gt;
  &lt;ul id=&quot;HxXZ&quot;&gt;
    &lt;li id=&quot;dONy&quot;&gt;Объявляем аргументы для функций&lt;/li&gt;
    &lt;li id=&quot;jwf2&quot;&gt;Объявляем props для компонентов&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;ociw&quot;&gt;Иногда настраивать ничего не требуется, это нормально.&lt;/p&gt;
  &lt;h2 id=&quot;4pva&quot;&gt;Действуй&lt;/h2&gt;
  &lt;p id=&quot;zgj2&quot;&gt;На этапе действия выполняется основная задача теста:&lt;/p&gt;
  &lt;ul id=&quot;xYla&quot;&gt;
    &lt;li id=&quot;at9H&quot;&gt;Рендерим React-компонент&lt;/li&gt;
    &lt;li id=&quot;O2pj&quot;&gt;Получаем DOM-элементы&lt;/li&gt;
    &lt;li id=&quot;OF6z&quot;&gt;Вызываем функции с аргументами&lt;/li&gt;
    &lt;li id=&quot;nGq6&quot;&gt;Изменяем состояние в React-хуках&lt;/li&gt;
    &lt;li id=&quot;5WRU&quot;&gt;Инициируем действие пользователя (клик, фокус и т.д.)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;9ktK&quot;&gt;Проверь&lt;/h2&gt;
  &lt;p id=&quot;Sp5K&quot;&gt;На этапе проверки сверяем результаты выполнения сценариев:&lt;/p&gt;
  &lt;ul id=&quot;phhq&quot;&gt;
    &lt;li id=&quot;JpUl&quot;&gt;Проверяем позитивные сценарии&lt;/li&gt;
    &lt;li id=&quot;3Iej&quot;&gt;Проверяем негативные сценарии&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;S4XY&quot;&gt;Примеры с тестами&lt;/h2&gt;
  &lt;h3 id=&quot;olf3&quot;&gt;Чистые функции&lt;/h3&gt;
  &lt;p id=&quot;S4zH&quot;&gt;Проверяем по AAA-паттерну результат работы чистой функции:&lt;/p&gt;
  &lt;pre id=&quot;vhQM&quot; data-lang=&quot;typescript&quot;&gt;describe(&amp;#x27;dateFormat&amp;#x27;, () =&amp;gt; {
  it(&amp;#x27;дата должна соотвествовать формату DD-MM-YYYY&amp;#x27;, () =&amp;gt; {
  
    // Настрой
  
    const inputDate = &amp;#x27;07.12.2012&amp;#x27;
    const outputFormat = &amp;#x27;DD-MM-YYYY&amp;#x27;
  
    // Действуй
  
    const date = dateFormat(inputDate, outputFormat)
  
    // Проверь
  
    expect(date).toBe(&amp;#x27;07-12-2012&amp;#x27;)
  })
}&lt;/pre&gt;
  &lt;h3 id=&quot;6Ip8&quot;&gt;Изменение &lt;code&gt;state&lt;/code&gt; в React-хуке&lt;/h3&gt;
  &lt;p id=&quot;SmNN&quot;&gt;Проверяем по AAA-паттерну бизнес-логику, вынесенную в отдельный хук:&lt;/p&gt;
  &lt;pre id=&quot;NaRJ&quot; data-lang=&quot;javascript&quot;&gt;function useAnalytics() { 
  const [events, setEventCount] = useState(0) 
  
  const sendEvent = debounce(async (event) =&amp;gt; {
     await ym(event)
     setEventCount((x) =&amp;gt; x + 1)
  }, 300)
  
  return { sendEvent, events } 
}&lt;/pre&gt;
  &lt;pre id=&quot;i8eT&quot; data-lang=&quot;javascript&quot;&gt;import { renderHook, waitFor } from &amp;quot;@testing-library/react&amp;quot;

describe(&amp;#x27;useAnalytics&amp;#x27;, () =&amp;gt; {
  it(&amp;#x27;только 1 событие отправлено после 2 кликов подряд&amp;#x27;, async () =&amp;gt; {
   
    // Действуй
  
    const { sendEvent, events } = renderHook(useAnalytics)
  
    waitFor(() =&amp;gt; { 
      await sendEvent(&amp;#x27;click&amp;#x27;)
      await sendEvent(&amp;#x27;click&amp;#x27;)
    })
  
    // Проверь
  
    expect(events).toBe(1)
  })
}&lt;/pre&gt;
  &lt;h3 id=&quot;gNHw&quot;&gt;Изменение &lt;code&gt;state&lt;/code&gt; в Redux-редюсере&lt;/h3&gt;
  &lt;p id=&quot;FMOx&quot;&gt;Проверяем по AAA-паттерну бизнес-логику вынесенную в отдельный редюсер, при помощи доступных методов:&lt;/p&gt;
  &lt;pre id=&quot;atr6&quot; data-lang=&quot;typescript&quot;&gt;const ratesReducer = createSlice({
  name: &amp;#x27;rates&amp;#x27;,
  initialState: {
     all: [],
     best: [],
  },
  reducers: {
     set: (state, action) =&amp;gt; {
        state.all = action.payload
     }
     filter: (state, action) =&amp;gt; {
        const { all, best } = state
        const { value } = action.payload
        
        best = all.filter(rate =&amp;gt; rate.value &amp;gt;= value)
     }
  }
})&lt;/pre&gt;
  &lt;pre id=&quot;AluO&quot; data-lang=&quot;typescript&quot;&gt;describe(&amp;#x27;ratesReducer&amp;#x27;, () =&amp;gt; {
  it(&amp;#x27;возвращает ставки при фильтрации по значению&amp;#x27;, () =&amp;gt; {
   
    // Настрой
  
    const initials = {
      all: [
        { name: &amp;#x27;Накопительный&amp;#x27;, value: 11 },
        { name: &amp;#x27;Среднесрочный&amp;#x27;, value: 14 },
        { name: &amp;#x27;Долгосрочный&amp;#x27;,  value: 20 },
      ],
      best: []
    }
  
    // Действуй
   
    const { reducer, filter } = rates
  
    const bestRates = reducer(initials, filter({ value: 12 })
  
    // Проверь
  
    expect(bestRates).toEqual([
      { name: &amp;#x27;Среднесрочный&amp;#x27;, value: 14 },
      { name: &amp;#x27;Долгосрочный&amp;#x27;,  value: 18 },
    ])
  })
})&lt;/pre&gt;
  &lt;h3 id=&quot;aVzF&quot;&gt;Изменение &lt;code&gt;props&lt;/code&gt;  в React-компоненте&lt;/h3&gt;
  &lt;p id=&quot;1bCX&quot;&gt;Проверяем по AAA-паттерну рендеринг компонента с различными сочетаниями &lt;code&gt;props&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;WaSM&quot; data-lang=&quot;typescript&quot;&gt;import { render } from &amp;quot;@testing-library/react&amp;quot;

describe(&amp;#x27;Button&amp;#x27;, () =&amp;gt; {
  it(&amp;#x27;отображает загрузку (без текста) для состояния loading&amp;#x27;, () =&amp;gt; {
  
    // Настрой
  
    const props = {
       isLoading: true
    }
  
    // Действуй
  
    const component = render(&amp;lt;Button {...props}&amp;gt;Скачать&amp;lt;/Button&amp;gt;)
    const button = component.getByTestId(&amp;#x27;button&amp;#x27;) 
  
    // Проверь

    expect(button).toHaveClass(&amp;#x27;.loading&amp;#x27;)
    expect(button).not.toHaveTextContent(&amp;quot;Скачать&amp;quot;) 
  })
})&lt;/pre&gt;
  &lt;p id=&quot;9YSX&quot;&gt;Тестируем внутреннее изменение &lt;code&gt;state&lt;/code&gt; в React-компоненте по AAA-паттерну:&lt;/p&gt;
  &lt;pre id=&quot;RPlm&quot; data-lang=&quot;typescript&quot;&gt;import { render, fireEvent } from &amp;quot;@testing-library/react&amp;quot;

describe(&amp;quot;Toggle&amp;quot;, () =&amp;gt; {
  it(&amp;quot;включён после клика на Toggle в дефолтном состоянии&amp;quot;, () =&amp;gt; {
  
    // Действуй
  
    const component = render(&amp;lt;Toggle /&amp;gt;)
    const toggle = component.getByTestId(&amp;#x27;.toggle&amp;#x27;) 

    waitFor(() =&amp;gt; { 
       fireEvent.click(toggle)
    }) 
  
    // Проверь

    expect(toggle).toBeChecked()
  })
})&lt;/pre&gt;
  &lt;h2 id=&quot;KO7u&quot;&gt;Название теста&lt;/h2&gt;
  &lt;p id=&quot;vMUm&quot;&gt;Имя теста так же можно создавать при помощи AAA-паттерна, только в обратную сторону (на примере тестов выше):&lt;/p&gt;
  &lt;ul id=&quot;JbkI&quot;&gt;
    &lt;li id=&quot;Sm6D&quot;&gt;(dateFormat) date must be exact to DD-MM-YYYY format&lt;/li&gt;
    &lt;li id=&quot;M3mt&quot;&gt;(useAnalytics) sent only one event after double call by sendEvent&lt;/li&gt;
    &lt;li id=&quot;VlEq&quot;&gt;(ratesReducer) returns rates with filter value&lt;/li&gt;
    &lt;li id=&quot;AOah&quot;&gt;(button) show loading styles and no text for loading state&lt;/li&gt;
    &lt;li id=&quot;BVmX&quot;&gt;(toggle) checked after click to toggle with default state&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;2S7u&quot;&gt;Заключение&lt;/h2&gt;
  &lt;p id=&quot;hn6G&quot;&gt;Паттерн хорош собой, так как при создании теста заставляет концентрироваться на независимых этапах, которые при повторении можно легко вынести и переиспользовать.&lt;/p&gt;
  &lt;p id=&quot;EAI1&quot;&gt;Так же паттерн создает условия, при которых код с бизнес-логикой нужно выносить в отдельные чистые функции, что в свою очередь считается другим хорошим паттерном.&lt;/p&gt;
  &lt;p id=&quot;dXa8&quot;&gt;Паттерн подходит &lt;strong&gt;только для unit-тестов, &lt;/strong&gt;так кактребует чтобы тесты проводили проверки, а не ходили по шагам.&lt;/p&gt;
  &lt;p id=&quot;exYJ&quot;&gt;Использовать паттерн — хорошая практика, так как разработчикам становиться проще читать и понимать чужие тесты.&lt;/p&gt;

</content></entry><entry><id>boost:unit-testing</id><link rel="alternate" type="text/html" href="https://teletype.in/@boost/unit-testing?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><title>Unit-тестирование</title><published>2024-10-03T15:58:01.928Z</published><updated>2024-10-23T18:09:04.489Z</updated><summary type="html">Любой проект стремится к стабилизации разработки.</summary><content type="html">
  &lt;p id=&quot;s5Bn&quot;&gt;&lt;strong&gt;Unit-тестирование&lt;/strong&gt; помогает стабилизировать процесс разработки при помощи тестов на базовые составляющие кода: функции, методы, классы и целые блоки кода, например: &lt;/p&gt;
  &lt;ul id=&quot;1Ocq&quot;&gt;
    &lt;li id=&quot;unnU&quot;&gt;Функция вычисления общей стоимости заказа&lt;/li&gt;
    &lt;li id=&quot;cplW&quot;&gt;Метод сортировки новостей по дате&lt;/li&gt;
    &lt;li id=&quot;auZA&quot;&gt;Колбек при переходе на страницу&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;o4F9&quot;&gt;&lt;strong&gt;Покрытие&lt;/strong&gt; unit-тестами позволяет:&lt;/p&gt;
  &lt;ul id=&quot;4zvi&quot;&gt;
    &lt;li id=&quot;ZzON&quot;&gt;Повысить стабильность рефакторинга&lt;/li&gt;
    &lt;li id=&quot;EshE&quot;&gt;Уменьшить количество ошибок на ранних стадиях разработки&lt;/li&gt;
    &lt;li id=&quot;O2Ad&quot;&gt;Увеличить доверие + получить гарантии работоспособности кода&lt;/li&gt;
    &lt;li id=&quot;21Uo&quot;&gt;Задокументировать код&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;U4bu&quot;&gt;&lt;strong&gt;Без покрытия&lt;/strong&gt; unit-тестами:&lt;/p&gt;
  &lt;ul id=&quot;K7Oz&quot;&gt;
    &lt;li id=&quot;EUs8&quot;&gt;Дефекты будут найдены позже, их исправление станет дороже&lt;/li&gt;
    &lt;li id=&quot;8Z1F&quot;&gt;Новый код будет лежать «рядом» с исходным, вместо изменений&lt;/li&gt;
    &lt;li id=&quot;gnTv&quot;&gt;Проект быстро устареет и его потребуется переписать с нуля&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;8K7j&quot;&gt;Unit-тестирование &lt;strong&gt;трудоемкий процесс&lt;/strong&gt; отнимающий значимое количество рабочего времени, поэтому перед тем как начать писать тест следует обдумать что конкретно вы собираетесь покрыть тестом.&lt;/p&gt;
  &lt;h2 id=&quot;mKxQ&quot;&gt;Что покрывать unit-тестами?&lt;/h2&gt;
  &lt;p id=&quot;jPiM&quot;&gt;Вопрос который мучает многих разработчиков, так как возможности &lt;strong&gt;Jest&lt;/strong&gt; в сочетании с другими инструментами позволяют тестировать компоненты на уровне сквозных тестов (e2e). &lt;/p&gt;
  &lt;p id=&quot;J5nA&quot;&gt;&lt;strong&gt;Концептуально&lt;/strong&gt; стоит тестировать любой код, отказ которого может привести к  &lt;strong&gt;потере денег, &lt;/strong&gt;например:&lt;/p&gt;
  &lt;ul id=&quot;DvWW&quot;&gt;
    &lt;li id=&quot;o7i1&quot;&gt;Бизнес-сценарий &lt;strong&gt;не может быть завершен&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;uO11&quot;&gt;Интерфейс &lt;strong&gt;работает некорректно&lt;/strong&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;WFqW&quot;&gt;На &lt;strong&gt;прикладном&lt;/strong&gt; уровне unit-тестами следует тестировать &lt;strong&gt;состояние&lt;/strong&gt; и &lt;strong&gt;поведение &lt;/strong&gt;кода.&lt;/p&gt;
  &lt;h3 id=&quot;xMv3&quot;&gt;Тестирование состояния&lt;/h3&gt;
  &lt;p id=&quot;wFGi&quot;&gt;Тестируя&lt;strong&gt; состояние &lt;/strong&gt;мы подаем на вход данные и проверяем:&lt;/p&gt;
  &lt;p id=&quot;RxBw&quot;&gt;1. Корректность вывода утилитарных функций&lt;/p&gt;
  &lt;pre id=&quot;u9G8&quot; data-lang=&quot;javascript&quot;&gt;function sum(a: number, b: number) :number {
    return a + b
}

test(&amp;quot;sum of 2 numbers return correct value&amp;quot;, () =&amp;gt; {
    const result = sum(1, 2)
    expect(result).toEqual(3)
})&lt;/pre&gt;
  &lt;p id=&quot;3psL&quot;&gt;2. Корректность отображения &lt;code&gt;props&lt;/code&gt; глупых компонентов&lt;/p&gt;
  &lt;pre id=&quot;Rngj&quot; data-lang=&quot;javascript&quot;&gt;import { render } from &amp;quot;@testing-library/react&amp;quot;;

test(&amp;quot;breadcrumbs renders correct count of items&amp;quot;, () =&amp;gt; {
    const items = [&amp;quot;Главная&amp;quot;, &amp;quot;Категория&amp;quot;, &amp;quot;Статья&amp;quot;]
    const component = render(&amp;lt;Breadcrumbs items={items} visible={2} /&amp;gt;)
    
    const items = component.querySelector(&amp;#x27;.items&amp;#x27;)
    
    // позитвные сценарии
    expect(items).toHaveLength(2)
    expect(items).toHaveTextContent(&amp;quot;Главная&amp;quot;)
    expect(items).toHaveTextContent(&amp;quot;Категория&amp;quot;)
    
    // негативные сценарии
    expect(items).not.toHaveTextContent(&amp;quot;Статья&amp;quot;)
})&lt;/pre&gt;
  &lt;p id=&quot;pmSv&quot;&gt;3. Корректность изменения &lt;code&gt;state&lt;/code&gt; глупых компонентов:&lt;/p&gt;
  &lt;pre id=&quot;IyWp&quot; data-lang=&quot;javascript&quot;&gt;import { renderHook, waitFor } from &amp;quot;@testing-library/react&amp;quot;;

function useCounter() {
  const [count, setCount] = useState(0)
  const increment = () =&amp;gt; setCount((x) =&amp;gt; x + 1)

  return { count, increment }
}

test(&amp;quot;useCounter increment method works correct&amp;quot;, async () =&amp;gt; {
  const result = renderHook(useCounter)
   
  waitFor(() =&amp;gt; {
    result.current.increment()
  })
   
  expect(result.current.count).toBe(1)
})&lt;/pre&gt;
  &lt;ul id=&quot;aPDj&quot;&gt;
    &lt;ul id=&quot;LAq1&quot;&gt;&lt;/ul&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;YPA5&quot;&gt;Тестирование поведения&lt;/h3&gt;
  &lt;p id=&quot;7ley&quot;&gt;Тестируя&lt;strong&gt; поведение &lt;/strong&gt;мысовершаем действия и смотрим:&lt;/p&gt;
  &lt;p id=&quot;gwm8&quot;&gt;1. Как компонент взаимодействует c другими компонентами&lt;/p&gt;
  &lt;ul id=&quot;4CKc&quot;&gt;
    &lt;li id=&quot;Sn9E&quot;&gt;Взаимодействие данных между страницами&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;kmn5&quot;&gt;2. Как компонент взаимодействует с пользователем&lt;/p&gt;
  &lt;ul id=&quot;wRT8&quot;&gt;
    &lt;li id=&quot;LgYX&quot;&gt;Прохождение &lt;code&gt;happy-path&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;3d3l&quot;&gt;Заполнение форм&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;04j5&quot;&gt;3. Как компонент реагирует на ответы с сервера&lt;/p&gt;
  &lt;ul id=&quot;GukC&quot;&gt;
    &lt;li id=&quot;QUkC&quot;&gt;Серверная валидация формы&lt;/li&gt;
    &lt;li id=&quot;0bUv&quot;&gt;Корректное отображение данных с сервера&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;hGNn&quot;&gt;Что такое хороший тест?&lt;/h3&gt;
  &lt;ul id=&quot;e9rK&quot;&gt;
    &lt;li id=&quot;wOX4&quot;&gt;Проверяет только 1 утверждение&lt;/li&gt;
    &lt;li id=&quot;DDpI&quot;&gt;Изолирован от других тестов и окружения&lt;/li&gt;
    &lt;li id=&quot;Ejzd&quot;&gt;Выполняться быстро и параллельно&lt;/li&gt;
    &lt;li id=&quot;z7T6&quot;&gt;Соблюдает структуру, конвенцию именования&lt;/li&gt;
    &lt;li id=&quot;6bIA&quot;&gt;Имеет небольшой размер&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;EgJM&quot;&gt;Пишем тесты с умом&lt;/h3&gt;
  &lt;p id=&quot;fSYj&quot;&gt;Бездумное написание тестов не помогает, а даже вредит проекту.&lt;/p&gt;
  &lt;p id=&quot;EOUF&quot;&gt;Если раньше у вас был один некачественный продукт, то написав тесты, не разобравшись, вы получите — два, и бонусом удвоенное время на сопровождение и поддержку за &lt;strong&gt;ваш счёт&lt;/strong&gt;.&lt;/p&gt;
  &lt;p id=&quot;4kUT&quot;&gt;Не стоит относиться к тестам как к второсортному коду. &lt;/p&gt;
  &lt;p id=&quot;bkU7&quot;&gt;Многие начинающие разработчики ошибочно полагают, что DRY, KISS и другие подходы, да даже переиспользование переменных для &lt;code&gt;test-id&lt;/code&gt; — это только для кода в продакшен, а в тестах допустимо всё. &lt;/p&gt;
  &lt;p id=&quot;DqHK&quot;&gt;&lt;strong&gt;Это не верно.&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;LAIg&quot;&gt;Тесты так же являются важным кодом, просто пользователи этого кода — другие разработчики.&lt;/p&gt;
  &lt;h3 id=&quot;qxjH&quot;&gt;Какой процент покрытия?&lt;/h3&gt;
  &lt;p id=&quot;nL0X&quot;&gt;Добиваться 100% покрытия бессмысленно, так как такой процент покрытия не гарантирует вам безотказную работу вашего приложения.&lt;/p&gt;
  &lt;figure id=&quot;DQLw&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/de/ed/deed0ca5-3445-4680-a799-7b4542d4ff82.png&quot; width=&quot;1020&quot; /&gt;
    &lt;figcaption&gt;Почему бесмысленно добиваться 100% покрытия&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;LNNL&quot;&gt;Хорошие практики&lt;/h3&gt;
  &lt;ul id=&quot;xipE&quot;&gt;
    &lt;li id=&quot;rbN7&quot;&gt;На баг всегда должен быть написан unit-тест&lt;/li&gt;
    &lt;li id=&quot;9A3K&quot;&gt;Писать unit-тесты на негативные сценарии&lt;/li&gt;
    &lt;li id=&quot;FREq&quot;&gt;Описывать unit-тест по структуре AAA&lt;/li&gt;
    &lt;ul id=&quot;vuRb&quot;&gt;
      &lt;li id=&quot;yNMD&quot;&gt;&lt;strong&gt;Arrange &lt;/strong&gt;(условие)&lt;/li&gt;
      &lt;li id=&quot;uJxD&quot;&gt;&lt;strong&gt;Act&lt;/strong&gt; (действие)&lt;/li&gt;
      &lt;li id=&quot;oTSf&quot;&gt;&lt;strong&gt;Assert &lt;/strong&gt;(утверждение)&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;cRbU&quot;&gt;Cтремиться к 80% покрытию&lt;/li&gt;
    &lt;li id=&quot;wymw&quot;&gt;Завязываться на test-id для обращения к DOM-элементами&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;il6L&quot;&gt;Плохие практики&lt;/h3&gt;
  &lt;ul id=&quot;zC53&quot;&gt;
    &lt;li id=&quot;1Lhj&quot;&gt;Unit-тест тестирует смежные модули&lt;/li&gt;
    &lt;li id=&quot;gjrh&quot;&gt;Unit-тест тестирует данные, а не бизнес-логику&lt;/li&gt;
    &lt;li id=&quot;4ime&quot;&gt;Unit-тест не проверяет исключительные ситуации&lt;/li&gt;
    &lt;li id=&quot;iW2I&quot;&gt;Unit-тест выводит не понятный assertion message&lt;/li&gt;
    &lt;li id=&quot;DQta&quot;&gt;Unit-тест тестирует компонент UI-библиотеки или готовый пакет&lt;/li&gt;
    &lt;li id=&quot;57va&quot;&gt;Стремиться к 100% покрытию&lt;/li&gt;
    &lt;li id=&quot;IYyZ&quot;&gt;Завязываться на селекторы и классы для обращения к DOM-элементами&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>boost:how-to-structure-a-proposal-to-thechnical-change</id><link rel="alternate" type="text/html" href="https://teletype.in/@boost/how-to-structure-a-proposal-to-thechnical-change?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><title>Как качественно сформулировать техническое предложение по изменениям в проекте</title><published>2024-09-28T13:29:56.431Z</published><updated>2024-10-10T04:52:48.847Z</updated><summary type="html">Тема должна быть узкой и предлагать конкретное решение проблемы. Широкая тема даёт возможность перескакивать с одного места на другое, из-за чего Вас становится сложно понять. Попробуйте сузить так, чтобы презентация умещалась в 7-10 простых слайдов.</summary><content type="html">
  &lt;p id=&quot;gpZ3&quot;&gt;Материал для тех, кому часто требуется выступить с&lt;strong&gt; предложением технических изменений&lt;/strong&gt; в проекте ✌&lt;/p&gt;
  &lt;p id=&quot;FKwY&quot;&gt;Кто пробовал изменить что-то в устоявшемся проекте, тот знает — любые изменения воспринимаются окружающими критически, и полезность ваших изменений надо еще доказать.&lt;/p&gt;
  &lt;p id=&quot;aAnW&quot;&gt;В особенности когда проект существует много лет и все привыкли что проект работает пускай не идеально, но зато предсказуемо и понятно. &lt;/p&gt;
  &lt;p id=&quot;z2U7&quot;&gt;Такая уж природа человека 🤷‍♂️&lt;/p&gt;
  &lt;p id=&quot;OBn9&quot;&gt;Чтобы предложение изменений причиняло как можно &lt;strong&gt;меньше боли&lt;/strong&gt; окружающим и вообще было &lt;strong&gt;воспринято конструктивно&lt;/strong&gt;, я сформулировал для себя чек-лист, цель которого:&lt;/p&gt;
  &lt;ul id=&quot;nyDu&quot;&gt;
    &lt;li id=&quot;OWTE&quot;&gt;Донести важность изменений&lt;/li&gt;
    &lt;li id=&quot;Oln5&quot;&gt;Сохранить адекватность повествования&lt;/li&gt;
    &lt;li id=&quot;in5s&quot;&gt;Не давать повествованию уйти в сторону&lt;/li&gt;
    &lt;li id=&quot;JRad&quot;&gt;Достичь хорошего соотношения времени/полезности в выступлении&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;4Fi7&quot;&gt;Итак, чек-лист адекватного предложения изменений:&lt;/p&gt;
  &lt;h2 id=&quot;wX9x&quot;&gt;&lt;strong&gt;Сформулируй тему&lt;/strong&gt;&lt;/h2&gt;
  &lt;p id=&quot;20Pw&quot;&gt;Тема должна быть &lt;strong&gt;узкой&lt;/strong&gt; и предлагать &lt;strong&gt;конкретное решение&lt;/strong&gt; проблемы. Широкая тема даёт возможность &lt;strong&gt;перескакивать с одного места на другое&lt;/strong&gt;, из-за этого становится сложно понять общий смысл.&lt;/p&gt;
  &lt;p id=&quot;STRX&quot;&gt;&lt;strong&gt;Широкие темы&lt;/strong&gt;, где мысль может скакать:&lt;/p&gt;
  &lt;ul id=&quot;Upa4&quot;&gt;
    &lt;li id=&quot;b47k&quot;&gt;Улучшение процесса тестирования&lt;/li&gt;
    &lt;li id=&quot;DI75&quot;&gt;Повышение производительности приложения&lt;/li&gt;
    &lt;li id=&quot;2Tpc&quot;&gt;Использование паттернов проектирования&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;zLVY&quot;&gt;&lt;strong&gt;Узкие темы&lt;/strong&gt;, где мысль будет идти по четкой траектории:&lt;/p&gt;
  &lt;ul id=&quot;yFv5&quot;&gt;
    &lt;li id=&quot;cNZS&quot;&gt;3 утилиты способные ускорить написание тестов&lt;/li&gt;
    &lt;li id=&quot;6wqQ&quot;&gt;Использование хуков для мемоизоции снижает нагрузка на коллстэк&lt;/li&gt;
  &lt;/ul&gt;
  &lt;ul id=&quot;5LEm&quot;&gt;
    &lt;li id=&quot;A2Fx&quot;&gt;Как внедрение MVC сделает приложение более устойчивым к рефакторингу&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;hdNk&quot;&gt;В контексте презентации, тема должна быть сформулирована так, чтобы презентация умещалась в 5-7 простых слайдов.&lt;/p&gt;
  &lt;h2 id=&quot;VpAV&quot;&gt;&lt;strong&gt;Определи цель&lt;/strong&gt;&lt;/h2&gt;
  &lt;p id=&quot;3pz6&quot;&gt;Целью выступления должно быть &lt;strong&gt;позитивное изменение&lt;/strong&gt; текущего положения дел.&lt;/p&gt;
  &lt;p id=&quot;uFQQ&quot;&gt;Не стоит коммититься на что-то амбициозное, нужно выбрать простую, понятную и достижимую цель, которую можно внедрить без лишней боли.&lt;/p&gt;
  &lt;p id=&quot;hHyN&quot;&gt;&lt;strong&gt;Абстрактная &lt;/strong&gt;амбициозная цель:&lt;/p&gt;
  &lt;ul id=&quot;rng4&quot;&gt;
    &lt;li id=&quot;2eeT&quot;&gt;Помочь разработчикам писать код лучше и не допускать ошибок&lt;/li&gt;
    &lt;li id=&quot;xCNE&quot;&gt;Предложить рефакторинг лейаутов&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;N7wf&quot;&gt;&lt;strong&gt;Конкретная &lt;/strong&gt;цель:&lt;/p&gt;
  &lt;ul id=&quot;xBxn&quot;&gt;
    &lt;li id=&quot;Hq41&quot;&gt;Убедить разработчиков включить/выключить линтер-правила&lt;/li&gt;
    &lt;li id=&quot;8AtY&quot;&gt;Доказать что доработка лейаута значительно сократит код-базу, снизит траты ресурсов на тестирование и поддержку&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;br4N&quot;&gt;&lt;strong&gt;Предложи решение&lt;/strong&gt;&lt;/h2&gt;
  &lt;p id=&quot;X1Ux&quot;&gt;Конечной целью выступления должно быть &lt;strong&gt;конкретное решение &lt;/strong&gt;или &lt;strong&gt;порядок действий, &lt;/strong&gt;который приведет к достижения поставленной целей. Некий набор шагов, в идеале, простых и коротких, выполнив который можно предсказуемо достигнуть поставленной цели.&lt;/p&gt;
  &lt;h2 id=&quot;rFzz&quot;&gt;&lt;strong&gt;Помни про тайминг&lt;/strong&gt;&lt;/h2&gt;
  &lt;p id=&quot;JsEC&quot;&gt;Выступление должно идти не больше 20 минут, иначе оно рискует превратится в скучную лекцию препода по матеше в субботний солнечный день.&lt;/p&gt;

</content></entry><entry><id>boost:js-use-strict-mode</id><link rel="alternate" type="text/html" href="https://teletype.in/@boost/js-use-strict-mode?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><title>Строгий режим в JavaScript (use strict)</title><published>2024-05-31T17:12:45.646Z</published><updated>2024-06-17T10:16:37.418Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/6e/40/6e404a79-13ba-4942-90fe-2a9d358ffded.png"></media:thumbnail><category term="js" label="JS"></category><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/02/7c/027cef1e-cbb9-41d9-b3a9-82961c56a1ab.png&quot;&gt;Долгое время JavaScript развивался без проблем с обратной совместимостью к прошлым версиям языка: добавлялись новые возможности, старая функциональность не изменялась.</summary><content type="html">
  &lt;p id=&quot;DDX8&quot;&gt;Долгое время JavaScript развивался без проблем с обратной совместимостью к прошлым версиям языка: добавлялись новые возможности, старая функциональность не изменялась.&lt;/p&gt;
  &lt;p id=&quot;8mdw&quot;&gt;В результате, существующий код продолжал работать, но каждая ошибка и несовершенство языка застревали в нем навсегда.&lt;/p&gt;
  &lt;p id=&quot;9JjN&quot;&gt;Так JavaScript работает по-умолчанию.&lt;/p&gt;
  &lt;figure id=&quot;bhO0&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/02/7c/027cef1e-cbb9-41d9-b3a9-82961c56a1ab.png&quot; width=&quot;1524&quot; /&gt;
    &lt;figcaption&gt;Что же выбрать?&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;B40W&quot;&gt;Sloppy mode (небрежный режим)&lt;/h2&gt;
  &lt;p id=&quot;Jbtr&quot;&gt;Режим работы JavaScript по-умолчанию называется &lt;code&gt;sloppy mode&lt;/code&gt; и у него есть свои плюсы и минусы:&lt;/p&gt;
  &lt;h3 id=&quot;SCwb&quot;&gt;Плюсы&lt;/h3&gt;
  &lt;ul id=&quot;ETm3&quot;&gt;
    &lt;li id=&quot;HDXD&quot;&gt;Режим позволяет не обращать внимание на несоответствие кода спецификации JavaScript, например:&lt;/li&gt;
    &lt;ul id=&quot;AEQK&quot;&gt;
      &lt;li id=&quot;iFm7&quot;&gt;Можно использовать переменную до её объявления&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;ykaM&quot;&gt;Минусы&lt;/h3&gt;
  &lt;ul id=&quot;WJsl&quot;&gt;
    &lt;li id=&quot;YeHd&quot;&gt;В коде появляется магия, например, с &lt;a href=&quot;https://thecode.media/js-types/&quot; target=&quot;_blank&quot;&gt;преобразованием типов&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;lpxj&quot;&gt;Код становится менее безопасным&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;hl4g&quot;&gt;Strict mode (строгий режим)&lt;/h2&gt;
  &lt;p id=&quot;Ojlj&quot;&gt;В 2009 году появляется стандарт ECMAScript 5 (ES5). &lt;/p&gt;
  &lt;p id=&quot;9nqi&quot;&gt;Он добавляет новые возможности в язык и изменяет некоторые из существующих. Чтобы устаревший код в новых версиях языка продолжал работать стабильно и предсказуемо, в стандарт был введен &lt;strong&gt;строгий режим&lt;/strong&gt;.&lt;/p&gt;
  &lt;p id=&quot;kkew&quot;&gt;Строгий режим вводит в JavaScript ограничения и некоторые правила по написанию кода:&lt;/p&gt;
  &lt;h3 id=&quot;CsdR&quot;&gt;Правила&lt;/h3&gt;
  &lt;p id=&quot;D3vo&quot;&gt;Значением &lt;code&gt;this&lt;/code&gt; по умолчанию является undefined:&lt;/p&gt;
  &lt;pre id=&quot;aCPf&quot; data-lang=&quot;javascript&quot;&gt;&amp;#x27;use strict&amp;#x27;

function showMeThis() {    
    return this
}

showMeThis() // undefined&lt;/pre&gt;
  &lt;h3 id=&quot;s6lr&quot;&gt;Ограничения&lt;/h3&gt;
  &lt;p id=&quot;ow6O&quot;&gt;Нельзя присваивать значения или обращаться к необъявленным переменным:&lt;/p&gt;
  &lt;pre id=&quot;rupn&quot; data-lang=&quot;javascript&quot;&gt;function returnY() {    
    &amp;#x27;use strict&amp;#x27;    
    y = 123    
    return y
}

returnY() 

// Uncaught ReferenceError: y is not defined&lt;/pre&gt;
  &lt;p id=&quot;YOHt&quot;&gt;Нельзя присваивать значения глобальным переменным, доступным только для чтения или записи:&lt;/p&gt;
  &lt;pre id=&quot;ZQVa&quot; data-lang=&quot;javascript&quot;&gt;&amp;#x27;use strict&amp;#x27;

var NaN = NaN
var undefined = undefined
var Infinity = &amp;#x27;and beyond&amp;#x27;

// Uncaught TypeError: Cannot assign to read only property &lt;/pre&gt;
  &lt;p id=&quot;jy3o&quot;&gt;Нельзя удалить «неудаляемое» свойство объекта:&lt;/p&gt;
  &lt;pre id=&quot;e0n3&quot; data-lang=&quot;javascript&quot;&gt;&amp;#x27;use strict&amp;#x27;

const obj = {}

Object.defineProperties(obj, &amp;#x27;x&amp;#x27;, {
    value: 1
})

delete obj.x 

// Uncaught TypeError: Property description must be an object: x&lt;/pre&gt;
  &lt;p id=&quot;1S4J&quot;&gt;Запрещено дублирование параметров:&lt;/p&gt;
  &lt;pre id=&quot;zhTU&quot; data-lang=&quot;javascript&quot;&gt;&amp;#x27;use strict&amp;#x27;

function someFunc(a, b, b, c) { } 

// Uncaught SyntaxError: Duplicate parameter
// nname ot allowed in this context&lt;/pre&gt;
  &lt;p id=&quot;UjpF&quot;&gt;Нельзя использовать &lt;a href=&quot;https://teletype.in/@boost/js-special-symbols-and-reserved-words&quot; target=&quot;_blank&quot;&gt;зарезервированные слова:&lt;/a&gt;&lt;/p&gt;
  &lt;pre id=&quot;f1Dt&quot; data-lang=&quot;javascript&quot;&gt;abstract extends intertace synchronized boolean false long this break 
final native throw byte finally new throws case float null transient 
catch for package true char function private try class goto protected 
var const if public void continue implements return while default 
import short with do in static double instanceof super else int switch&lt;/pre&gt;
  &lt;h2 id=&quot;lcvq&quot;&gt;Когда использовать строгий режим?&lt;/h2&gt;
  &lt;ul id=&quot;QTFm&quot;&gt;
    &lt;li id=&quot;IPTE&quot;&gt;Защитить код от начинающих разработчиков&lt;/li&gt;
    &lt;li id=&quot;aM9J&quot;&gt;Когда нужно писать чистый и безопасный код&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>boost:browser-api-interview-questions</id><link rel="alternate" type="text/html" href="https://teletype.in/@boost/browser-api-interview-questions?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><title>Вопросы для собеседования по Browser API</title><published>2024-05-31T12:44:57.031Z</published><updated>2024-06-13T12:35:10.710Z</updated><category term="sobesedovaniya" label="Собеседования"></category><summary type="html">Событийная модель</summary><content type="html">
  &lt;h3 id=&quot;fymi&quot;&gt;Темы&lt;/h3&gt;
  &lt;ul id=&quot;5pMA&quot;&gt;
    &lt;li id=&quot;SZEQ&quot;&gt;&lt;a href=&quot;https://teletype.in/@boost/browser-event-model-with-bubbling-and-capturing&quot; target=&quot;_blank&quot;&gt;Событийная модель браузера (bubbling, capturing)&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;0OvO&quot;&gt;&lt;a href=&quot;https://teletype.in/@boost/eventloop&quot; target=&quot;_blank&quot;&gt;Событий цикл (eventloop)&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;lDeM&quot;&gt;Где лучше хранить токен авторизации?&lt;/h3&gt;
  &lt;p id=&quot;zCG0&quot;&gt;В &lt;code&gt;cookies&lt;/code&gt; с использованием флагов:&lt;/p&gt;
  &lt;ul id=&quot;nJmO&quot;&gt;
    &lt;li id=&quot;TBIJ&quot;&gt;&lt;code&gt;secure&lt;/code&gt; передача только по HTTPS&lt;/li&gt;
    &lt;li id=&quot;abQM&quot;&gt;&lt;code&gt;httpOnly&lt;/code&gt; отключение доступа из JavaScript&lt;/li&gt;
  &lt;/ul&gt;
  &lt;hr /&gt;
  &lt;h3 id=&quot;chCL&quot;&gt;Как победить ошибку CORS?&lt;/h3&gt;
  &lt;ul id=&quot;WXOd&quot;&gt;
    &lt;li id=&quot;nSHQ&quot;&gt;Прописать CORS на сервере&lt;/li&gt;
    &lt;li id=&quot;PVho&quot;&gt;Настроить локальный &lt;code&gt;proxy&lt;/code&gt; сервер&lt;/li&gt;
    &lt;li id=&quot;bKJr&quot;&gt;Отключить политику &lt;code&gt;cors&lt;/code&gt; в браузере&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>boost:js-special-symbols-and-reserved-words</id><link rel="alternate" type="text/html" href="https://teletype.in/@boost/js-special-symbols-and-reserved-words?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><title>Специальные символы и зарезервированные слова в JavaScript</title><published>2024-05-11T14:27:51.337Z</published><updated>2024-06-13T13:31:12.345Z</updated><summary type="html">Внутри строк мы можем использовать специальные символы. Это комбинации обычных символов, обозначающих служебные или непечатаемые символы, то есть те, которые нельзя ввести обычным способом:</summary><content type="html">
  &lt;h2 id=&quot;fypA&quot;&gt;Специальные символы&lt;/h2&gt;
  &lt;p id=&quot;Gogz&quot;&gt;Внутри строк мы можем использовать специальные символы. &lt;/p&gt;
  &lt;p id=&quot;Uhb2&quot;&gt;Это комбинации обычных символов, обозначающих &lt;strong&gt;служебные&lt;/strong&gt; или &lt;strong&gt;непечатаемые&lt;/strong&gt; символы, то есть те, которые нельзя ввести обычным способом:&lt;/p&gt;
  &lt;p id=&quot;Vm0x&quot;&gt;&lt;code&gt;\n&lt;/code&gt; перевод строки&lt;/p&gt;
  &lt;p id=&quot;e779&quot;&gt;&lt;code&gt;\f&lt;/code&gt; перевод страницы&lt;/p&gt;
  &lt;p id=&quot;Z83O&quot;&gt;&lt;code&gt;\t&lt;/code&gt; табуляция&lt;/p&gt;
  &lt;p id=&quot;y4zT&quot;&gt;&lt;code&gt;\\&lt;/code&gt; обратный слэш&lt;/p&gt;
  &lt;p id=&quot;XZcL&quot;&gt;&lt;code&gt;\r&lt;/code&gt; возврат каретки &lt;/p&gt;
  &lt;h2 id=&quot;CR2g&quot;&gt;Зарезервированные слова&lt;/h2&gt;
  &lt;p id=&quot;2ENX&quot;&gt;Зарезервированные слова нельзя использовать в каче­стве имен переменных, функций и объектов:&lt;/p&gt;
  &lt;pre id=&quot;Kqvu&quot;&gt;abstract extends intertace synchronized boolean false long this break final
native throw byte finally new throws case float null transient catch for 
package true char function private try class goto protected var const if 
public void continue implements return while default import short with do 
in static double instanceof super else int switch&lt;/pre&gt;

</content></entry><entry><id>boost:flatten-array</id><link rel="alternate" type="text/html" href="https://teletype.in/@boost/flatten-array?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><title>Развернуть вложенный массив | Алгоритмические задачи по JavaScript</title><published>2023-10-30T11:36:39.353Z</published><updated>2023-11-29T16:58:37.739Z</updated><category term="zadachi-po-java-script" label="Задачи по JavaScript"></category><summary type="html">Три подхода для разворачивания массива любой вложенности</summary><content type="html">
  &lt;p id=&quot;VbQi&quot;&gt; Три подхода для разворачивания массива любой вложенности:&lt;/p&gt;
  &lt;h2 id=&quot;unHy&quot;&gt;Код&lt;/h2&gt;
  &lt;h3 id=&quot;tMJp&quot;&gt;&lt;strong&gt;Мутирование&lt;/strong&gt;&lt;/h3&gt;
  &lt;pre id=&quot;yFDv&quot; data-lang=&quot;typescript&quot;&gt;const arr = [1, [2, 3, [4, 5, 6]], 7]

const flat = (arr) =&amp;gt; {
  for (let i = 0; i &amp;lt; arr.length; i++) {
    if (Array.isArray(arr[i])) {
      arr.splice(i, 1, ...arr[i])
    }
  }
  return arr
}

flat(arr) // [1, 2, 3, 4, 5, 6, 7]&lt;/pre&gt;
  &lt;h3 id=&quot;rk7O&quot;&gt;Рекурсия&lt;/h3&gt;
  &lt;pre id=&quot;9INM&quot; data-lang=&quot;javascript&quot;&gt;const arr = [1, [2, 3, [4, 5, 6]], 7]

const flat = (arr) =&amp;gt; {
  const cache = []
  
  for (let i = 0; i &amp;lt; arr.length; i++) {
    if (Array.isArray(arr[i])) {
      cache.push(...flat(arr[i]))
    } else {
      cache.push(arr[i])
    }
  }
  return cache
}

flat(arr) // [1, 2, 3, 4, 5, 6, 7]&lt;/pre&gt;
  &lt;h3 id=&quot;nQwp&quot;&gt;&lt;strong&gt;Стэк&lt;/strong&gt;&lt;/h3&gt;
  &lt;pre id=&quot;ihdl&quot; data-lang=&quot;javascript&quot;&gt;const arr = [1, [2, 3, [4, 5, 6]], 7]

const flat = (arr) =&amp;gt; {
  const stack = [...arr]
  const result = []
  
  while(stack.length &amp;gt; 0) {
     const pop = stack.pop()
     
     if (Array.isArray(pop) {
        stack.unshift(...pop)
     } else {
        result.push(pop)
     }
  }
  
  return result
}

flat(arr) // [1, 2, 3, 4, 5, 6, 7]&lt;/pre&gt;
  &lt;h2 id=&quot;02aw&quot;&gt;Вопросы&lt;/h2&gt;
  &lt;ul id=&quot;emF4&quot;&gt;
    &lt;li id=&quot;E2hK&quot;&gt;Почему рекурсия наиболее худший вариант из предложенных?&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;3n2o&quot;&gt;Полезное&lt;/h2&gt;
  &lt;ul id=&quot;CXwG&quot;&gt;
    &lt;li id=&quot;wCuK&quot;&gt;&lt;a href=&quot;https://learn.javascript.ru/array-methods&quot; target=&quot;_blank&quot;&gt;https://learn.javascript.ru/array-methods&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;kMuJ&quot;&gt;Задачи&lt;/h2&gt;
  &lt;ul id=&quot;AIwr&quot;&gt;
    &lt;li id=&quot;B8ZK&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/flatten-deeply-nested-array/&quot; target=&quot;_blank&quot;&gt;https://leetcode.com/problems/flatten-deeply-nested-array/&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>boost:stack-and-queue</id><link rel="alternate" type="text/html" href="https://teletype.in/@boost/stack-and-queue?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><title>Очереди (stack, queue)</title><published>2023-10-27T08:45:49.463Z</published><updated>2024-05-24T10:17:29.622Z</updated><category term="data-structures" label="Структуры данных"></category><summary type="html">Стек хранит данные в последовательном порядке и удаляет последние добавленные данные.</summary><content type="html">
  &lt;h2 id=&quot;Ov6h&quot;&gt;Стэк (stack)&lt;/h2&gt;
  &lt;p id=&quot;AQOl&quot;&gt;Стек хранит данные в последовательном порядке и удаляет &lt;strong&gt;последние&lt;/strong&gt; (новые) элементы.&lt;/p&gt;
  &lt;h3 id=&quot;pnGM&quot;&gt;Алгоритм&lt;/h3&gt;
  &lt;ul id=&quot;cY3S&quot;&gt;
    &lt;li id=&quot;HCnM&quot;&gt;push: добавить новый элемент&lt;/li&gt;
    &lt;li id=&quot;HltJ&quot;&gt;pop: удалить верхний элемент, вернуть его&lt;/li&gt;
    &lt;li id=&quot;Z1Lh&quot;&gt;peek: вернуть верхний элемент&lt;/li&gt;
    &lt;li id=&quot;ygYw&quot;&gt;length: вернуть количество элементов в стеке&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;98um&quot;&gt;Код&lt;/h3&gt;
  &lt;pre id=&quot;bevt&quot; data-lang=&quot;typescript&quot;&gt;function Stack() { 
  this.count = 0 
  this.storage = {} 
 
  this.push = function(value) { 
    this.storage[this.count] = value 
    this.count++ 
  } 
 
  this.pop = function() { 
 
    if (this.count === 0) return undefined 
    
    this.count-- let
    result = this.storage[this.count] 
    delete this.storage[this.count] 
    
    return result
  } 
 
  this.peek = function() { 
    return this.storage[this.count - 1] 
  } 
 
  this.size = function() { 
    return this.count 
  }
}&lt;/pre&gt;
  &lt;h2 id=&quot;QMst&quot;&gt;Очередь (queue)&lt;/h2&gt;
  &lt;p id=&quot;Ur6P&quot;&gt;Очередь напоминает стек, она так же хранит данные в последовательном порядке, но удаляет самые &lt;strong&gt;первые&lt;/strong&gt; элементы (старые)&lt;/p&gt;
  &lt;h3 id=&quot;t2Mq&quot;&gt;Алгоритм&lt;/h3&gt;
  &lt;ul id=&quot;1nHL&quot;&gt;
    &lt;li id=&quot;UXp2&quot;&gt;enqueue: войти в очередь, добавить элемент в конец&lt;/li&gt;
    &lt;li id=&quot;Yotz&quot;&gt;dequeue: покинуть очередь, удалить первый элемент и вернуть его&lt;/li&gt;
    &lt;li id=&quot;vQRp&quot;&gt;front: получить первый элемент&lt;/li&gt;
    &lt;li id=&quot;6cqj&quot;&gt;isEmpty: проверить, пуста ли очередь&lt;/li&gt;
    &lt;li id=&quot;J9DX&quot;&gt;size: получить количество элементов в очереди&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;mIj1&quot;&gt;Код&lt;/h3&gt;
  &lt;pre id=&quot;bEbO&quot; data-lang=&quot;typescript&quot;&gt;function Queue() { 
  let collection = [] 
  
  this.print = function() { 
    console.log(collection) 
  } 
  
  this.enqueue = function(element) { 
    collection.push(element) 
  } 
  
  this.dequeue = function() { 
    return collection.shift() 
  } 
  
  this.front = function() { 
    return collection[0] 
  } 
  
  this.isEmpty = function() { 
    return collection.length === 0 
  } 
  
  this.size = function() { 
    return collection.length } 
  }&lt;/pre&gt;
  &lt;h2 id=&quot;N0sM&quot;&gt;Задачи&lt;/h2&gt;
  &lt;ul id=&quot;5TUX&quot;&gt;
    &lt;li id=&quot;MsWC&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/valid-parentheses&quot; target=&quot;_blank&quot;&gt;https://leetcode.com/problems/valid-parentheses&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;MnAc&quot;&gt;Видео&lt;/h2&gt;
  &lt;ul id=&quot;jEuF&quot;&gt;
    &lt;li id=&quot;I0di&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=C6CbIReHsNk&quot; target=&quot;_blank&quot;&gt;https://www.youtube.com/watch?v=C6CbIReHsNk&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>boost:hash-tables</id><link rel="alternate" type="text/html" href="https://teletype.in/@boost/hash-tables?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><title>Hash-таблицы (hash table)</title><published>2023-10-26T14:21:35.629Z</published><updated>2024-05-24T10:22:58.006Z</updated><category term="data-structures" label="Структуры данных"></category><summary type="html">Hash-таблица — неупорядоченная структура данных которая позволяет быстро получать значение по ключу независимо от количества данных.</summary><content type="html">
  &lt;p id=&quot;wMPA&quot;&gt;Hash-таблица — неупорядоченная структура данных для быстрого доступа к значению по ключу. &lt;/p&gt;
  &lt;p id=&quot;hdyU&quot;&gt;Вместо индексов таблица генерирует хэши или ключи на основе значения. Расшифровав хэш мы можем быстро получить значение&lt;/p&gt;
  &lt;h3 id=&quot;QmVk&quot;&gt;Плюсы&lt;/h3&gt;
  &lt;ul id=&quot;IzGQ&quot;&gt;
    &lt;li id=&quot;BbSp&quot;&gt;Эффективно работает с неизменяемыми объектами&lt;/li&gt;
    &lt;li id=&quot;L2bO&quot;&gt;Хэш-функция дает (должна) равномерное распределение &lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;nrGY&quot;&gt;Структура&lt;/h3&gt;
  &lt;ul id=&quot;s0mw&quot;&gt;
    &lt;li id=&quot;m4gn&quot;&gt;Словарь для хранения ключей&lt;/li&gt;
    &lt;li id=&quot;ZuFJ&quot;&gt;Хэш-функция (преобразует ключ в уникальный хэш)&lt;/li&gt;
    &lt;li id=&quot;vk7V&quot;&gt;Получение значения по хэшу&lt;/li&gt;
    &lt;li id=&quot;5Ce0&quot;&gt;Удаление значения по хэшу&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;EJKO&quot;&gt;Код&lt;/h3&gt;
  &lt;pre id=&quot;6KB3&quot; data-lang=&quot;typescript&quot;&gt;class HashTable { 
  constructor() { 
    this.memory = []
  } 
  
  hashKey(key) { 
    var hash = 0
    for (var index = 0; index &amp;lt; key.length; index++) { 
      // базовая генерация hash
      var code = key.charCodeAt(index)
      hash = ((hash &amp;lt;&amp;lt; 5) - hash) + code | 0
    } 
    return hash; 
  }
  
  get(key) { 
    var address = this.hashKey(key)
    return this.memory[address]
  }

  remove(key) { 
    var address = this.hashKey(key)

    if (this.memory[address]) { 
        delete this.memory[address]
    }
  }
}&lt;/pre&gt;
  &lt;p id=&quot;CUmC&quot;&gt;Пример hash-функций:&lt;/p&gt;
  &lt;pre id=&quot;qRIl&quot; data-lang=&quot;typescript&quot;&gt;function hash(string, max) { 
  let hash = 0 
  
  for (let i = 0; i &amp;lt; string.length; i++) { 
    hash += string.charCodeAt(i) 
  } 
  
  return hash % max 
}&lt;/pre&gt;
  &lt;h2 id=&quot;WmCx&quot;&gt;Проблемы&lt;/h2&gt;
  &lt;h3 id=&quot;OeWs&quot;&gt;Коллизии&lt;/h3&gt;
  &lt;p id=&quot;kVU2&quot;&gt;Слишком простая функция для генерации хэшей может привести к ситуации когда на один и тот же хэш будут ссылаться разные значения.&lt;/p&gt;
  &lt;h3 id=&quot;zTpL&quot;&gt;Потребление памяти&lt;/h3&gt;
  &lt;p id=&quot;mSko&quot;&gt;При большом размере таблица будет использоваться много памяти. При маленьком размере в таблице будет большой коэффициент заполнения, медленный поиск и удаление&lt;/p&gt;
  &lt;h2 id=&quot;gofi&quot;&gt;Задачи&lt;/h2&gt;
  &lt;ul id=&quot;1jAz&quot;&gt;
    &lt;li id=&quot;8Iqv&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/single-number&quot; target=&quot;_blank&quot;&gt;https://leetcode.com/problems/single-number&lt;/a&gt;  (решить за O(1) по памяти)&lt;/li&gt;
    &lt;li id=&quot;sVpE&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/two-sum&quot; target=&quot;_blank&quot;&gt;https://leetcode.com/problems/two-sum&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;PKsS&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/4sum&quot; target=&quot;_blank&quot;&gt;https://leetcode.com/problems/4sum&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;aeoI&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/group-anagrams&quot; target=&quot;_blank&quot;&gt;https://leetcode.com/problems/group-anagrams&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;VRN4&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/valid-anagram&quot; target=&quot;_blank&quot;&gt;https://leetcode.com/problems/valid-anagram&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;Wugi&quot;&gt;&lt;a href=&quot;https://leetcode.com/problems/find-all-anagrams-in-a-string&quot; target=&quot;_blank&quot;&gt;https://leetcode.com/problems/find-all-anagrams-in-a-string&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;UYHv&quot;&gt;Видео&lt;/p&gt;
  &lt;ul id=&quot;2UpM&quot;&gt;
    &lt;li id=&quot;Ubad&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=0UX4MIfOMEs&quot; target=&quot;_blank&quot;&gt;https://www.youtube.com/watch?v=0UX4MIfOMEs&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;

</content></entry><entry><id>boost:algorithms-and-data-structure</id><link rel="alternate" type="text/html" href="https://teletype.in/@boost/algorithms-and-data-structure?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=boost"></link><title>Алгоритмы и структуры данных</title><published>2023-10-26T13:40:36.027Z</published><updated>2024-05-24T10:24:13.260Z</updated><category term="algoritms" label="Алгоритмы"></category><summary type="html">Это количество операций за которое алгоритм будет выполнен</summary><content type="html">
  &lt;p id=&quot;Ko4c&quot;&gt;Другими словами, алгоритм — это определенная последовательность действий, которая приводит к предсказуемому результату.&lt;/p&gt;
  &lt;p id=&quot;5ytp&quot;&gt;Алгоритмы применяются в разных сферах: интернет, безопасность, мультимедия, социальный сети, физика и биология.&lt;/p&gt;
  &lt;h2 id=&quot;Cdp8&quot;&gt;Сложность алгоритмов&lt;/h2&gt;
  &lt;p id=&quot;pRoM&quot;&gt;Сложность алгоритма это количество операций за которое алгоритм будет выполнен.&lt;/p&gt;
  &lt;ul id=&quot;3Ocd&quot;&gt;
    &lt;li id=&quot;WVme&quot;&gt;&lt;a href=&quot;https://teletype.in/@boost/editor/big-o&quot; target=&quot;_blank&quot;&gt;Оценка сложности алгоритма (Big O)&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;BQTs&quot;&gt;Алгоритмы&lt;/li&gt;
    &lt;ul id=&quot;YBtS&quot;&gt;
      &lt;li id=&quot;s2br&quot;&gt;Поиск&lt;/li&gt;
      &lt;ul id=&quot;Dn8T&quot;&gt;
        &lt;li id=&quot;0Xo5&quot;&gt;&lt;a href=&quot;https://teletype.in/@boost/linear-search&quot; target=&quot;_blank&quot;&gt;Линейный поиск&lt;/a&gt;&lt;/li&gt;
        &lt;li id=&quot;9PBe&quot;&gt;&lt;a href=&quot;https://teletype.in/@boost/binary-search&quot; target=&quot;_blank&quot;&gt;Бинарный поиск&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;li id=&quot;2peu&quot;&gt;Сортировки&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;ul id=&quot;EDHz&quot;&gt;
    &lt;ul id=&quot;1bzc&quot;&gt;
      &lt;ul id=&quot;Ss1X&quot;&gt;
        &lt;li id=&quot;Pqem&quot;&gt;&lt;a href=&quot;https://teletype.in/@boost/bubble-sorting&quot; target=&quot;_blank&quot;&gt;Пузырьком &lt;/a&gt;&lt;/li&gt;
        &lt;li id=&quot;ruoA&quot;&gt;Выбором&lt;/li&gt;
        &lt;li id=&quot;jotK&quot;&gt;Вставками&lt;/li&gt;
        &lt;li id=&quot;XvAw&quot;&gt;&lt;a href=&quot;https://teletype.in/@boost/merge-sort&quot; target=&quot;_blank&quot;&gt;Слиянием &lt;/a&gt;&lt;/li&gt;
        &lt;li id=&quot;bXfd&quot;&gt;Быструю&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;ul id=&quot;rSMz&quot;&gt;
    &lt;ul id=&quot;hkn2&quot;&gt;
      &lt;li id=&quot;07sg&quot;&gt;&lt;a href=&quot;https://teletype.in/@boost/stack-and-queue&quot; target=&quot;_blank&quot;&gt;Очереди&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
    &lt;li id=&quot;9F8E&quot;&gt;Пространственная сложность&lt;/li&gt;
    &lt;ul id=&quot;MXBX&quot;&gt;
      &lt;li id=&quot;63tZ&quot;&gt;Количество памяти которое задействует алгоритм&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;VJyn&quot;&gt;Структуры данных (data structure)&lt;/h2&gt;
  &lt;p id=&quot;t7wQ&quot;&gt;Структуры данных это определенный способ организации данных, предоставляющая механизмы взаимодействия с ними.&lt;/p&gt;
  &lt;ul id=&quot;qP4D&quot;&gt;
    &lt;li id=&quot;xM7P&quot;&gt;&lt;a href=&quot;https://teletype.in/@boost/linked-list&quot; target=&quot;_blank&quot;&gt;Связанный список (linked list)&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;5JXC&quot;&gt;&lt;a href=&quot;https://teletype.in/@boost/editor/4MVPpJ1H2yp&quot; target=&quot;_blank&quot;&gt;Hash-таблицы (hash tables)&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;ESj3&quot;&gt;Материалы&lt;/p&gt;
  &lt;ul id=&quot;M93x&quot;&gt;
    &lt;li id=&quot;bnYy&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/497476/&quot; target=&quot;_blank&quot;&gt;https://habr.com/ru/articles/497476/&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;yXYh&quot;&gt;&lt;a href=&quot;https://proglib.io/p/rasprostranennye-algoritmy-i-struktury-dannyh-v-javascript-osnovnye-ponyatiya-i-rabota-s-massivami-2021-10-06&quot; target=&quot;_blank&quot;&gt;https://proglib.io/p/rasprostranennye-algoritmy-i-struktury-dannyh-v-javascript-osnovnye-ponyatiya-i-rabota-s-massivami-2021-10-06&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;

</content></entry></feed>