싱글벙글 OOP 생활 - 1

최혜성·2024년 1월 18일
0

갑자기 생각날때마다 쓰는 글

기존에 설계했던 인터페이스의 일부 구현체가 다른값을 리턴해야만 했다

interface Reader
     fun read() : String
     
class AReader
     override fun read() = return "A Result"
     
class BReader
     override fun read() = return "B Result"
     
     fun extraData() = "Additional Data"

원래는 B리더를 잘 쓰고 있었는데 추가 데이터를 반환할 일이 생겼다.

그래서 이걸 캐스팅하자나 OOP 원칙에 위배되고, 인터페이스에 넣자니 A클래스는 해당이 안되고, 인터페이스를 버리자니 A클래스가 아깝고

어캐야되나 생각했는데 추가 데이터를 반환하는것 끼리 묶고 그걸 참조하면 되겠다고 생각했다

interface ExtraReader : Reader

     fun extraData()
    
    
//ExtraReader 구현
class BReader : ExtraReader  

    fun read() ~
    
    fun extraData() ~
     

이렇게 하면 BReader를 Reader로써도, ExtraReader로써도 쓸 수 있다.

근데 여기서 한번더 막혔다. extra data를 특정 dto로 mapping 해야 했다. 그러면 각 구현체마다 dto로 매핑할 수 있도록 지원해야 했는데 class generic은 왠지 쓰기 싫었다. 그렇다고 원본 클래스로 참조하기도 좀 그렇고

한번더 꼬아봤다

interface CoolReader : ExtraReader

      fun setupCool = CoolDto(getExtraData())
      
interface HotReader : ExtraReader

      run setupHot = HotDto(getExtraData())

Cool이랑 Hot은 일정한 구조를 띄고 있어 재활용될 가능성이 높았다
-> 그냥 Response의 추상화라 보면 될듯

그래서 구조를 보면

              Reader
          /           \
  AReader(impl)     ExtraReader(I)
                    /            \
             HotReader(I)      CoolReader(I)
                  ㅣ
                BReader
                

구조가 이렇게 될거 같은데.. 그냥 상속 구조로 짜지말까
하지만 C리더가 추가된다면 HotReader에 붙을거고, D리더는 Cool에 붙을텐데

머리가 아프다

20:50

생각해보니 ExtraData도 read를 해야 읽을 수 있는 정보이다. 따라서 Read의 Response로 주는게 맞아서 위 구조는 성립될 수 없음 :(

22:15

억지로 안맞는거 끼리 붙이는건 OOP, SOLID 다 위배함. 그정도면 다른 클래스로 분리하는게 욕 덜 들어먹음

그래도 같은 READ를 한다는 점에서 동일한데 반환 결과만 다를뿐.

음 생각하다보니 Adapter 패턴이 떠올랐는데 유사하게 구현가능할듯

무조건적으로 Reader를 상속한다기 보단, 각 클래스가 뭘 할려고 하는지 생각해보자

AReader - 단순 read : String만 반환
BReader - 단순 read + Extra read : 특수 데이터인 ColdDTO반환

근데 생각해보면 read로 부터 extra read를 유도해내야 하는데, 반대로 생각해보면 extra read를 함으로써 단순 read의 result를 뽑아내면 되지 않을까?
(일반 read와 extrea read는 같은 파일을 읽음. 읽는 범위만 다를뿐)

그러면 ExtraRead를 할 수 있는 클래스를 분리해보자

class ExtraReader
     fun readExtra() : ColdDto
      
data class ColdDTO //실제 그 DTO가 아니다 그냥 이름만
   val read
   val extraRead

이때 ReadData는 기존의 Extra범위만 읽힌게 아닌 일반 read + extra를 읽은 반환값이다

따라서 위 데이터를 잘 가공한다면 일반 read를 그대로 사용할 수 있지 않을까?

class ExtraReader : Reader
     override fun read()
          call readExtra().read
     
     fun readExtra() : ColdDto
          

이러면 될듯? Extra가 필요하면 해당 클래스로 불러오고
이제 인터페이스로 분리하면 될듯

interface ColdReader
     fun readExtra() : ColdDto
profile
KRW 채굴기

0개의 댓글