Skip to content

constant94-dev/java-product-order

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

44 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

μƒν’ˆμ£Όλ¬Έ ν”„λ‘œκ·Έλž¨ 핡심: μ‚¬μš©μžκ°€ μ›ν•˜λŠ” μƒν’ˆμ„ λ¬Έμ œμ—†μ΄ μ£Όλ¬Έν•  수 μžˆμ–΄μ•Ό ν•œλ‹€.

πŸ”§ ν”„λ‘œμ νŠΈ ν™˜κ²½

  • Java version: jdk-11.0.18
  • Gradle version: 8.0
  • lombok version: 1.18.28

πŸ›’ μƒν’ˆμ£Όλ¬Έ ν”„λ‘œκ·Έλž¨ κΈ°λŠ₯ λͺ©λ‘

  • μƒν’ˆμ£Όλ¬Έ ν”„λ‘œκ·Έλž¨ κΈ°λŠ₯ μΆœλ°œμ§€ - ProductController#run()
    • ν”„λ‘œκ·Έλž¨ 객체 μ€€λΉ„ - ProductController#ready()
    • ν”„λ‘œκ·Έλž¨ κΈ°λŠ₯ μ‹œμž‘ - ProductController#orderPlay()
  • μƒν’ˆ μ €μž₯μ†Œ
    • μƒν’ˆ 데이터 κ°€μ Έμ˜€κΈ° - ProductRepository#getCSVData()
    • 콀마(,) κΈ°μ€€ λΆ„ν•  - ProductRepository#splitToComma()
    • μƒν’ˆ 데이터 검증 - ProductRepository#validateTokens()
    • μƒν’ˆ 데이터 제λͺ© 검증 - ProductRepository#validateTitle()
    • μƒν’ˆ 데이터 μΆ”κ°€ - ProductRepository#addProductMap()
    • μƒν’ˆ 데이터 파일 읽기 μ’…λ£Œ - ProductRepository#fileReaderClose()
  • μƒν’ˆ μ£Όλ¬Έ
    • μ£Όλ¬Έ λ˜λŠ” μ’…λ£Œ μž…λ ₯ - InputView#orderORQuit()
    • μƒν’ˆλ²ˆν˜Έ μž…λ ₯ - InputView#orderOfNumber()
    • μˆ˜λŸ‰ μž…λ ₯ - InputView#orderOfVolume()
  • μ£Όλ¬Έ 처리
    • μƒν’ˆ μ£Όλ¬Έ 번호 검증 - OrderService#validateOrderNumber()
      • μƒν’ˆ 메뉴 λ²ˆν˜Έλ“€ 확인 - OrderService#hasMenuNumbers()
      • μƒν’ˆ μ£Όλ¬Έ 번호 비ꡐ - OrderService#isOrderNumber()
    • μƒν’ˆμˆ˜λŸ‰ 검증 - OrderService#validateOrderVolume()
      • μƒν’ˆ μˆ˜λŸ‰κ³Ό 재고 수 확인 - Menu#volumeInStock()
  • μ£Όλ¬Έ λ‚΄μ—­
    • 총 μƒν’ˆ 정보 좜λ ₯ - OutputView#printToTotalProduct()
    • μƒν’ˆ μ£Όλ¬Έ λ‚΄μ—­ 좜λ ₯ - OutputView#printToOrderResult()

♻️ μƒν’ˆμ£Όλ¬Έ ν”„λ‘œκ·Έλž¨ ν…ŒμŠ€νŠΈ λͺ©λ‘

  • μƒν’ˆ 데이터 처리
    • csv νŒŒμΌμ—μ„œ κ°€μ Έμ˜¨ μƒν’ˆ 데이터 κ°€μ Έμ˜€κ°€ 성곡 - ProductRepositoryTest#getCSVDataSuccess()
  • μƒν’ˆ μ£Όλ¬Έ 처리
    • μ£Όλ¬Έ μƒν’ˆ 번호 μ‘΄μž¬ν•˜λŠ” 경우 성곡 - OrderServiceTest#orderNumberToExist()
    • μ£Όλ¬Έ μƒν’ˆ 번호 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 경우 μ˜ˆμ™Έ λ°œμƒ - OrderServiceTest#orderNumberToNotExist()
    • μ£Όλ¬Έ μƒν’ˆ 재고 λΆ€μ‘± μ—¬λΆ€ 확인 - OrderServiceTest#orderVolumeInStock()
    • μ£Όλ¬Έ μƒν’ˆ 재고 λΆ€μ‘± μ˜ˆμ™Έ λ°œμƒ - OrderServiceTest#orderVolumeNotInStock()

πŸ“‚ Project Structure

πŸ“¦src
 ┣ πŸ“‚main
 ┃ β”— πŸ“‚java
 ┃ ┃ β”— πŸ“‚kr
 ┃ ┃ ┃ β”— πŸ“‚co
 ┃ ┃ ┃ ┃ β”— πŸ“‚_29cm
 ┃ ┃ ┃ ┃ ┃ β”— πŸ“‚homework
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚constant
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚exception
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œmessageException.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚service
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“œOrderConstant.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œResultNameConstant.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“‚view
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“œInputViewConstant.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œOutputViewConstant.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚exception
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œhandlerException.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚model
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“œMenu.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“œOrder.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œProduct.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚repository
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œProductRepository.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚service
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œOrderService.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚validate
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“œInputViewValidator.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œOutputViewValidator.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚view
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“œConsole.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“œInputView.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œOutputView.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“œMain.java
 ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œProductController.java
 β”— πŸ“‚test
 ┃ β”— πŸ“‚java
 ┃ ┃ β”— πŸ“‚kr
 ┃ ┃ ┃ β”— πŸ“‚co
 ┃ ┃ ┃ ┃ β”— πŸ“‚_29cm
 ┃ ┃ ┃ ┃ ┃ β”— πŸ“‚homework
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚model
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“œMenuTest.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œOrderTest.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚repository
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œProductRepositoryTest.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚service
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œOrderServiceTest.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚validate
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“œInputViewValidatorTest.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œOutputViewValidatorTest.java
 ┃ ┃ ┃ ┃ ┃ ┃ ┣ πŸ“‚view
 ┃ ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œOutputViewTest.java
 ┃ ┃ ┃ ┃ ┃ ┃ β”— πŸ“œMultiThreadRequestTest.java

πŸ“Œ Stack

πŸ’» μ‹€ν–‰ ν™”λ©΄

초기 μƒν’ˆ 메뉴

feature

2개 μƒν’ˆ μ£Όλ¬Έ

feature

μƒν’ˆ 결제 ν›„ 메뉴

feature

1개 μƒν’ˆ μ£Όλ¬Έ

feature

μƒν’ˆ 결제 ν›„ 메뉴

feature

μƒν’ˆ 재고 λΆ€μ‘±

feature

μƒν’ˆ μ£Όλ¬Έ μ’…λ£Œ

feature

πŸ”Ž Test

ν…ŒμŠ€νŠΈ μ‹€ν–‰

feature

feature

초기 μ‚¬μš©μž 및 λ©€ν‹° μ“°λ ˆλ“œ μ„ΈνŒ…

feature

ν˜„μž¬ μ‹€ν–‰λ˜κ³  μžˆλŠ” μ“°λ ˆλ“œ

feature

μ‚¬μš©μž A μƒν’ˆ μ£Όλ¬Έ

feature

μ‚¬μš©μž B μƒν’ˆ μ£Όλ¬Έ

feature

μ“°λ ˆλ“œ μž‘μ—… μ™„λ£Œ

feature

μ‚¬μš©μž A 와 μ‚¬μš©μž B λ©€ν‹° μ“°λ ˆλ“œ μš”μ²­ 처리 ν…ŒμŠ€νŠΈ 성곡화면

feature

πŸ“‰ ν…ŒμŠ€νŠΈ μ“°λ ˆλ“œ WorkFlow

feature

✍ μ“°λ ˆλ“œ 처리의 Point

WorkFlow μ—μ„œ λ³΄μ—¬μ§€λŠ” 흐름과 같이 μ‚¬μš©μžκ°€ 주문에 λŒ€ν•œ 결제λ₯Ό μ§„ν–‰ν•  λ•Œ λ‹€λ₯Έ μ“°λ ˆλ“œμ—μ„œλŠ” μ£Όλ¬Έ 결제λ₯Ό 기닀리고 μžˆμ–΄μ•Όν•œλ‹€. κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄ μƒν’ˆλ²ˆν˜Έ:213341 의 μž¬κ³ κ°€ 뢀쑱함에도 μ£Όλ¬Έ κ²°μ œκ°€ μ§„ν–‰λ˜μ–΄ μ‚¬μš©μžλŠ” μ—†λŠ” μƒν’ˆμ„ 주문을 ν•˜κ²Œλœλ‹€.

μ—¬κΈ°μ„œ κ³ λ―Όν•΄μ•Όλ˜λŠ” Point κ°€ DB Transaction Level κ³Ό method Level 2가지이닀. 해결방법은 κ²°μ œκ°€ λ°œμƒν•  λ•Œ Lock 을 κ±Έμ–΄μ£ΌλŠ” 것이닀.

이 ν”„λ‘œμ νŠΈμ—μ„œλŠ” λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— method Level μ—μ„œ Lock 을 κ±Έμ–΄μ£Όμ—ˆλ‹€.

feature

μ“°λ ˆλ“œκ°€ getOrderComplete() μž‘μ—…μ„ μˆ˜ν–‰ν•  λ•Œ λ‹€λ₯Έ μ“°λ ˆλ“œκ°€ μ ‘κ·Ό ν•˜μ§€ λͺ»ν•˜κ²Œ ν•˜κ³  μž‘μ—…μ΄ 마무리 된 후에 λ‹€λ₯Έ μ“°λ ˆλ“œκ°€ μ ‘κ·Όν•  수 μžˆλ‹€.

⏱ μ‹œκ°„ λ³΅μž‘λ„

μ‹œκ°„ λ³΅μž‘λ„λŠ” ν•¨μˆ˜μ˜ μ‹€ν–‰ μ‹œκ°„μ„ ν‘œν˜„ν•˜λŠ” 것
주둜 점근적 뢄석을 톡해 μ‹€ν–‰ μ‹œκ°„μ„ λ‹¨μˆœν•˜κ²Œ ν‘œν˜„ν•˜λ©°
이 λ•Œ 점근적 ν‘œκΈ°λ²•μœΌλ‘œ ν‘œν˜„ν•¨

feature

main μ—μ„œ μ‹€ν–‰λ˜λŠ” method κ°€ 2개 μžˆλ‹€.
main 의 μ„ μ–Έλœ method 2개λ₯Ό μ‹€ν–‰ν•˜λ©΄ λλ‚˜κΈ° λ•Œλ¬Έμ— λΉ…μ˜€ ν‘œκΈ°λ²•μœΌλ‘œ ν‘œν˜„ν•˜λ©΄ O(1) μƒμˆ˜μ‹œκ°„μ˜ μ‹œκ°„λ³΅μž‘λ„λ₯Ό κ°€μ§„λ‹€. ν•˜μ§€λ§Œ, μ‹€ν–‰λ˜λŠ” method 의 λ‚΄λΆ€ λ‘œμ§μ„ 확인해 보아야 ν•œλ‹€.

productRepository.getData() λ‘œμ§μ„ 확인해보면

while((line=file.readLine())!=null){
        /* Service Logic */
        }

while 반볡문 1κ°œκ°€ λŒκ³ μžˆλ‹€. 이 λ°˜λ³΅λ¬Έμ€ CSV 파일의 μ‘΄μž¬ν•˜λŠ” ν–‰μ˜ 개수만큼 λ°˜λ³΅ν•˜κ³  μ’…λ£Œν•œλ‹€. ν˜„μž¬λŠ” 20개 행이 μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ— 20번 λ°˜λ³΅ν•˜κ³  μ’…λ£Œλ  것이닀. ν•˜μ§€λ§Œ, μƒν’ˆ μˆ˜λŠ” 증가 ν•  수 μžˆλŠ” 성격을 κ°€μ§€κΈ° λ•Œλ¬Έμ— μ°ΎμœΌλ €λŠ” μƒν’ˆ 수 만큼 νƒμƒ‰ν•œλ‹€κ³  ν•  수 μžˆμ–΄ O(N) μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ§„λ‹€.

이제 productSale.run() λ‘œμ§μ„ ν™•μΈν•΄λ³΄μž

while(true){ // μ’…λ£Œ μž…λ ₯ μ „κΉŒμ§€ 'μ£Όλ¬Έ'을 반볡적으둜 μž…λ ₯ λ°›λŠ” 반볡문
        /* Service Logic */
        while(true){ // 'μƒν’ˆλ²ˆν˜Έ', 'μˆ˜λŸ‰'을 반볡적으둜 μž…λ ₯ λ°›λŠ” 반볡문
        /* Service Logic */
        }
        }

while 반볡문 2κ°œκ°€ λŒκ³ μžˆλ‹€.
첫 번째 반볡문의 역할은 μ‚¬μš©μžκ°€ 'μ£Όλ¬Έ' or 'μ’…λ£Œ' λ₯Ό μ„ νƒν•˜λŠ” λ°˜λ³΅λ¬Έμ΄λ‹€.
두 번째 반볡문의 역할은 μ‚¬μš©μžκ°€ 'μ£Όλ¬Έ' μ„ νƒμ‹œ μ£Όλ¬Έν•  'μƒν’ˆλ²ˆν˜Έ' and 'μˆ˜λŸ‰' 을 반볡적으둜 μž…λ ₯λ°›λŠ” λ°˜λ³΅λ¬Έμ΄λ‹€.

μ‚¬μš©μžμ˜ μž…λ ₯이 1번으둜 끝날 μˆ˜λ„ 있고 100번으둜 끝날 μˆ˜λ„ μžˆμ–΄ 예츑이 λΆˆκ°€ν•˜μ§€λ§Œ κ²°κ΅­μ—λŠ” μ‚¬μš©μžκ°€ μž…λ ₯ν•˜λŠ” 횟수만큼 λ°˜λ³΅ν•  것이닀.

μ—¬κΈ°μ„œ 반볡문 λ‚΄λΆ€μ˜ μ‘΄μž¬ν•˜λŠ” method 듀도 ν™•μΈν•΄λ³΄μž

첫 번째 λ°˜λ³΅λ¬Έμ—μ„œ λ™μž‘ν•˜λŠ” method κ°€ 2개 μ‘΄μž¬ν•œλ‹€.

  • productRepository.getCurrentProductInfo()
  • productRepository.getOrderComplete(productNumbers, productStocks)
// getCurrentProductInfo()
productMap.forEach((k,v)->
        /* Service Logic */
        )

// getOrderComplete(productNumbers, productStocks)
        for(int i=0;i<productNumbers.size();i++){
        /* Service Logic */
        }

getCurrentProductInfo() λŠ” μ €μž₯된 μƒν’ˆ 정보λ₯Ό ν•˜λ‚˜μ”© 좜λ ₯ν•˜κ³  μžˆλ‹€.
ν˜„μž¬λŠ” 19개의 μƒν’ˆμ •λ³΄λ₯Ό κ°€μ§€κ³  μžˆμ–΄ O(19) μƒμˆ˜ μ‹œκ°„λ§Œ λ°˜λ³΅ν•˜μ§€λ§Œ 이 κ²½μš°λ„ μƒν’ˆ 데이터가 증가할 수 μžˆλŠ” 성격을 띄기 λ•Œλ¬Έμ— μ‘΄μž¬ν•˜λŠ” μƒν’ˆ 수 만큼 νƒμƒ‰ν•œλ‹€κ³  ν•  수 μžˆμ–΄ O(N) μ‹œκ°„λ³΅μž‘λ„λ₯Ό κ°€μ§„λ‹€.

getOrderComplete(productNumbers, productStocks) λŠ” μ‚¬μš©μžκ°€ μ£Όλ¬Έν•œ 만큼 반볡이 μ§„ν–‰λœλ‹€.
μ‚¬μš©μž 주문이 1번일 수 도 있고 100번 일 μˆ˜λ„ 있기 λ•Œλ¬Έμ— κ²°κ΅­ μ‚¬μš©μž 주문만큼 λ°˜λ³΅ν•˜κ²Œλ˜ O(N) μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ§„λ‹€.

두 번째 λ°˜λ³΅λ¬Έμ—μ„œ λ™μž‘ν•˜λŠ” method 도 2개 μ‘΄μž¬ν•œλ‹€.

  • productRepository.getStockCheck(orderNumber, orderStock)
  • productRepository.getProductCheck(orderNumber)
// getStockCheck(orderNumber, orderStock)
if(product!=null){
        /* Service Logic */
        if(currentStock<orderStock){
        /* Service Logic */
        }
        }

// getProductCheck(orderNumber)
        if(productExist!=null){
        /* Service Logic */
        }

getStockCheck(orderNumber, orderStock) λŠ” ν˜„μž¬ μ‘΄μž¬ν•˜λŠ” 재고 μˆ˜μ™€ μ£Όλ¬Έν•œ 재고 수λ₯Ό ν™•μΈν•˜λŠ” κΈ°λŠ₯이닀. 이쀑 쑰건문을 μ‚¬μš©ν•˜μ§€λ§Œ 쑰건문은 O(1) μƒμˆ˜ μ‹œκ°„μ˜ μ‹œκ°„λ³΅μž‘λ„λ₯Ό κ°€μ§„λ‹€.

getProductCheck(orderNumber) λŠ” μ‚¬μš©μžκ°€ μ£Όλ¬Έν•œ μƒν’ˆμ΄ μ‘΄μž¬ν•˜λŠ” μƒν’ˆμΈμ§€ ν™•μΈν•˜λŠ” κΈ°λŠ₯이닀. 쑰건문 ν•˜λ‚˜λ₯Ό μ‚¬μš©ν•˜κ³  μžˆμ–΄ O(1) μƒμˆ˜ μ‹œκ°„μ˜ μ‹œκ°„λ³΅μž‘λ„λ₯Ό κ°€μ§„λ‹€.

결둠적으둜, μ΅œκ³ μ°¨ν•­λ§Œμ„ λ‚¨κΈ°λŠ” 점근적 ν‘œκΈ°λ²•μΈ λΉ…μ˜€(Big-O) ν‘œκΈ°λ²•μœΌλ‘œ ν‘œν˜„ν•œλ‹€λ©΄
두 번째 λ°˜λ³΅λ¬Έμ—μ„œ λ™μž‘ν•˜λŠ” ν•¨μˆ˜λŠ” μ‹€ν–‰μ‹œκ°„μ—μ„œ μ œμ™Έν•  수 있고,
첫 번째 λ°˜λ³΅λ¬Έμ—μ„œλŠ” 반볡문이 1개 μ€‘μ²©λ˜μ–΄ μ‚¬μš©λ˜λŠ”κ±Έ 확인할 수 있기 λ•Œλ¬Έμ— 이 ν”„λ‘œκ·Έλž¨μ€ O(N^2) μ‹œκ°„λ³΅μž‘λ„λ₯Ό κ°€μ§„λ‹€κ³  ν•  수 μžˆλ‹€.

About

Product order program implemented in Java and Junit5

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages