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

В каких случаях использовать package

1.0 Junior🔥 221 комментариев
#Основы Java

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

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

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

Использование package в Java

Пакеты — это организационный механизм в Java для группировки связанных классов и контроля видимости.

Что такое package

Пакет — это директория классов с именованным пространством имён.

package com.example.domain;  // Класс находится в com/example/domain/

public class User {
    // ...
}

Случаи использования package

1. Организация кода по функциональности (слои архитектуры)

com.example.app
├── domain              // Бизнес-логика
│   ├── User.java
│   ├── Order.java
│   └── OrderService.java
├── application         // Use Cases
│   ├── CreateOrderUseCase.java
│   └── FindOrderUseCase.java
├── infrastructure      // Базаданные, API, кэш
│   ├── PostgresUserRepository.java
│   ├── HttpPaymentService.java
│   └── RedisCache.java
└── presentation        // REST контроллеры
    ├── UserController.java
    └── OrderController.java

Это следует onion architecture (луковая архитектура). Зависимости идут только внутрь (presentation → application → domain).

2. Контроль доступа через модификаторы доступа

// package-private (видно только внутри пакета)
class InternalHelper {  // без public
    // ...
}

// public (видно везде)
public class User {
    // ...
}

public class User {
    // package-private (видно только в пакете com.example.domain)
    void internalMethod() { }
    
    // public (видно везде)
    public void publicMethod() { }
}

3. Разделение по компонентам (микросервисная архитектура)

com.example
├── auth
│   ├── domain
│   ├── application
│   ├── infrastructure
│   └── presentation
├── users
│   ├── domain
│   ├── application
│   ├── infrastructure
│   └── presentation
└── orders
    ├── domain
    ├── application
    ├── infrastructure
    └── presentation

Каждый компонент независим и может быть отделён в отдельный микросервис.

4. Изоляция внутренних деталей реализации

// com.example.users.domain
public interface UserRepository {
    User findById(String id);
}

// com.example.users.infrastructure
class PostgresUserRepository implements UserRepository {
    // внутренняя реализация, не используется напрямую
    @Override
    public User findById(String id) { }
}

Возможно заменить PostgresUserRepository на MongoUserRepository без изменения кода, который использует интерфейс.

Правила именования package

Используй обратное доменное имя:

// ✅ Правильно
package com.company.product.domain;
package org.springframework.boot;
package com.google.guava;

// ❌ Неправильно
package domain;  // слишком общее
package myapp.domain;  // не обратный домен
package com.mycompany.verylong.nested.structure;  // слишком глубоко

Best Practices

1. Не делай слишком глубокие package иерархии

// ❌ Плохо — слишком глубоко
package com.example.app.domain.entities.user.models.dto;

// ✅ Хорошо — достаточно глубоко
package com.example.users.domain;

2. Используй package-private для скрытия реализации

public class UserService {
    private InternalValidator validator;  // package-private класс
    
    public void createUser(CreateUserRequest req) {
        validator.validate(req);  // видно только в пакете
    }
}

class InternalValidator {  // package-private
    // ...
}

3. Разделяй API и реализацию

com.example.users
├── api
│   ├── UserRepository.java  // публичный интерфейс
│   └── UserService.java
└── impl
    └── PostgresUserRepository.java  // внутренняя реализация

4. Избегай циклических зависимостей между пакетами

// ❌ Проблема
// users → orders (импортирует OrderService)
// orders → users (импортирует UserService)

// ✅ Решение
// users → events (публикует события)
// orders → events (слушает события)

Пример правильной структуры проекта

src/main/java/com/example/shop
├── shared
│   ├── domain
│   │   ├── DomainEvent.java
│   │   └── Repository.java
│   └── application
│       └── ApplicationService.java
├── users
│   ├── domain
│   │   ├── User.java
│   │   ├── UserId.java
│   │   └── UserRepository.java  (интерфейс)
│   ├── application
│   │   ├── CreateUserUseCase.java
│   │   └── FindUserUseCase.java
│   ├── infrastructure
│   │   └── PostgresUserRepository.java  (реализация)
│   └── presentation
│       └── UserController.java
└── orders
    ├── domain
    ├── application
    ├── infrastructure
    └── presentation

Когда НЕ использовать package

Не переусложняй:

// ❌ Переусложнено для маленького проекта
com.example.calculator.domain.math.operations.arithmetic.addition

// ✅ Достаточно
com.example.calculator.domain

Вывод

Используй package для:

  1. Организации кода по слоям архитектуры
  2. Контроля доступа через package-private модификатор
  3. Изоляции реализации от публичного API
  4. Разделения компонентов в больших проектах
  5. Избегания конфликтов имён между проектами

Пакеты — это не просто папки, это инструмент проектирования архитектуры. Правильная структура package помогает другим разработчикам понять код и его зависимости.