혼자서 풀스택으로 제작한 축구 퀴즈앱.. 다시한번 앱을 오픈하고 싶지만 현재 서버비가 부담되어 플레이스토어에서 내렸다..(눈물)
그중 OCP 원칙을 지키지 않아 개선한 부분을 말해보겠다..
OCP원칙을 지켜야겠다는 생각을 가진 원인
앱 배포가 거절되어서 기능을 추가해야했는데 기존 코드를 건드리는 경험을 했기때문이다. (OCP 위반)
친절한 구글 ..내 앱 테스트하면서 댓글도 작성해줬다..
영어로 유저 report 기능 게시글 report 기능 abusive users 에 대한 block remove 기능을 넣으라고한다..
드디어 배포하는 줄 알았는데 그때 당시 살짝 당황했다.
구글 정책을 확인하지 않았던 내가 미웠지만
코드개선할 기회가 생겼고
배포까진 무조건해야하는 목표를 생각해서
오히려 좋아 마인드로 수정해서 끝까지 하려고 했다.
하지만 기존코드가 내가봐도 엉망이었고 새로운 기능을 추가하려니까 기존의 코드를 수정해야했다..
기존코드 (게시글 수정)
@Operation(summary = "게시물 수정하기")
@PostMapping("/front-user/user-post/edit-post")
public String userEditPost(UserPostDto userPostDto, Long postId, RedirectAttributes redirectAttributes,Model model) {
String title = userPostDto.getTitle();
String content = userPostDto.getContent();
Optional<UserPost> userPostByPostId = userPostService.getUserPostByPostId(postId);
redirectAttributes.addAttribute("nickName", userPostDto.getNickName());
if (titleWrongChk(title)|| contentWrongChk(content))
{
Map<String, String> errors = new HashMap<>();
if (titleWrongChk(title))
errors.put("titleLength", "제목은 2~25자 로 작성해 주세요.");
if (contentWrongChk(content))
errors.put("contentLength", "내용은 2~500자 로 작성해 주세요.");
model.addAttribute("errors", errors);
model.addAttribute("beforeContent", content);
model.addAttribute("beforeTitle", title);
model.addAttribute("postId", postId);
redirectAttributes.addAttribute("postId", postId);
return "editPost";
}
userPostByPostId.get().setTitle(userPostDto.getTitle());
userPostByPostId.get().setContent(userPostDto.getContent());
userPostService.save(userPostByPostId.get());
return "redirect:/user-boards";
}
부끄럽다.. 매우 난장판인 모습
문제점1
여기서 공통으로 사용할 부분이 입력값에 대한 validate하는 부분이라고생각해서 따로 분리시켰다.
validate
@Component
public class PostValidator {
public Map<String, String> validateEditPost(UserPostDto userPostDto) {
Map<String, String> errors = new HashMap<>();
if (isTitleInvalid(userPostDto.getTitle())) {
errors.put("titleLength", "제목은 2~25자 로 작성해 주세요.");
}
if (isContentInvalid(userPostDto.getContent())) {
errors.put("contentLength", "내용은 2~500자 로 작성해 주세요.");
}
return errors;
}
private boolean isTitleInvalid(String title) {
return title.length() < 2 || title.length() > 25;
}
private boolean isContentInvalid(String content) {
return content.length() < 2 || content.length() > 500;
}
}
이런식으로 분리시켰다..
문제점2
캡슐화 안함
userPostByPostId.get().setTitle(userPostDto.getTitle());
userPostByPostId.get().setContent(userPostDto.getContent());
캡슐화 위반해버린 코드... set으로 넣어버리다니..
public void updatePost(String title, String content) {
this.title = title;
this.content = content;
}
따로 메소드를 만들어서 넣도록 했다.
수정된코드
@Operation(summary = "게시물 수정하기")
@PostMapping("/front-user/user-post/edit-post")
public String userEditPost(UserPostDto userPostDto, Long postId, RedirectAttributes redirectAttributes, Model model) {
Map<String, String> errors = postValidator.validateEditPost(userPostDto);
if (!errors.isEmpty()) {
model.addAttribute("errors", errors);
model.addAttribute("beforeContent", userPostDto.getContent());
model.addAttribute("beforeTitle", userPostDto.getTitle());
model.addAttribute("postId", postId);
redirectAttributes.addAttribute("postId", postId);
return "editPost";
}
Optional<UserPost> userPostByPostId = userPostService.getUserPostByPostId(postId);
if (userPostByPostId.isPresent()) {
UserPost userPost = userPostByPostId.get();
userPost.updatePost(userPostDto.getTitle(), userPostDto.getContent());
userPostService.save(userPost);
}
return "redirect:/user-boards";
}
결론
유지 보수를 위해선 SOLID 원칙이 중요하다는걸 깨닫고 처음에 고생하면서 코드를 짜야 나중에 고생하지 않는다는걸 깨달았다.
'스프링부트' 카테고리의 다른 글
[스프링 부트] keycloak 사용 SSO(OIDC) 인증 서버 간단하게 구축해보기 (1) | 2024.11.25 |
---|---|
스프링 부트 Redis 분산 락 활용 동시성 제어 (1) | 2024.07.04 |
이미지 업로드 비동기 처리 (0) | 2024.06.19 |
[스프링] 프로젝트 N+1 해결하기 (fetch join (0) | 2023.09.01 |
[스프링부트] 개인 프로젝트 버그 고치기 (0) | 2023.08.27 |