Skip to content
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

[feat] 1주차 과제 제출 #2

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

[feat] 1주차 과제 제출 #2

wants to merge 1 commit into from

Conversation

choyeongju
Copy link
Member

@choyeongju choyeongju commented Apr 9, 2024

Related Issue 📌

Description ✔️

  • 1주차 과제입니다

Main

  • switch 문을 통해서 메뉴를 구분할 수 있도록 했습니다.
  • ArrayList 로 프로그램 실행 중에 생성되는 계좌들을 배열로 저장하여 관리할 수 있게 하였습니다.
public class Main {
    private static final ArrayList<Account> accounts = new ArrayList<>();

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("은행 프로그램 입니다.");
        System.out.println("원하는 메뉴의 번호를 선택해 주세요.");

        showMenu(); //메뉴 출력

        while(true){
            String menu=sc.nextLine();
            switch (menu){
                case "1" :
                    createAccountService();
                    break;
                case "2" :
                    showAccountService();
                    break;
                case "3" :
                    depositService();
                    break;
                case "4" :
                    withDrawService();
                    break;
                case "5":
                    transferService();
                    break;
                case "6" :
                    System.out.println("은행 프로그램을 종료합니다.");
                    return;
                default:
                    System.out.println("메뉴를 다시 선택해 주세요.");
            }
            showMenu();
        }
    }

계좌 생성 메서드

  public static void createAccountService(){
        System.out.println("계좌 생성 서비스 입니다.");
        System.out.print("생성할 새로운 계좌번호 입력 : ");

        Scanner sc = new Scanner(System.in);
        String account_num = sc.nextLine();

        System.out.print("예금주명 입력 : ");
        String customer_name = sc.nextLine();

        System.out.print("초기 금액 입력 : ");
        int init_money = sc.nextInt();

        Account ac = new Account(account_num, customer_name, init_money);
        accounts.add(ac);
        System.out.println("계좌 개설 완료!");
        System.out.println();
    }

계좌 목록 보여주는 메서드

 public static void showAccountService(){
        if(accounts.isEmpty()) System.out.println("계좌 목록이 비어 있습니다. 계좌를 개설해 주세요.");
        else{
            System.out.println("---------<계좌 목록 출력>---------");
            for(int i=0; i<accounts.size();i++){
                Account ac = accounts.get(i);
                System.out.println("계좌 번호 : " + ac.getAccount());
                System.out.println("예금주 : " + ac.getCustomer_name());
                System.out.println("잔액 : " + ac.getMoney());
                System.out.println();
            }
            System.out.println("-------------------------------");
        }
    }

입금 메서드

 public static void depositService(){
        System.out.println("입금 서비스 입니다.");
        System.out.print("입금할 계좌번호 입력 : ");

        Scanner sc = new Scanner(System.in);
        String account_num = sc.nextLine();

        System.out.print("입금할 금액 입력 : ");
        int money = sc.nextInt();
        System.out.println();

        Account ac=findAccount(account_num);
        if(account_num == null) System.out.println("없는 계좌입니다.");
        else{
            ac.deposit(money);
        }
    }

출금 메서드

 public static void withDrawService() {
        System.out.println("출금 서비스 입니다.");
        System.out.print("출금할 계좌번호 입력 : ");

        Scanner sc = new Scanner(System.in);
        String account_num = sc.nextLine();

        System.out.print("출금할 금액 입력 : ");
        int money = sc.nextInt();

        Account ac=findAccount(account_num);
        if(account_num == null) System.out.println("없는 계좌입니다.");
        else{
            ac.withDraw(money);
        }
    }

계좌이체 메서드

  • 계좌번호가 존재하지 않을 시 메세지 띄우도록 했음
 public static void transferService(){
        Scanner sc= new Scanner(System.in);
        System.out.println("계좌이체 서비스 입니다.");

        System.out.print("당신의 계좌를 입력하세요(보내는 사람) : ");
        String account_send = sc.nextLine();

        System.out.print("계좌이체할 상대방의 계좌번호를 입력하세요(받는 사람) : ");
        String account_receive = sc.nextLine();

        System.out.print("이체할 금액 입력 : ");
        int money=sc.nextInt();
        System.out.println();

        Account ac_send = findAccount(account_send);
        Account ac_receive = findAccount(account_receive);
        if(ac_send == null ) System.out.println("보내는 사람이 없는 계좌입니다. 계좌를 개설해 주세요.");
        else if(ac_receive == null) System.out.println("받는 사람이 없는 계좌입니다. 계좌를 개설해 주세요.");
        else{
            ac_send.transfer(ac_receive, ac_send, money);
        }
    }

계좌 목록 확인 메서드

  • 계좌번호에 해당하는 계좌를 찾고, 찾을 시 리턴한다.
  private static Account findAccount(String account_num){
        for(int i = 0; i < accounts.size(); i++){
            Account ac = accounts.get(i);
            if(ac.getAccount().equals(account_num)){
                return ac;
            }
        }
        return null;
    }

Account 클래스

필드와 생성자

public class Account {
    private String account;
    private String customer_name;
    private int money;

    public Account(String account, String customer_name, int money){
        this.account=account;
        this.customer_name=customer_name;
        this.money = money;
    }

입금, 출금, 계좌이체

   public void deposit(int money){ //입금
        this.money+=money;
        System.out.println(this.customer_name + "님에게 " + money + "원 입금 완료.");
        System.out.println(this.customer_name + "님의 현재 잔액은 " + this.money + "원 입니다.");
    }

    public void withDraw(int money){ //출금
        if(this.money<money) System.out.println("잔액이 부족합니다.");
        else {
            this.money -= money;
            System.out.println();
            System.out.println(money + "원 출금 완료.");
            System.out.println(this.customer_name + "님의 현재 잔액은 " + this.money + "원 입니다.");
        }
    }

    public void transfer(Account otherAccount, Account myAccount, int money){ //계좌 이체
        if(this.money<money) System.out.println("잔액이 부족합니다.");
        else{
            this.money-=money;
            System.out.println(otherAccount.getCustomer_name() + "님에게 " + money + "원을 이체 하였습니다.");
            otherAccount.deposit(money);
        }
    }

To Reviewers

  • Customer 클래스도 처음엔 따로 만들었으나 Customer 클래스를 통해 어떤 내용으로 관리할 지 모르겠어서 코드를 짜다 보니 Account 객체만 쓰게 되었습니다. 묘듈화하여 프로그램의 구조를 짜는 법이 아직 익숙치 않은 것 같습니다.
  • 코드가 다소 지저분하다고 느껴져서 다음엔 이를 고려해서 설계하도록 노력하겠습니다..!

Copy link
Member

@mini-min mini-min left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM👍🏻 첫 과제 고생하셨습니다!!

저도 잘하지 못하다보니 영주님처럼 처음에 어떤 부분을 어떻게 나눠야할까 고민을 많이했던 것 같아요. 저도 과제를 할 때, 프로그램의 구조를 나누면서 생각한 것들을 같이 공유해볼게요!

일단 main은 무거우면 안된다는 생각입니다.
-> 결국 말이 어려워서 그렇지 OOP는 클래스든, 모듈이든 객체로 분리해서 만들어두고 이것들을 호출하면서 사용하라는 뜻이거든요!
main 한 곳에만 코드를 몰게 되면, 가독성 측면도 있겠지만, 2차 세미나 마지막에 다뤘던 테스트 코드 적용이나 무엇보다 코드의 유연성 측면(기존 코드를 수정하고, 새로운 기능을 추가하고)에서 불편함이 많아질거에요.

지금은 입출금과 송금 기능만 구현해서 과제를 제출하셨지만, (설상 나중에 이 프로그램을 더 건들지 않는다고 하더라도) "추후에 다른 기능이 추가될 수 있다는 가능성"을 혹은 "기존 기능의 변경사항이 발생할 수 있는 가능성"을 생각하신다면 더 좋을 것 같습니다 ^__^

뭐 예를 들어 나중에는 송금하기 위해서 계좌 비밀번호를 입력하는 기능을 추가한다고 했을 때,
지금처럼 Account의 필드를 만들고, 함수를 추가하고, 생성자도 변경하고, 그러면 Main에 어느 부분을 수정해야했지...같은 문제가 생길 수 있다는 점을 고려하시면
"아 내가 이 부분을 나누면 수정할 때 조금 용이하겠네!"라는 생각이 들 것이라 생각합니다!

  • 추상 클래스나 인터페이스를 만들어서 활용해보시는 연습을 권장드립니닷!

Copy link
Contributor

@sohyundoh sohyundoh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

과제하느라 고생하셨습니다!

앞으로 과제하실 때 패키지 구조와 접근제어자를 잘 이용해보는게 어떨까요? 객체지향의 핵심은 책임을 분리하는 것입니다!

영주님의 과제에는 Account와 Main으로 두 개의 클래스로 모든 걸 담당하고 있으니 이걸 분리하는 방안을 고민해보시면 좋을 것 같아요!

예를 들어 입출력 모듈을 다른 클래스로 분리한다던지, 고객 클래스를 따로 정의하는 방법도 좋을 것 같습니다!

앞으로 계속해서 발전할 과제 기대할게요🍀

Copy link
Member

@hoonyworld hoonyworld left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1주차 과제 수고하셨습니다!

계좌개설 부터 프로그램 종료까지 6개의 기능을 구현하셨다는 점이 대단하신 것 같습니다!

저도 소현님과 민재님과 동일한 의견입니다.
main 클래스의 책임이 많다고 느껴집니다. 이는 프로그램의 유연성 뿐만 아니라 가독성이 떨어지게 됩니다. 그래서 추후에 리팩터링 하실 때 MVC 패턴을 적용해 볼 것을 권유드립니다!

MVC 패턴은 설계시 기능과 모듈 단위로 계층을 나누는 방법으로 객체 지향 프로그래밍에서 깔끔하고 효율적인 코드 구조를 만들기 위해 사용됩니다. 아마 MVC를 공부하시고 리팩터링을 하시게 되면 아! 이 부분에서 컴포넌트를 하나 추가해서 책임을 분산시켜야 겠다! 라는 생각이 드실 겁니다.

또한 저도 잘 적용시키지 못했지만, 인터페이스와 추상클래스를 이용해서 SOLID 원칙을 지키도록 구현해 보시면 좋겠습니다.

저도 리팩터링 과정에서 적용하려고 생각중인데, 예를 들어 입금과 출금기능을 담당하는 인터페이스를 구현하고 두 인터페이스를 Account 클래스에서 구현하는 방법이 있을 것 같습니다!

Comment on lines +99 to +104
Account ac=findAccount(account_num);
if(account_num == null) System.out.println("없는 계좌입니다.");
else{
ac.deposit(money);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

account_null은 위에서 sc.nextInt()로 받은 결과물인 것으로 보이는데, 여기서는 account_num == null를 검사하는 것이 아닌, 함수 호출로 부터 받은 ac객체를 검사(ac == null)해야 할 것 같다고 생각됩니다!

영주님은 어떻게 생각하시나요?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추가로 아래와 같이 try-catch로 예외처리를 해주시면 account_num이 숫자가 아닌 입력일 경우 예외처리를 할 수 있을 것 같습니다!

public static void depositService() {
    System.out.println("입금 서비스 입니다.");
    System.out.print("입금할 계좌번호 입력 : ");
    String account_num = scanner.nextLine();
    
    try {
        System.out.print("입금할 금액 입력 : ");
        int money = sc.nextInt();
        sc.nextLine(); 

        Account ac = findAccount(account_num);
        if(ac == null) {
            System.out.println("없는 계좌입니다.");
        } else {
            ac.deposit(money);
        }
    } catch (InputMismatchException e) {
        System.out.println("유효하지 않은 금액입니다. 숫자를 입력해주세요.");
        sc.nextLine(); 
    }
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setter는 사용되지 않으므로 삭제해도 좋을 것 같다고 생각합니다.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

잔액과 입출금 시의 금액을 모두 money로 관리하고 계신 것 같습니다.
저도 처음에는 영주님과 동일하게 둘다 money로 변수를 구현하다가, 잔액의 money인지 입출금의 money인지 헷갈리는 경험을 했습니다. 😂
그래서 잔액은 balance, 입출금은 기존 money로 관리하니 명확히 구분할 수 있어 구현할 때 편리했었습니다.

리팩터링 할때 이 방법도 생각해보시면 좋을 것 같습니다!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scanner 객체를 함수 호출시마다 생성하고 계신 것으로 보입니다.

Main함수 위에 private static final Scanner scanner = new Scanner(System.in);로 전역적으로 선언하면 호출시마다 생성할 필요 없이 바로 sc.메서드로 입력을 받을 수 있습니다!

Comment on lines +116 to +121
Account ac=findAccount(account_num);
if(account_num == null) System.out.println("없는 계좌입니다.");
else{
ac.withDraw(money);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

account_null 관련해서 위와 동일한 의견입니다!

@softmoca
Copy link
Member

과제 하시느라 너무 고생 많으셨어요 !
저도 자바가 처음이다 보니 영주님과 클래스를 사용해서 코드를 관리하는게 많이 어색하고 찝찝한 느낌이 많았습니다 !
(지금도 그렇구요..ㅎ)
그래서 저도 처음엔 Main 문 내 모든 기능을 구현했었습니다. 그리고 간단하게나마 프로그램이 작동하는걸 확인한 뒤 Customer 클래스를 따로 추가해서 생성해보았고 그 이후 ICustomer 인터페이스, Account 클래스 등등 하나씩 추가 하며 동작을 확인하고 커밋으로 기록하는 식으로 했었습니다 ! 물론 그 과정에서 접근 지시자에 관한 에러가 너무 발생하여 캡술화, 추상화 등등 모두를 고려하지 못해 public으로 다 넣긴 해서 코드가 엉망이지만요 🥲

영주 님두 현재 Accout 클래스는 따로 모듈화 하는 것 까진 성공 하셨으니 조금씩 클래스를 더 세분화 시켜 책임 분리를 시키며 객체지향적으로 조금씩 조금씩 고도화 해보시면 어떨까 싶습니다 !

  • 인터페이스, 추상 클래스를 사용해 상속 관계를 조금씩 적용해 보는것도 좋을꺼 같아요 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[week1] 세미나 1차 과제 _ 은행 프로그램 설계
5 participants