Hexagonal Mimari: Kavram ve Uygulama
Çekirdek: Uygulamanın temel iş mantığını içeren kısım.Portlar: Çekirdeğin dış dünyayla etkileşim kurduğu ara yüzler.Adaptörler: Portları uygulayan ve dış dünyaya bağlanan bileşenler.
Test edilebilirlik: Çekirdek, dış bağımlılıklardan bağımsız olarak test edilebilir.Esneklik: Dış dünyadaki değişiklikler çekirdeği etkilemez.Yeniden kullanılabilirlik: Çekirdek, farklı adaptörlerle farklı ortamlarda kullanılabilir.
// Çekirdek
public class UserService {
private final UserPersistence userPersistence;
public UserService(UserPersistence userPersistence) {
this.userRepo = userRepo;
}
public User createUser(User user) {
return userRepo.save(user);
}
}
// Port
public interface UserPersistence {
User save(User user);
User findById(Long id);
}
// Adaptör (Spring Data JPA)
public class JPAUserRepo implements UserPersistence {
private final UserRepository userRepository;
public JPAUserRepo(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public User save(User user) {
return userRepository.save(user);
}
@Override
public User findById(Long id) {
return userRepository.findById(id).orElseThrow(() -> new NotFoundException("Kullanıcı bulunamadı."));
}
}
// Spring Boot Uygulaması
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public UserService userService(UserPersistence userPersistence) {
return new UserService(userPersistence);
}
@Bean
public UserPersistence jpaUserRepo(UserRepository userRepository) {
return new JPAUserRepo(userRepository);
}
}
UserRepo arayüzü, çekirdeğin veri erişimini nasıl yapacağını tanımlar. UserService, temel iş mantığını içerir ve UserRepo arayüzünü kullanır. UserPersistence arayüzü, port görevi görür ve veri erişiminin nasıl yapılacağını tanımlar. JPAUserRepo, UserPersistence arayüzünü uygulayan ve JPA kullanarak veriye erişen bir adaptör. Application sınıfı, Spring Boot uygulamasını başlatır ve bağımlılıkları oluşturur.
UserService, JPAUserRepo ile sıkı sıkıya bağlı değildir, bu da bağımsızlık ve test edilebilirliği sağlar. Uygulamanın veri depolamasının nasıl yapıldığını değiştirmek (örneğin, bir başka veritabanı teknolojisi kullanmak veya dosya sistemine kaydetmek) yalnızca adaptör değiştirilerek yapılabilir.
Hexagonal mimari, bir mimari stilidir, kesin bir uygulama yoktur. Kullanılacak portlar ve adaptörler uygulamaya bağlı olarak değişebilir. Çekirdek genellikle bir domain model olarak düşünülür, ancak bu zorunlu değildir.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MongoUserRepository extends MongoRepository<User, String> {
// İhtiyaç duyduğunuz özel sorguları burada tanımlayabilirsiniz.
// Örneğin:
// User findByEmail(String email);
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MongoUserRepo implements UserPersistence {
private final MongoUserRepository mongoUserRepository;
@Autowired
public MongoUserRepo(MongoUserRepository mongoUserRepository) {
this.mongoUserRepository = mongoUserRepository;
}
@Override
public User save(User user) {
return mongoUserRepository.save(user);
}
@Override
public User findById(Long id) {
return mongoUserRepository.findById(id)
.orElseThrow(() -> new NotFoundException("Kullanıcı bulunamadı."));
}
}
@SpringBootApplication
public class Application {
// ... diğer kodlar
@Bean
public UserPersistence mongoUserRepo(MongoUserRepository mongoUserRepository) {
return new MongoUserRepo(mongoUserRepository);
}
}
spring.data.mongodb.uri=mongodb://localhost:27017/mydatabase
MongoUserRepository sınıfında, ihtiyacınıza göre özel sorgular tanımlayabilirsiniz. Uygulamada farklı veri depolamaları kullanmak isterseniz, her bir depolama için ayrı adaptörler oluşturabilirsiniz. Hexagonal mimari, uygulamanızı daha esnek, test edilebilir ve sürdürülebilir hale getirir.