← Назад к вопросам

Разрабатывал ли новый код

1.2 Junior🔥 131 комментариев
#Soft Skills и карьера

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Развитие новых функций: от концепции к production

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

Проект: Real-time Notification System

Контекст:

Мы разрабатывали e-commerce платформу, и возник запрос: нужна система уведомлений, которая информирует пользователей о:

  • Смене статуса заказа (в обработке, готово, отправлено)
  • Появлении товара на складе
  • Скидках на интересующие товары

Требование: real-time, не более 5 секунд задержки, поддержка 100K concurrent users.

Фаза 1: Дизайн и планирование

Анализ требований:

// Требования выкристаллизовались следующие:

public class NotificationRequirements {
    // Функциональные требования
    private List<NotificationType> supportedTypes = Arrays.asList(
        NotificationType.ORDER_STATUS_CHANGED,
        NotificationType.PRODUCT_AVAILABLE,
        NotificationType.PRICE_DROPPED
    );
    
    // Non-functional требования
    private int maxLatencySeconds = 5;
    private int expectedConcurrentUsers = 100_000;
    private double reliability = 0.999;  // 99.9% uptime
    
    // Предпочтение по каналам
    private List<Channel> channels = Arrays.asList(
        Channel.WEBSOCKET,      // Real-time preferred
        Channel.PUSH_NOTIFICATION,
        Channel.EMAIL           // Fallback
    );
}

Архитектурное решение:

Применение Event-Driven Architecture с Message Queue:

┌──────────────┐
│   Services   │  (Order, Product, Inventory)
│   (Event)    │
└──────┬───────┘
       │ publish
       ▼
┌─────────────────┐
│  RabbitMQ       │  Event Bus
│  (AMQP)         │
└────────┬────────┘
         │ subscribe
    ┌────┴─────┐
    ▼          ▼
┌─────────┐ ┌──────────────┐
│ WebSocket│ │ Push Notif   │
│ Handler  │ │ Service      │
└────┬────┘ └──────┬───────┘
     │             │
     └──────┬──────┘
            ▼
      ┌──────────────┐
      │  User Client │
      └──────────────┘

Фаза 2: Разработка ядра

Шаг 1: Определение моделей и контрактов

// Domain Model
@Entity
@Table(name = "notifications")
public class Notification {
    @Id
    private UUID id;
    
    @Enumerated(EnumType.STRING)
    private NotificationType type;
    
    private UUID recipientId;
    private String title;
    private String message;
    private LocalDateTime createdAt;
    private LocalDateTime sentAt;
    
    @Enumerated(EnumType.STRING)
    private NotificationStatus status;  // PENDING, SENT, FAILED
}

public enum NotificationType {
    ORDER_STATUS_CHANGED,
    PRODUCT_AVAILABLE,
    PRICE_DROPPED
}

public enum Channel {
    WEBSOCKET,
    PUSH_NOTIFICATION,
    EMAIL
}

// Event Contract
public abstract class DomainEvent {
    private UUID eventId = UUID.randomUUID();
    private LocalDateTime timestamp = LocalDateTime.now();
    private String aggregateId;
    
    public abstract NotificationType getNotificationType();
}

public class OrderStatusChangedEvent extends DomainEvent {
    private UUID orderId;
    private OrderStatus oldStatus;
    private OrderStatus newStatus;
    private UUID userId;
    
    @Override
    public NotificationType getNotificationType() {
        return NotificationType.ORDER_STATUS_CHANGED;
    }
}

Шаг 2: Event Publisher

// Application Layer
@Service
public class OrderService {
    @Autowired
    private OrderRepository repository;
    
    @Autowired
    private EventPublisher eventPublisher;
    
    @Transactional
    public Order updateOrderStatus(UUID orderId, OrderStatus newStatus) {
        Order order = repository.findById(orderId)
            .orElseThrow(() -> new OrderNotFoundException(orderId));
        
        OrderStatus oldStatus = order.getStatus();
        order.setStatus(newStatus);
        
        // Сохраняем в БД
        repository.save(order);
        
        // Публикуем событие (важно ПОСЛЕ сохранения!)
        eventPublisher.publish(
            new OrderStatusChangedEvent(
                orderId,
                oldStatus,
                newStatus,
                order.getUserId()
            )
        );
        
        return order;
    }
}

// Infrastructure Layer
@Service
public class RabbitMqEventPublisher implements EventPublisher {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Override
    public void publish(DomainEvent event) {
        rabbitTemplate.convertAndSend(
            "notifications.exchange",
            "event." + event.getNotificationType().toString().toLowerCase(),
            event
        );
    }
}

Шаг 3: Notification Handler

// Application Service
@Service
public class NotificationService {
    @Autowired
    private NotificationRepository repository;
    
    @Autowired
    private ChannelDispatcher dispatcher;
    
    @Autowired
    private UserPreferenceService preferences;
    
    @RabbitListener(queues = "notification.queue")
    public void handleEvent(DomainEvent event) {
        try {
            // 1. Получить предпочтения пользователя
            UUID userId = event.getAggregateId();  // Упрощённо
            UserNotificationPreference prefs = preferences.getPreferences(userId);
            
            // 2. Создать уведомление
            Notification notification = createNotification(event);
            repository.save(notification);
            
            // 3. Отправить по предпочитаемым каналам
            dispatcher.dispatch(notification, prefs.getChannels());
            
            // 4. Обновить статус
            notification.setStatus(NotificationStatus.SENT);
            notification.setSentAt(LocalDateTime.now());
            repository.save(notification);
            
        } catch (Exception e) {
            logger.error("Failed to process event: " + event, e);
            // Retry logic через Dead Letter Queue
        }
    }
    
    private Notification createNotification(DomainEvent event) {
        // Преобразуем event в notification
        Notification notif = new Notification();
        notif.setId(UUID.randomUUID());
        notif.setType(event.getNotificationType());
        notif.setCreatedAt(LocalDateTime.now());
        // ...
        return notif;
    }
}

Шаг 4: Channel Dispatcher (Strategy Pattern)

@Service
public class ChannelDispatcher {
    @Autowired
    private Map<Channel, NotificationChannel> channels;
    
    public void dispatch(Notification notification, List<Channel> preferredChannels) {
        for (Channel channel : preferredChannels) {
            try {
                NotificationChannel handler = channels.get(channel);
                if (handler != null) {
                    handler.send(notification);
                    break;  // Успешно отправили
                }
            } catch (Exception e) {
                logger.warn("Failed to send via " + channel, e);
                // Пробуем следующий канал
            }
        }
    }
}

public interface NotificationChannel {
    void send(Notification notification) throws NotificationException;
}

// WebSocket implementation
@Component("WEBSOCKET")
public class WebSocketNotificationChannel implements NotificationChannel {
    @Autowired
    private WebSocketSessionManager sessionManager;
    
    @Override
    public void send(Notification notification) throws NotificationException {
        String userId = notification.getRecipientId().toString();
        WebSocketSession session = sessionManager.getSession(userId);
        
        if (session != null && session.isOpen()) {
            session.sendMessage(
                new TextMessage(toJson(notification))
            );
        } else {
            throw new NotificationException("WebSocket session not available");
        }
    }
}

// Push Notification implementation
@Component("PUSH_NOTIFICATION")
public class PushNotificationChannel implements NotificationChannel {
    @Autowired
    private FirebaseMessaging firebaseMessaging;
    
    @Override
    public void send(Notification notification) throws NotificationException {
        Message message = Message.builder()
            .setToken(getDeviceToken(notification.getRecipientId()))
            .setNotification(
                com.google.firebase.messaging.Notification.builder()
                    .setTitle(notification.getTitle())
                    .setBody(notification.getMessage())
                    .build()
            )
            .build();
        
        firebaseMessaging.send(message);
    }
}

Фаза 3: Тестирование

Unit тесты:

@SpringBootTest
public class NotificationServiceTest {
    @Autowired
    private NotificationService service;
    
    @MockBean
    private NotificationRepository repository;
    
    @MockBean
    private ChannelDispatcher dispatcher;
    
    @Test
    public void shouldCreateAndDispatchNotification() {
        // Given
        OrderStatusChangedEvent event = new OrderStatusChangedEvent(
            UUID.randomUUID(),
            OrderStatus.PENDING,
            OrderStatus.PROCESSING,
            UUID.randomUUID()
        );
        
        // When
        service.handleEvent(event);
        
        // Then
        verify(repository, times(2)).save(any(Notification.class));
        verify(dispatcher, times(1)).dispatch(any(), any());
    }
}

Load тесты:

@SpringBootTest
public class NotificationLoadTest {
    @Autowired
    private EventPublisher publisher;
    
    @Test
    public void shouldHandleHighLoad() throws InterruptedException {
        int numMessages = 10_000;
        ExecutorService executor = Executors.newFixedThreadPool(10);
        
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < numMessages; i++) {
            executor.submit(() -> {
                publisher.publish(new OrderStatusChangedEvent(...));
            });
        }
        
        executor.shutdown();
        executor.awaitTermination(5, TimeUnit.MINUTES);
        
        long duration = System.currentTimeMillis() - startTime;
        double throughput = numMessages / (duration / 1000.0);
        
        System.out.println("Throughput: " + throughput + " messages/sec");
        assertTrue(throughput > 1000);  // Минимум 1000 msg/sec
    }
}

Фаза 4: Развёртывание и мониторинг

@Configuration
public class NotificationMetrics {
    @Bean
    public MeterRegistry meterRegistry() {
        return new MicrometerRegistry();
    }
    
    @Bean
    public NotificationMetricsAspect metricsAspect(MeterRegistry registry) {
        return new NotificationMetricsAspect(registry);
    }
}

@Aspect
@Component
public class NotificationMetricsAspect {
    private MeterRegistry registry;
    
    @Around("@annotation(com.example.Monitored)")
    public Object trackMetrics(ProceedingJoinPoint pjp) throws Throwable {
        String methodName = pjp.getSignature().getName();
        
        Timer timer = Timer.start();
        try {
            Object result = pjp.proceed();
            registry.timer("notification." + methodName + ".success").record(timer.stop());
            return result;
        } catch (Exception e) {
            registry.counter("notification." + methodName + ".failed").increment();
            throw e;
        }
    }
}

Фаза 5: Итерации и улучшения

После первого месяца в production:

1. Performance: добавил Redis кэширование для user preferences
2. Reliability: внедрил Circuit Breaker для Firebase API
3. User Experience: добавил WebSocket reconnection logic
4. Scalability: миграция на Kafka вместо RabbitMQ для большей пропускной способности

Результаты

Метрики:

  • Latency: 95th percentile = 1.2 сек (требование: 5 сек) ✅
  • Reliability: 99.97% (требование: 99.9%) ✅
  • Throughput: 15,000 notifications/sec
  • User satisfaction: 4.8/5 (feedback)

Код quality:

  • Test coverage: 92%
  • 0 production bugs за 6 месяцев
  • Cyclomatic complexity: в норме

Ключевые навыки, которые развивал

  1. System Design: архитектура из requirement до implementation
  2. Event-Driven Development: асинхронные системы, message queues
  3. Performance Optimization: load testing, profiling, caching
  4. DevOps awareness: мониторинг, логирование, alerting
  5. Team Collaboration: код review, документирование, знание transfer

Вывод

Разработка нового функционала — это не просто написание кода, это:

  • Глубокое понимание требований — не бери за очевидное
  • Архитектурные решения — выбирай правильный инструмент
  • Качественное тестирование — unit + load + integration тесты
  • Production mindset — мониторинг и поддержка после launch
  • Постоянное улучшение — iterate на основе метрик и feedback
Разрабатывал ли новый код | PrepBro