Что заставляет сказать 'Этот разработчик — сеньор'

#frontend#architecture#senior

TL;DR

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

Введение: Beyond Hello World

Когда junior сосредоточен на “как сделать”, senior думает о “как не сломать”. Разница проявляется в мелочах: от обработки edge-кейсов до проектирования системы, которая не треснет при первом же требовании продукт-менеджера. Рассмотрим индикаторы профессионализма через призму React-экосистемы.

1. State Management: Когда Context уже недостаточно

Показательный пример — выбор стейт-менеджмента не по популярности, а по domain-логике:

// Не просто Zustand, а с гранулярной подпиской
const useUserPreferences = create<UserPreferences>()((set) => ({
  theme: 'light',
  updateTheme: (theme) => set({ theme }),
}));

// В компоненте:
const theme = useUserPreferences((state) => state.theme);

Почему это senior:

2. Эффекты как first-class citizen

Типичный антипаттерн junior — useEffect везде, где нужно “что-то сделать”. Альтернатива:

// Кастомный хук для аналитики
function useAnalyticsEffect(event: AnalyticsEvent, deps: DependencyList) {
  const analytics = useAnalytics();
  useEffect(() => {
    analytics.track(event);
  }, [analytics, ...deps]);
}

// Использование:
useAnalyticsEffect('page_view', [pathname]);

Что это показывает:

3. TypeScript как дизайн-система

Senior использует TS не для аннотаций, а для проектирования:

// Вместо примитивов — branded types
type UserId = string & { __brand: 'userId' };
type Email = string & { __brand: 'email' };

// Валидация при runtime (Zod + type narrowing)
const UserSchema = z.object({
  id: z.string().transform((val) => val as UserId),
  email: z.string().email().transform((val) => val as Email),
});

Почему важно:

4. Тестирование: не только Jest

Профессионал тестирует не только рендер, но и поведение:

// Интеграционный тест с MSW
test('loads user data', async () => {
  server.use(
    rest.get('/api/user', (req, res, ctx) => {
      return res(ctx.json(mockUser));
    })
  );

  render(<UserProfile />);
  await waitFor(() => {
    expect(screen.getByText(mockUser.name)).toBeInTheDocument();
  });
});

Что ценного:

5. Перформанс как feature

Оптимизации не по шаблону, а по данным:

// Динамический импорт + Suspense границы
const HeavyChart = React.lazy(() => import('./HeavyChart'));

function Dashboard() {
  return (
    <ErrorBoundary>
      <Suspense fallback={<ChartSkeleton />}>
        <HeavyChart />
      </Suspense>
    </ErrorBoundary>
  );
}

Критерии senior-подхода:

Практическое применение

Собираем всё вместе в реальном сценарии — форма с валидацией:

function CheckoutForm() {
  const { register, handleSubmit } = useForm<CheckoutData>({
    resolver: zodResolver(CheckoutSchema),
  });

  useAnalyticsEffect('checkout_viewed', []);
  const { mutateAsync } = useCheckoutMutation();

  const onSubmit = handleSubmit(async (data) => {
    await mutateAsync(data);
  });

  return (
    <form onSubmit={onSubmit}>
      <Input {...register('email')} />
      <AsyncSubmitButton loadingText="Processing..." />
    </form>
  );
}

Что здесь senior-grade:

Заключение: Идеология против синтаксиса

Настоящий senior — не тот, кто знает все хуки React, а тот, кто понимает, когда их не использовать. Профессионализм измеряется не количеством зависимостей в package.json, а способностью объяснить, почему в проекте их именно столько. Ваш код — это автопортрет: пусть в нём читается не только умение гуглить, но и инженерная культура.


Источник: https://www.reddit.com/r/webdev/comments/1qifdm5/what_are_things_that_you_see_and_make_you_say/