現実世界の Java
理論から実践へ移行するには、次のことを知る必要があります。 ベストプラクティス 専門的なプロジェクトを構築するため: ロギング、構成、環境管理。
何を学ぶか
- プロフェッショナルなプロジェクト構造
- SLF4J と Logback を使用したロギング
- アウトソーシングされた構成
- 環境管理 (開発、テスト、本番)
プロジェクトの構造
my-project/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/
│ │ │ ├── Application.java
│ │ │ ├── config/
│ │ │ ├── controller/
│ │ │ ├── service/
│ │ │ ├── repository/
│ │ │ ├── model/
│ │ │ └── util/
│ │ └── resources/
│ │ ├── application.properties
│ │ ├── application-dev.properties
│ │ ├── application-prod.properties
│ │ └── logback.xml
│ └── test/
│ ├── java/
│ └── resources/
├── pom.xml (o build.gradle)
└── README.md
ロギング
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserService {
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
public User findUser(Long id) {
logger.debug("Cercando utente con ID: {}", id);
try {
User user = repository.findById(id);
logger.info("Utente trovato: {}", user.getName());
return user;
} catch (UserNotFoundException e) {
logger.warn("Utente non trovato: {}", id);
throw e;
} catch (Exception e) {
logger.error("Errore durante ricerca utente", e);
throw new ServiceException("Errore interno", e);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d [%thread] %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
<logger name="com.example" level="DEBUG" />
</configuration>
構成
# Database
db.url=jdbc:postgresql://localhost:5432/mydb
db.username=user
db.password=password
db.pool.size=10
# API
api.timeout.ms=5000
api.retry.count=3
# Feature flags
feature.newUi.enabled=true
import java.io.*;
import java.util.Properties;
public class ConfigurationManager {
private static final Properties props = new Properties();
static {
String env = System.getProperty("app.env", "dev");
String filename = "application-" + env + ".properties";
try (InputStream is = ConfigurationManager.class
.getClassLoader().getResourceAsStream(filename)) {
if (is != null) {
props.load(is);
}
} catch (IOException e) {
throw new RuntimeException("Impossibile caricare configurazione", e);
}
}
public static String get(String key) {
return props.getProperty(key);
}
public static int getInt(String key, int defaultValue) {
String value = props.getProperty(key);
return value != null ? Integer.parseInt(value) : defaultValue;
}
public static boolean getBoolean(String key) {
return Boolean.parseBoolean(props.getProperty(key));
}
}
// Uso
String dbUrl = ConfigurationManager.get("db.url");
int timeout = ConfigurationManager.getInt("api.timeout.ms", 3000);
ベストプラクティス
プロフェッショナルプロジェクトのルール
- コードから構成を分離する: プロパティファイル、環境変数
- 構造化された方法でログインする: 適切なレベル、System.out なし
- アーキテクチャレイヤーを使用する: コントローラー、サービス、リポジトリ
- 自動テスト: ユニット、統合、e2e
- 書類: README、パブリック API の Javadoc
- 例外を管理する: 集中化、ロギングあり







