-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Seminar1 심화 과제 #4
Open
Yeonnies
wants to merge
3
commits into
main
Choose a base branch
from
seminar1_deep
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package org.sopt.seminar1; | ||
|
||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
|
||
public class Diary { | ||
private Long id; | ||
private final String body; | ||
private boolean isDeleted = false; | ||
private LocalDateTime lastEditedDateTime; | ||
|
||
public Diary(Long id, String body) { | ||
this.id = id; | ||
this.body = body; | ||
this.lastEditedDateTime = LocalDateTime.now(); | ||
} | ||
|
||
public Long getId() { | ||
return id; | ||
} | ||
public String getBody() { | ||
return body; | ||
} | ||
|
||
public boolean isDeleted() { | ||
return isDeleted; | ||
} | ||
public void setDeleted(boolean deleted) { | ||
this.isDeleted = deleted; | ||
} | ||
|
||
public LocalDateTime getLastEditedDateTime() { | ||
return lastEditedDateTime; | ||
} | ||
public void setLastEditedDateTime(LocalDateTime lastEditedDateTime) { | ||
this.lastEditedDateTime = lastEditedDateTime; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package org.sopt.seminar1; | ||
|
||
import java.util.List; | ||
|
||
public class DiaryController { | ||
private Status status = Status.READY; | ||
private final DiaryService diaryService = new DiaryService(); | ||
|
||
Status getStatus() { | ||
return status; | ||
} | ||
|
||
void boot() { | ||
this.status = Status.RUNNING; | ||
} | ||
|
||
void finish() { | ||
this.status = Status.FINISHED; | ||
} | ||
|
||
// APIS | ||
final List<Diary> getList() { | ||
return diaryService.getDiaryList(); | ||
} | ||
|
||
final void post(final String body) { | ||
diaryService.writeDiary(body); | ||
} | ||
|
||
final void delete(final String id) { | ||
long longId = validateAndConvertId(id); | ||
diaryService.deleteDiary(longId); | ||
} | ||
|
||
final void patch(final String id, final String body) { | ||
long longId = validateAndConvertId(id); | ||
diaryService.updateDiary(longId, body); | ||
} | ||
|
||
final void restore(final String id) { | ||
long longId = validateAndConvertId(id); | ||
diaryService.restoreDiary(longId); | ||
} | ||
|
||
enum Status { | ||
READY, | ||
RUNNING, | ||
FINISHED, | ||
ERROR, | ||
} | ||
|
||
private long validateAndConvertId(final String id) { | ||
if (!id.matches("^[1-9][0-9]*$")) { | ||
throw new Main.UI.InvalidInputException(); | ||
} | ||
|
||
try { | ||
return Long.parseLong(id); | ||
} catch (NumberFormatException e) { | ||
throw new IllegalArgumentException("유효한 long 형식의 ID여야 합니다."); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package org.sopt.seminar1; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.atomic.AtomicLong; | ||
|
||
public class DiaryRepository { | ||
private final Map<Long, Diary> storage = new ConcurrentHashMap<>(); | ||
private final AtomicLong numbering = new AtomicLong(); | ||
private int updateCount = 0; | ||
|
||
void save(Diary diary) { | ||
final long id = numbering.addAndGet(1); | ||
diary.setDeleted(false); | ||
diary = new Diary(id, diary.getBody()); | ||
storage.put(id, diary); // Diary 객체를 저장 | ||
} | ||
|
||
List<Diary> findAll() { | ||
final List<Diary> diaryList = new ArrayList<>(); | ||
for (long index = 1; index <= numbering.longValue(); index++) { | ||
final Diary diary = storage.get(index); | ||
if (diary != null && !diary.isDeleted()) { | ||
diaryList.add(diary); | ||
} | ||
} | ||
return diaryList; | ||
} | ||
|
||
void delete(final long id) { | ||
Diary diary = storage.get(id); | ||
if (diary != null) { | ||
diary.setDeleted(true); | ||
} | ||
} | ||
|
||
void update(final long id, final String newBody) { | ||
Diary diary = storage.get(id); | ||
if (diary != null && !diary.isDeleted()) { | ||
LocalDateTime now = LocalDateTime.now(); | ||
LocalDateTime lastEditedDateTime = diary.getLastEditedDateTime(); | ||
|
||
if (!(lastEditedDateTime.toLocalDate().equals(now.toLocalDate()))) { | ||
updateCount = 0; | ||
diary.setLastEditedDateTime(now); | ||
} | ||
|
||
if (updateCount <2){ | ||
updateCount++; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updateCount 에 대한 동시처리 고민도 가지면 좋을것같습니다 |
||
diary.setDeleted(false); | ||
storage.replace(id, new Diary(id, newBody)); | ||
} else { | ||
throw new Main.UI.InvalidInputException(); | ||
} | ||
} | ||
} | ||
|
||
void restore(final long id) { | ||
Diary diary = storage.get(id); | ||
if (diary != null && diary.isDeleted()) { | ||
diary.setDeleted(false); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package org.sopt.seminar1; | ||
|
||
import java.util.List; | ||
|
||
public class DiaryService { | ||
private final DiaryRepository diaryRepository = new DiaryRepository(); | ||
|
||
void writeDiary(String body){ | ||
final Diary diary = new Diary(null, body); | ||
diaryRepository.save(diary); | ||
} | ||
List<Diary> getDiaryList(){ | ||
return diaryRepository.findAll(); | ||
} | ||
void deleteDiary(long id){ | ||
diaryRepository.delete(id); | ||
} | ||
void updateDiary(long id, String body){ | ||
diaryRepository.update(id ,body); | ||
} | ||
void restoreDiary(long id) { // 복구 기능 추가 | ||
diaryRepository.restore(id); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
package org.sopt.seminar1; | ||
|
||
import java.io.*; | ||
|
||
public class Main { | ||
public static void main(String[] args) { | ||
final UI ui; | ||
try { | ||
ui = new DiaryUI(new DiaryController()); | ||
ui.runRepeatedly(); | ||
} catch (Throwable t) { | ||
|
||
} | ||
} | ||
|
||
interface UI { | ||
void runRepeatedly() throws IOException; | ||
|
||
class UIException extends RuntimeException { | ||
} | ||
|
||
class InvalidInputException extends UIException { | ||
} | ||
} | ||
|
||
static class DiaryUI implements UI { | ||
private final DiaryController server; | ||
private String selected; | ||
|
||
public DiaryUI(DiaryController server) throws IOException { | ||
this.server = server; | ||
server.boot(); | ||
ConsoleIO.printLine(getStartMessage()); | ||
} | ||
|
||
public void runRepeatedly() throws IOException { | ||
|
||
do { | ||
if (onMenu()) { | ||
ConsoleIO.printLine(""); | ||
ConsoleIO.printLine(getMenu()); | ||
selected = ConsoleIO.readLine().trim().toUpperCase(); | ||
} | ||
|
||
try { | ||
run(); | ||
} catch (InvalidInputException e) { | ||
ConsoleIO.printLine("잘못된 값을 입력하였습니다."); | ||
} | ||
|
||
if (isFinished()) { | ||
ConsoleIO.printLine(getFinishMessage()); | ||
break; | ||
} | ||
|
||
selected = null; | ||
} while (isRunning()); | ||
} | ||
|
||
//30글자 제한 | ||
private void validateInputLength(final String input) throws InvalidInputException, IOException { | ||
if (input.length() > 30) { | ||
ConsoleIO.printLine("일기는 최대 30글자까지만 입력할 수 있습니다. 다시 입력해주세요."); | ||
throw new InvalidInputException(); | ||
} | ||
} | ||
|
||
private void run() throws IOException { | ||
switch (server.getStatus()) { | ||
case READY, FINISHED, ERROR -> throw new UIException(); | ||
|
||
case RUNNING -> { | ||
switch (selected) { | ||
case "GET" -> { | ||
server.getList().forEach(diary -> { | ||
try { | ||
ConsoleIO.printLine(diary.getId()+" : "+diary.getBody()); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
}); | ||
} | ||
case "POST" -> { | ||
ConsoleIO.printLine("한 줄 일기를 작성해주세요!"); | ||
final String input = ConsoleIO.readLine(); | ||
validateInputLength(input); | ||
server.post(input); | ||
} | ||
|
||
case "DELETE" -> { | ||
ConsoleIO.printLine("삭제할 id 를 입력하세요!"); | ||
final String input = ConsoleIO.readLine(); | ||
server.delete(input); | ||
} | ||
case "PATCH" -> { | ||
ConsoleIO.printLine("수정할 id 를 입력하세요!"); | ||
final String inputId = ConsoleIO.readLine(); | ||
|
||
ConsoleIO.printLine("수정 body 를 입력하세요!"); | ||
final String inputBody = ConsoleIO.readLine(); | ||
validateInputLength(inputBody); | ||
server.patch(inputId, inputBody); | ||
} | ||
case "RESTORE" -> { | ||
ConsoleIO.printLine("복구할 id 를 입력하세요!"); | ||
final String input = ConsoleIO.readLine(); | ||
server.restore(input); // 복구 기능 호출 | ||
} | ||
case "FINISH" -> { | ||
server.finish(); | ||
} | ||
default -> { | ||
throw new InvalidInputException(); | ||
} | ||
} | ||
} | ||
|
||
} | ||
} | ||
|
||
private boolean isRunning() { | ||
return server.getStatus() == DiaryController.Status.RUNNING; | ||
} | ||
|
||
private boolean isFinished() { | ||
return server.getStatus() == DiaryController.Status.FINISHED; | ||
} | ||
|
||
private boolean onMenu() { | ||
return selected == null; | ||
} | ||
|
||
private String getMenu() { | ||
return """ | ||
============================ | ||
- GET : 일기 불러오기 | ||
- POST : 일기 작성하기 | ||
- DELETE : 일기 제거하기 | ||
- PATCH : 일기 수정하기 | ||
- RESTORE : 일기 복구하기 | ||
"""; | ||
|
||
} | ||
|
||
private String getStartMessage() { | ||
return "시작합니다 :)"; | ||
} | ||
|
||
private String getFinishMessage() { | ||
return "종료됩니다 :)"; | ||
} | ||
} | ||
|
||
// not thread safe | ||
private static class ConsoleIO { | ||
private final static BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out)); | ||
private final static BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); | ||
private final static StringBuilder sb = new StringBuilder(); | ||
|
||
public static void printLine(final String toPrint) throws IOException { | ||
if (toPrint == null) { | ||
throw new IllegalArgumentException("console can not print null"); | ||
} | ||
|
||
appendLine(toPrint); | ||
print(); | ||
clearStringBuilder(); | ||
} | ||
|
||
public static String readLine() throws IOException { | ||
return bufferedReader.readLine(); | ||
} | ||
|
||
private static void appendLine(final String toPrint) { | ||
sb.append(toPrint); | ||
sb.append("\n"); | ||
} | ||
|
||
private static void print() throws IOException { | ||
bufferedWriter.write(sb.toString()); | ||
bufferedWriter.flush(); | ||
} | ||
|
||
private static void clearStringBuilder() { | ||
sb.setLength(0); | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 로직은 Repository 영역이라고 볼 수 있을까요?
Repository 의 역할은 단순히 데이터를 읽고 조회하는 역할이라고 생각이 들어요.