Skip to content

Instantly share code, notes, and snippets.

@msbaek
msbaek / userRepository.java
Created December 21, 2025 03:59
userRepository
public void updateName(Long id, String newName) {
User user = userRepository.findById(id).orElseThrow(); // 그냥 POJO
user.setName(newName);
userRepository.save(user); // 명시적. 호출 안 하면 아무 일도 없다.
}
@msbaek
msbaek / OrderRepositoryInMemory.java
Created December 21, 2025 03:57
OrderRepositoryInMemory
static class OrderRepositoryInMemory implements OrderRepository {
private final Map<Long, Order> orders = new ConcurrentHashMap<>();
private final AtomicLong idGenerator = new AtomicLong(1);
public Order save(Order order) {
if (order.getId() == null) {
Long id = idGenerator.getAndIncrement();
Order savedOrder = new Order(id, order.getItems());
orders.put(id, savedOrder);
return savedOrder;
@msbaek
msbaek / tt.java
Created December 21, 2025 03:47
jpa-wrapper
// 순수 인터페이스 (도메인 계층)
public interface OrderRepository {
Order save(Order order);
Optional<Order> findById(Long id);
}
// JPA 구현체 (인프라 계층)
@Repository
public class JpaOrderRepository implements OrderRepository {
private final OrderJpaRepository jpaRepository;
@msbaek
msbaek / OrderService.java
Created December 21, 2025 03:45
도메인 서비스가 JpaRepository에 직접 의존
// 도메인 서비스가 JpaRepository에 직접 의존
@Service public class OrderService {
private final OrderRepository orderRepository; // JpaRepository 상속
public void createOrder(OrderRequest request) {
// 도메인 로직이 JPA에 종속됨
}
}
@msbaek
msbaek / update.java
Created December 21, 2025 03:41
더티 체킹의 함정
@Transactional
public void updateName(Long id, String newName) {
User user = userRepository.findById(id).orElseThrow();
user.setName(newName);
// 여기서 마법이 일어난다. save() 없이도 DB가 업데이트된다.
}
  • 우리는 가장 의미있는 테스트(general case)를 제일 먼저 떠올린다.
    • 하지만 그런 테스트는 구현이 복잡하고, 그런 기능을 제일 먼저 구현하면 예외적인 경우들이 누락되는 현상이 발생하기 쉽다.
    • tdd에서는 functional decomposition을 통해서 가장 단순한 테스트(special case)부터 추가해 가면서 최종적으로 general case에 도달하기 위한 stair step tests 목록을 작성하게 됨
  • 절차
    • most simple and degenerate(special)에서 시작
      • null, empty, 0, boundary, simple stuff 등과 같은 special case
  • 다음 단계로 interesting 하지만 조금 덜 degenerate한 테스트 케이스(단일
public class Divider {
public int divide(int dividend, int divisor) {
if (divisor == null) {
throw new IllegalArgumentException("divisor must not be null");
}
if (dividend == null) {
throw new IllegalArgumentException("dividend must not be null");
}
if (divisor == 0) {
throw new IllegalArgumentException("divisor must not be 0");
public class Divider {
public int divide(int dividend, int divisor) {
if (divisor != null) {
if(dividend != null) {
if (divisor != 0) {
return dividend / divisor;
} else {
throw new IllegalArgumentException("divisor must not be 0");
}
} else {
@msbaek
msbaek / Divider2.java
Created February 23, 2025 07:13
Divider2.java
public class Divider {
public int divide(int dividend, int divisor) {
return dividend / divisor;
}
}
import { calc, search } from '@/pages/goodsList/search';
describe('search api', () => {
it('search api를 호출한다.', async () => {
const { data } = await search({ keyword: 'blackpink' });
// console.log(data);
expect(data).toMatchSnapshot();
});
});