Ormus
1k
2021-03-02 19:41:09 작성 2021-03-02 20:13:05 수정됨
2
364

객체(Object)와 자료구조(Data Structures)에 대해 의견이 듣고싶습니다.


안녕하세요?


클린코드(Clean Code)책을 읽다가 의문이 생겨서 질문드립니다.


구글링을 아무리 해봐도 책의 내용을 그대로 옮겨쓴 블로그들밖에 없어

현재 의문에 대한 납득가는 해답이 생기질 않습니다.



public class Person {
    String name;
    int age;
}

책의 내용을 보면 자료구조에 대해 이런 방식으로 표현합니다.

내부의 변수를 외부에 공개하는 클래스 정도로 이해가 됩니다.



의문이 생긴 부분의 내용입니다.



자료/객체 비대칭
앞서 소개한 두 가지 예제는 객체와 자료 구조 사이에 벌어진 차이를 보여준다.
객체는 추상화 뒤로 자료를 숨긴 채 자료를 다루는 함수만 공개한다. 자료 구조는 자료를 그대로 공개하며 별다른 함수는 제공하지 않는다.

문단을 처음부터 다시 읽어보기 바란다. 두 정의는 본질적으로 상반된다. 두 개념은 사실상 정반대다. 사소한 차이로 보일지 모르지만 그 차이가 미치는 영향은 굉장하다.


위 글을 보면 자바빈즈나 BigDecimal 같은 경우는 대체 뭔가 싶은 의문이 생깁니다.


public class BigDecimal extends Number implements Comparable<BigDecimal> {
    private final BigInteger intVal;
    private final int scale;  
    private transient int precision;
    private transient String stringCache;





모든 필드를 private으로 제한했고, 메서드를 통해 외부에 노출하고있습니다.

또한 메서드를 통해 내부의 자료를 조작하고 있습니다.


전형적인 객체에 대한 설명에 들어맞는데

제 생각에 그럼에도 불구하고 BigDecimal은 분명히 자료구조라고 생각합니다.

BigDecimal은 대체로 금액에 관련된 정확한 정수형 값을 가지고 있고,

이는 언제든지 호출해 확인할 수 있기때문입니다.


그래서 계속해서 책을 보다보면 BigDecimal은 잡종구조라는 결론으로 귀결되는데,

이후 책에서 잡종구조에 대해

객체와 자료구조의 단점만 모아둔 구조이므로 되도록이면 피하라고 설명하고 있습니다.


근데 그렇게 이해하고 넘어가자니

그토록 안좋다고 설명하고있는 잡종구조의 클래스가 자바 패키지에 들어있고,

전세계에서 유용하게 사용되어지고 있는게 맞나? 라는 의문이 생깁니다.


그래서 이도저도아닌 상태에서 자료구조는 대체 뭐고 객체는 뭔가라는 의문에서 정답을 못찾고있습니다.


자료구조는 크게보면 객체의 부분집합일까요?

DTO는 자료구조일까요? 객체일까요? 제 생각엔 일단 자료구조인 것 같습니다.


Objects vs Data Structures를 보면 이런 구문들이 있습니다.



public class Person {
    public String firstName;
    public String lastName;
    public String phoneNumber;
}


명백한 자료구조라고 설명하고 있습니다.



public class Person {
    private String firstName;
    private String lastName;
    private String phoneNumber;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

}


클린코드 책의 내용대로라면 위의 클래스는 자료구조며

아래의 클래스는 객체라고 보는게 맞다고 생각합니다.


하지만 필드의 접근제한자가 public 에서 private으로 바뀌었고, 접근자와 수정자가 정의되었으나

여전히 외부에서 Person 객체의 변수가 뭔지 짐작할 수 있고 객체의 목적또한 바뀐것이 없기때문에

본질적으로 두 코드는 같으며 자료구조라고 얘기하고 있습니다.


자바빈즈의 경우 접근자와 수정자 없이 필드를 public으로 공개할 경우

프레임워크에서 프로퍼티로 사용하기 위해 접근자와 수정자가 필요하기 때문에

굳이 필드를 private으로 제한하고 모든 필드에 대해 접근자와 수정자를 정의한

표준규약으로 약속되어 사용되고 있다고 납득하고 넘어갈 수 있었습니다.



public class Person {
    private String firstName;
    private String lastName;
    private String phoneNumber;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    private void validatePhoneNumber (String phoneNumber) throws FormatException {
        // Do validation here to ensure we have a legit phone number.
        // Throw an exception if its invalid.
    }

}


위의 클래스에 validatePhoneNumber() 라는 핸드폰번호 유효성 검사 메서드가 생겼습니다.

이제 이 객체에는 다른 목적과 행동(Methods)이 생겼기 때문에 객체로 볼수 있느냐는 물음이 있습니다.


저는 잡종구조라고 생각했습니다.

자료구조도 맞는것 같고 OOP의 객체도 맞다고 생각했기때문입니다.


하지만 위 글에서는 Person객체에 유효성검사 기능이 생기므로서 다른 목적과 행동이 생겼으나

여전히 모든 필드가 외부에 공개되어있다시피 하고(캡슐화가 되어있지 않고),

누구나 내부의 자료를 짐작하고 조작할 수 있기 때문에 여전히 자료구조라고 얘기하고 있습니다.



No matter how much lipstick you put on this pig, Person is a data structure, not an object.

심지어 Person 객체라는 돼지에 아무리 립스틱을 바르더라도 Person은 객체가 아니고 자료구조라고 하네요.



고수님들 생각은 어떠신가요?

이게 딱 답이 정해진 의문일까요?


책을 보면서 계속 쓸데없는 의문만 생기는 것 같습니다 ;(


0
  • 답변 2

  • fender
    23k
    2021-03-02 20:34:42 작성 2021-03-02 20:39:27 수정됨

    살짝 의아한 내용이라 링크된 원문을 읽어보았습니다. 내용을 보니 어떤 관점에서 그런 주장을 하는 지는 이해는 되고, "틀린" 이야기는 아니라고 생각은 들지만, 개인적으로 동의하기 어려운 부분이 많았습니다.

    예컨대 클래스와 자료구조의 차이를 강조하는 내용은 이른바 "anemic domain model"라고 부르는 설계 관행에 대한 비판이라면 납득할 수 있는 부분이지만 마치 용어 정의에 대한 구분이 중요한 것처럼 착각할 수 있게 서술하고 있는 부분이 마음에 들지 않더군요. 아마 질문하신 내용도 그런 오해에서 출발한 것이 아닌가 싶습니다.

    그리고 예시의 설계 관행이 SOLID 원칙을 위반하고 있다는 관점도 완전히 동의하긴 어려웠습니다. 예시의 Person 클래스가 게시판 같은 시스템의 사용자를 나타내는 것이라면, 사용자의 이름과 이메일의 유효성을 확인하는 것이 정말로 인터페이스 분리가 필요한 다른 관점의 문제라고 단언할 수 있나요?

    물론 예시에는 유효성 검사를 전담하는 별도 클래스를 만드는 접근을 소개하고는 있지만, 그건 해당 프로젝트에서 이메일 검사 같은 코드가 재사용이 필요할 만큼 자주 쓰이고 사용 사례 간의 유사성이 있다면 고려할 수 있는 선택의 문제이지 Person 클래스 하나보고 무작정 속성 별로 유효성 검증 인터페이스를 뜯는게 정석이다라고 생각할 문제는 아닙니다.

    특히 사용자에서 전화번호 만 필요한 경우도 있기 때문에 이름 등을 다루는 인터페이스와 분리하지 않으면 ISP 위반이라고 하는 건 상당히 오해/문제의 소지가 많은 주장이고, Open/Closed 원칙을 Person에 필드를 추가하는 경우로 설명하는 것도 꽤 부적절한 예시라고 봅니다.

    다만 이는 어느정도 해석과 주관이 개입할 수 있는 문제이기 때문에 꼭 참고하신 글이 "틀렸다"라고 할 수 있는 건 아닙니다.

    개인적인 감상으로는 아직 객체지향 개념이 익숙하지 않은 개발자가 보기엔 꽤 혼동스럽고 오해의 소지도 많은 내용이기 때문에 해당 글이 소개하는 "객체"와 "자료구조"의 엄밀한 정의 같은 문제에 너무 천착하지 않는 것이 바람직하다고 생각합니다.

    단지 결론에 해당하는 아래 내용은 정론에 가까운 이야기라 새겨들을 필요가 있는 것 같습니다:

    Instead, define behaviors based on your use-cases, define data structures based on your I/O requirements, and then define objects to connect the two.
  • Ormus
    1k
    2021-03-02 20:57:54
    fender
    역시 다른 견해가 나오는군요 ㅜㅜ
    제생각에도 이건 뭐가 무조껀 답이다 라는 결론이 나올만한 문제가 아니라고 생각하긴 했습니다.

    다만 객체와 자료구조의 차이에 대해 의문을 갖게된 계기는 
    클린코드책에는 디미터법칙에 대해 자료구조라면 어차피 외부에 공개되야하는 자료들이기 때문에 상관없지만, OOP 객체라면 디미터법칙을 위반하지 않는게 좋다는 글귀가 있었기 때문입니다.

    제가 JPA를 공부하고 있는데, 문득 JPA Entity는 자료구조인가? 객체인가? 라는 의문과 함께 만일 객체라면 JPA Entity의 객체그래프 탐색에 대해 디미터 법칙을 위반하고 있지는 않은지라는 의문이 들었었구요.

    아무튼 정성스러운 답변 감사드립니다 !

  • 로그인을 하시면 답변을 등록할 수 있습니다.