EasyDev | Селедков Тимур
236 subscribers
4 links
EasyDev - сообщество для бесплатного обучения веб-разработке и прокачке навыков. Стань разработчиком! Это просто!

Группа с чатом:
t.me/easydev_club

Менторство:
https://easydev.club

YouTube канал:
https://youtube.com/@easydev_it
Download Telegram
Меня зовут Тимур, я Senior Frontend Developer, TeamLead и ментор.

Успешно разработал и вывел в эксплуатацию 5 продуктов с нуля.

Три в Сбербанке (Продукт года ежегодной премии Digital Leaders)
Два в продуктовой компании.
Менторю с лета 2022.

Мой стек: TypeScript, React, Vue3

Помогаю людям с любым уровнем знаний стать разработчиками с зп от 200к

Менторство && Отзывы

Роадмап с нуля до джуна
https://miro.com/app/board/uXjVMXKy4gQ=/

https://easydev.yonote.ru/share/cources-accounts

Я выкинул все лишнее, остается только то что понадобится для реальной работы над проектом, если нужен аккаунт с курсами из роадмапа пишите в лс бесплатно выдам
👍4🔥21
#доклад #навыки
Как сделать сложную таску?

https://easydev.yonote.ru/share/skill-how-make-hard-task

Когда задачу можно назвать сложной?

Выделю три типа "сложных" задач:

1.Недостаточно вводных данных
Пример: У Васи задача “сделать поиск как в гугле”
Чеклист:
- есть тз?
- есть апи?
- есть макет?
Решение: уточняем вводные данные, у кого?
мой видос по воркфлоу, определяем чья зона ответственности, понимаем кому написать, ответы крепим к задаче комментами или в описание самой задачи

2. Объемная
Пример: сделать редизайн всего приложения
Решение?
разбиваем на подзадачи по блокам или функциональности

например:
- сделать редизайн страницы регистрации и авторизации
- сделать редизайн главного меню
- сделать редизайн страницы А
- сделать редизайн страницы Б

3. У нас нет точного представления как ее сделать

Например: “Сделать страницу поиска как в Google”

Типовые проблемы:
- Непонятно с чего начинать
- Пробуем делать все сразу, постоянно переключаемся из-за чего мы тратим много энергии, при этом темп работы выходит низкий, а результата не видно

Решение:
а) Приоритезация
- Разбиваем задачу на функционал, ориентируемся на юзер стори
Например: “сделать поиск и вывести результаты” это минимальный полезный функционал, самых важных 1-3 юзер стори

b) Декомпозиция
- Разбиваем приоритетную задачу до тех пор пока не будет понятно как ее сделать за конечное время, за условных 1-2часа

Например:
b.1) “сделать поиск”
- ввод текста
- отправка текста на бэк и получение результата
b.2) сделать вывод результатов
- сделать компонент выводимого результата
- разложить полученные данные по компонентам
b.3) сделать переход на страницы найденных результатов
- сделать у компонента результата кликабельную ссылку с переходом

c) Реализация
- Садимся и делаем первую задачу с проведенной декомпозиции и СТРОГО только ее!!!
- реализуем следующую одну за другой

Следующая итерация с пункта 3.а


Какая польза использования данного подхода?

1) когда мы видим простую и понятную задачу ее легче начать делать, а значит и сделать
2) закрывая много маленьких задач наш мозг получает постоянное позитивное подкрепление
3) закрывая подзадачи мы видим прогресс выполнения нашей большой задачи и мы знаем что сказать на дейлики и можем спрогнозировать сроки
4) при решении понятных задач наш мозг меньше устает и его ресурса дольше хватает

Лайфхаки работающие у меня:
- дневной сон
- прогулка без девайсов
- рабочие сессии по 2-3 часа
- помидорро
- тайм блокинг
🔥73👍321❤‍🔥1🕊1🍓1💘1
На собеседеованиях один из самых частых вопросов по TypeScript - чем type отличается от interface?

Давайте разбираться:

1️⃣ Для каких структур предназначен

Interface преднаначен для описания структур объектов


interface User {
name: string;
age: number;
}


type универсален и может описывать не только структуры объектов, но и примитивные типы, объединение и др


type User = {
name: string;
age: number;
};

type SerialCode = string


2️⃣ Объединения (Union)

type умеет а interface нет


type TypeAorB = TypeA | TypeB;

type ID = number | string

type TaskStatus = 'todo' | 'processed' | 'done' | 'testing';


3️⃣Расширение

type расширяется через & (intersection)



type TypeAandB = TypeA & TypeB;


interface через ключевое слово extends



interface IAandB extends IA, IB {}


4️⃣Слияние деклараций

Интерфейсы поддерживают слияние деклараций, что позволяет определять несколько интерфейсов с одинаковым именем, которые TypeScript объединит в один:

лично я считаю это плохой практикой и всегда говорю об этом на собеседовании


interface IA {
name: string;
}

interface IA {
age: number;
}

// в результате будет так:
interface IA {
name: string;
age: number;
}


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

5️⃣Классы и interface:

Классы могут реализовывать interface с помощью ключевого слова implements.



interface IA {
name: string;
}

class Cat implements IA {
name: string;
constructor(name: string) {
this.name = name;
}
}


В случае с type можно имплеменитровать его только если он в виде описания объекта или пересечения объектов.
Нельзя с примитивом или объединением(union)



type Text = string;

class Example implements Text { }
// Ошибка: A class can only implement an object type or intersection of object types with statically known members


type Shape = Circle | Square;

class Figure implements Shape { }
// Ошибка A class can only implement an object type or intersection of object types with statically known members




// описание объекта
type Identifiable = {
id: number | string // тут можно union тк описывается ключ объекта
};

// пересечение объектов
type UserType = Identifiable & {
name: string;
age: number;
};

// Все хорошо
class User implements UserType {
id: number | string;
name: string;
age: number;

constructor(id: number, name: string, age: number) {
this.id = id;
this.name = name;
this.age = age;
}
}


Менторство && Отзывы
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥184👍4
Качаем frontend бицуху - как обновлять данные в UI, если мы их меняем на сервере ⁉️

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


1. Оптимистичное (позитивное) обновление

Описание:
UI мгновенно отражает изменение, не дожидаясь ответа сервера. Запрос отправляется «в фоне», а интерфейс уже показывает результат. При ошибке происходит «откат» назад и выводится уведомление.

В чем фишка:
* Мгновенная реакция приложения — пользователь не видит задержек и получает «живой» отклик.
* Снижение ощущаемой латентности, особенно важно в высокоинтерактивных сценариях.
* Простота UX — нет «зависшего» состояния ожидания.

Рассмотрим на примере: «лайк котиков в соцсети»

1. Пользователь кликает «лайк» у фотографии кота.
2. Счётчик лайков тут же увеличивается в интерфейсе (+1).
3. В фоне отправляется запрос:


POST /cats/{catId}/like

4. Если сервер вернёт 200 OK — ничего не меняем.
5. Если ошибка — возвращаем счётчик на прежнее значение и показываем сообщение «Не удалось поставить лайк».



2. Пассивное (рефетч после мутации) обновление

Описание:
UI меняет данные только после подтверждения от сервера. Сначала отправляется запрос на изменение, затем, получив успешный ответ и (опционально) тело с обновлёнными данными, интерфейс обновляется.

В чем фишка:
* Гарантия консистентности локального состояния с серверным.
* Нет необходимости писать логику «отката» — изменения применяются только после «200 OK».
* Меньше лишних запросов, чем при полном рефетче всего списка.

Рассмотрим на примере: «локальный ToDo-список»

1. Пользователь редактирует задачу и нажимает «Сохранить».
2. Отправляется запрос:


PUT /todos/{todoId}

3. Ожидаем ответа сервера.
4. Если пришёл 200 OK с телом обновлённой задачи — заменяем запись в локальном списке. (если апишка не возвращает обновленные данные то делаем перезапрос этой сущности по ид и ее пихаем в стейт)
5. При ошибке (400/500 или сбое сети) — оставляем старое состояние и выводим «Не удалось сохранить задачу».


🌐 3. Серверное (рефетч всего списка) обновление

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

В чем фишка:
* Максимальная актуальность — вы точно знаете текущее состояние всей очереди или каталога.
* Избежание рассинхрона в многопользовательских сценариях, где многие участники параллельно меняют одни и те же данные.
* Упрощённая логика обработки конфликтов — нет «частичных» обновлений.

Рассмотрим на примере:: «Таск-трекер» Или «Сервис Доставки»

1. Курьер нажимает «Выполнено» на задаче.
2. Отправляется запрос:


PUT /todos/{todoId}

3. После 200 OK сразу выполняется дополнительный запрос:


GET /tasks

4. Полученные данные (следующая задача или весь актуальный список) полностью заменяют локальную очередь.
5. При ошибке любого из запросов — выводится сообщение об ошибке и предлагается повторить операцию.

---

Вывод:
Все три стратегии нормальны и имеют право на жизнь. Выбирайте в зависимости от конкретного бизнес-кейса:

Оптимистичное — для мгновенных реакций (лайки, быстрые клики, чат).

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

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

Менторство && Отзывы
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20👍4😁21