63
오픈소스 리팩토링 하기 - JEDIS (redis java client) - SoftwareArchitecting 김주희, 이경민 https://github.com/kjhwee91/jedis

오픈소스 리팩토링 하기(전 과정) - JEDIS

  • Upload
    -

  • View
    339

  • Download
    4

Embed Size (px)

Citation preview

Page 1: 오픈소스 리팩토링 하기(전 과정) - JEDIS

오픈소스 리팩토링 하기 - JEDIS (redis java client) -

SoftwareArchitecting 김주희, 이경민

https://github.com/kjhwee91/jedis

Page 2: 오픈소스 리팩토링 하기(전 과정) - JEDIS

요약

• 문제점1 : 패키지 간의 Tangled

- 해결단계1. jedis 패키지 안에 있던 HostAndPort를 새로운 패키지인 host로 분리

- 해결단계2. jedis 패키지 안에 있던 exception 패키지를 밖으로 분리

- 해결 결과

• 문제점2 : jedis 내부에 패키징 되어 있지 않음

- 해결단계1. 조건에 따라 리패키징

- 해결단계1-1. JedisShardedInfo 클래스 관련 tangled 수정하기

- 해결단계1-2. client 클래스와 commands 인터페이스간 tangled 수정하기 첫번째

- 해결단계1-3. client 클래스와 commands 인터페이스간 tangled 수정하기 두번째

- 해결결과

• 문제점3. 리패키징 한 후 해결하지 못한 문제

- 해결단계1. 패키지 네이밍 다시 하기

- 해결단계2. 패키징 더 깔끔하게 하기

- 해결단계3. 리패키징이 부적절한 경우 (단순히 tangled 해소를 위한 배치) 해결

- 해결단계4. 리패키징 하면서 생긴 에러 수정하기

- 해결단계4-1. 에러가 수정후 새롭게 생긴 tangled 수정하기

• 최종 결과

Page 3: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점1. 패키지간의 Tangled 지수가 심함

Page 4: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점1. 패키지간의 Tangled 지수가 심함

- exceptions와 jedis 안에 있는 HostAndPort 사이의 의존 관계가 있음

- util과 jedis 안에 있는 HostAndPort 사이의 의존 관계가 있음

- util과 jedis패키지 안에 있는 exception 패키지와의 의존관계가 있음

Page 5: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점1. 패키지간의 Tangled 지수가 심함 해결단계1. HostAndPort를 새로운 패키지인 host로 분리

- Couplings 를 보고 HostAndPort 클래스는 jedis 밖에서 사용 되는 것이 맞다고 판단

- jedis 패키지 안에 있던 HostAndPort 클래스를 새로운 host 패키지로 포함

Page 6: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점1. 패키지간의 Tangled 지수가 심함 해결단계2. jedis 패키지 안에 있던 exception 패키지를 밖으로 분리

- jedis 패키지 안에 있던 exception 패키지를 밖으로 분리

- exception 패키지는 jedis 안에서만 사용되지 않고, util 과도 의존 관계를 갖고 있기 때문에 밖

으로 분리시킴

Page 7: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점1. 패키지간의 Tangled 지수가 심함 해결결과

- 오염도 하락

(5.57 -> 4.21) - tangled 제거

Page 8: 오픈소스 리팩토링 하기(전 과정) - JEDIS

before after

문제점1. 패키지간의 Tangled 지수가 심함 해결결과

Page 9: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음

- redis 의 주요 기능을 제공하는 클래스가 들어있는 jedis 패키지 내부를 보

면 기능별 분류가 전혀 되어있지 않음

- 첨부된 Composition 결과는 jedis 하나의 패키지 내부의 상황

Page 10: 오픈소스 리팩토링 하기(전 과정) - JEDIS

• composition의 구조, 클래스 이름, 주요 기능을 참고해서 리패키징 할 클래스를 선택한다.

• 우선순위 및 조건

- Composition 결과의 최대한 상위에 있을것

- 해당 클래스를 참조하는 다른 클래스가 적을 것

- handling, pooling 등 부수적 역할이 부여된 클래스가 아닌 중심 역할이 부여된 클래스인 것

- tangled 가 발생하지 않는 범위 내에서의 이동

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 11: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

1. cluster 패키지 생성

2. JedisCluster, JedisClusterCommand 클래스 이동

Page 12: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 13: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

1. pool 패키지 생성

2. ShardedJedisPool, JedisPoolConfig 클래스 이동

Page 14: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 15: 오픈소스 리팩토링 하기(전 과정) - JEDIS

1. handler 패키지 생성

2. 세가지 핸들러를 패키지로 이동

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 16: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 17: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

1. shard 패키지 생성

2. ShardJedis, BinaryShardedJedis, ShardJedisPipeline 이동

Page 18: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 19: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

1. 이미 있는 pool 패키지에 JedisPool, JedisSenctinelPool 이동

Page 20: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 21: 오픈소스 리팩토링 하기(전 과정) - JEDIS

• 참고사항

- JedisFactory가 참조하고 있는 Jedis 와 BinaryJedis 클래스는 매우 많은 클래스들과 참조관계에 있음

- 특히 Jedis 클래스는 자바에서 레디스를 사용하는데 가장 기본적인 클래스이기 때문에 중요하다고 판단

• 해결법

1. core 패키지 생성

2. BinaryJedis, JedisFactory, Jedis 이동

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 22: 오픈소스 리팩토링 하기(전 과정) - JEDIS

- JedisShardInfo 클래스가 jedis 클래스와 상호 참조 중

- JedisShardInfo 클래스를 shard 패키지로 이동 시킴

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다. 해결단계1-1. JedisShardedInfo 클래스 관련 tangled 수정하기

Page 23: 오픈소스 리팩토링 하기(전 과정) - JEDIS

- JedisShardInfo 클래스를 shard 패키지로 이동한 후

에도 Tangled 존재

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다. 해결단계1-1. JedisShardedInfo 클래스 관련 tangled 수정하기

Page 24: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다. 해결단계1-1. JedisShardedInfo 클래스 관련 tangled 수정하기

1. info 패키지 생성

2. JedisShardInfo 클래스 이동

- 이동 후에도 tangled 사라지지 않음

Page 25: 오픈소스 리팩토링 하기(전 과정) - JEDIS

- JedisShardInfo 클래스는 샤딩할 레이스 클라이언트들을

정의할 때 사용하기 때문에 기본적으로 Shard 와 관련된

클래스

- 우선 순위 중에 tangled 발생시키지 않는 것도 있기 때문

에 기능상으로는 적합하지 않지만 Jedis, BinaryJedis 와

같은 패키지에 포함시킴

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 26: 오픈소스 리팩토링 하기(전 과정) - JEDIS

1. cmd 클래스를 생성한다.

2. command 와 관련된 인터페이스를 이동한다.

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 27: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 28: 오픈소스 리팩토링 하기(전 과정) - JEDIS

1. transaction 패키지를 생성한다.

2. Transaction, TransactionBlock클래스를 이동한다.

1. pipeline 패키지를 생성한다.

2. Pipeline, PipelineBlock 클래스를 이동한다.

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 29: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 30: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

1. PipelineBase 클래스와 MultikeyPipelineBase 클래스를 pipeline 패키지로 이동한다.

Page 31: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 32: 오픈소스 리팩토링 하기(전 과정) - JEDIS

1. pubsub 패키지를 생성한다.

2. BinaryJedisPubsub, JedisPubsub 클래스를 이동한다.

!1. client 패키지를 생성한다.

2. Client 클래스를 이동한다.

!1. usage 패키지를 생성한다.

2. JedisMonitor 클래스를 이동한다.

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 33: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 34: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

1. BinaryRedisPipeline, RedisPipeline 인터페이스는 pipeline 패키지로 이동한다.

2. Commands 인터페이스는 cmd 패키지로 이동한다.

- Client 클래스와 Commands 인터페이스간 상호 참조 발생

Page 35: 오픈소스 리팩토링 하기(전 과정) - JEDIS

• client 클래스와 commands 인터페이스간 상호 참조 발생

• cmds 패키지 내부에 있는 commands 인터페이스를 다른 패

키지로 이동하기

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다. 해결단계1-2. Client 클래스와 Commands 인터페이스간 tangled 수정하기1

Page 36: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 37: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

1. BinaryClient 클래스를 client 패키지로 이동한다.

2. MultiKeyBinaryRedisPipeline, MultiKeyCommandsPipeline 인터페이스를

pipeline 패키지로 이동한다.

!1.Support 패키지를 생성한다.

2. ScanResult 클래스를 이동한다.

Page 38: 오픈소스 리팩토링 하기(전 과정) - JEDIS

• tangled 를 생성하지 않는 것도 중요한 조건

• cmds패키지 안에 있는 Commands 인터페이스를 Client 패키지로 이동

• Commands 인터페이스에 관한 패키징은 추후에 다시 해결

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다. 해결단계1-3. client 클래스와 commands 인터페이스간 tangled 수정하기2

Page 39: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 40: 오픈소스 리팩토링 하기(전 과정) - JEDIS

1. params 패키지 생성

2. params 와 관련된 클래스 이동

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 41: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 42: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

• ClusterPipeline, BasicRedisPileline - pipeline 패키지로 이동

• Queable - usage 패키지로 이동

• Connection, Protocol - conn 패키지 생성 후 이동

• Tuple - worker 패키지 생성 후 이동

• BitOP - support 패키지 생성 후 이동

Page 43: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결단계1. 우선순위에 따라 차례대로 리패키징한다.

Page 44: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결 결과

before

after

after

Page 45: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점2. jedis가 전혀 패키징 되어 있지 않음 해결 결과

- 오염도 하락

(4.21->3.69) - fat 감소

Page 46: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제

• 네이밍

• 단순히 tangled 만 해결한 문제

- cmds패키지 안에 있는 Commands 클래스를 Client 패키지로 이동

- core 패키지 안에 있는 jedisshardinfo

• 묶을 수 있는 것은 묶고, 더 분리해야 할 필요성이 있는 것들 분리하기

• 에러가 생긴것 수정하기

Page 47: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계1. 패키지 네이밍 다시 하기

• cmd : command - 최대한 한번에 알아 볼 수 있도록 하기

• core : 패키징 안하기

- core ‘핵’과 같은 느낌이라서 접근하지 말아야 한다는 느낌이 들

기 때문에 적절하지 않음

- client.jedis 내에 패키징 없이 두고, 클라이언트와 가장 가깝게

배치함

Page 48: 오픈소스 리팩토링 하기(전 과정) - JEDIS

• 테스트 패키지에 있는 클래스들과 “AdvancedUsage” 튜

토리얼을 통해서 핵심적인 기능 파악하기 - Transactions - Pipelining - Publish/Subscribe - ShardedJedis - Monitoring - …

https://github.com/xetorthio/jedis/wiki/AdvancedUsage

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계2. 패키징 더 깔끔하게 하기

Page 49: 오픈소스 리팩토링 하기(전 과정) - JEDIS

• 핵심기능 대로 분류된 패키지의 경우 해당 기능을 유지

하는데 필요한 클래스 및 인스턴스와 해당 기능이 확장

되어서 사용되는 클래스가 섞여 있었음

- 기능 유지에 필요한 클래스 / 기능이 확장된 클래

스 별로 패키지를 나눔

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계2. 패키징 더 깔끔하게 하기

Page 50: 오픈소스 리팩토링 하기(전 과정) - JEDIS

• 여전히 패키지 분류가 부족한 듯한 느낌

• 기본 클래스 / 사용하는 클래스로 나누어진

것들이 많음

• 기본 패키지 밑에 하위 패키지로 ‘사용하는

클래스’ 패키지를 새로 생성

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계2. 패키징 더 깔끔하게 하기

Page 51: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계2. 패키징 더 깔끔하게 하기

Page 52: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계2. 패키징 더 깔끔하게 하기 해결단계2-1. 리패키징 하면서 생긴 tangled 수정하기

• support 와 usage 의 패키징에 별 의미

가 없다고 생각해서 support 패키지로

합침

• support 와 client 패키지 간 tangled

발생

Page 53: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계2. 패키징 더 깔끔하게 하기 해결단계2-1. 리패키징 하면서 생긴 tangled 수정하기

• support 패키지의 BitOP 를 이동하는 것보다

JedisMonitor 를 이동하는 것이 더 낫다고 판단

- monitor 패키지를 생성하기

- JedisMonitor 클래스 이동하기

• usage 패키지 제거

Page 54: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계2. 패키징 더 깔끔하게 하기 해결단계2-1. 리패키징 하면서 생긴 tangled 수정하기

Page 55: 오픈소스 리팩토링 하기(전 과정) - JEDIS

• 주요 기능에 관한 패키지

• support 에 관련된 패키지 - worker, conn, params 등

을 support 패키지로 포함시킴

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계2. 패키징 더 깔끔하게 하기

Page 56: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계3. 리패키징이 부적절한 경우 (단순히 tangled 해소를 위한 배치) 해결

• core 안에 있는 jedisShardInfo

- AdvancedUsage에 따르면 jedisShardInfo는 샤딩을 진

행하기 전에 샤딩된 서버 목록의 정보를 알아오는 과정을 진행

하는 클래스

- ShardedJedis 를 랩핑하는 기능으로써 클라이언트와 가까

운 기능이기 때문에 core에 포함되어도 무방함

Page 57: 오픈소스 리팩토링 하기(전 과정) - JEDIS

• Commands 인터페이스는 이전에 리패키징 하는 과정에서 tangled

를 생성되지 않기 위해 의도치 않게 Client 클래스와 같은 패키지에 넣

은 것

• commands 패키지 내의 *Commands.linsert라는 메소드가

BinaryClient의 LIST_POSITION이라는 enum값을 참조.

• client 패키지 내의 Client는 Commands를 implements.

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계3. 리패키징이 부적절한 경우 (단순히 tangled 해소를 위한 배치) 해결

Page 58: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계3. 리패키징이 부적절한 경우 (단순히 tangled 해소를 위한 배치) 해결

• LIST_POSITION이라는 enum값을

BinaryClient로 부터 분리, 새로운 패키지로 이동

시킴

• commands 패키지를

commandsBase와 commands 패

키지로 분리

• commands에는 Commands.java

라는 interface만 들어있음

Page 59: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계4. 리패키징 하면서 생긴 에러 수정하기

• 원래 하나의 package에서 출발했기 때

문에 패키지를 변경하는 과정에서 몇 가

지 문제가 발생

- protected 혹은 공개범위를 설정

하지 않은 class들을 참조하는 경우

에러가 발생

- 문제가 생기는 class들은 모두

public으로 변경

Page 60: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계4. 리패키징 하면서 생긴 에러 수정하기 해결단계4-1. 에러가 수정후 새롭게 생긴 tangled 수정하기

• 새로운 클래스를 생성해서 getParam()

만 밖으로 분리함

Page 61: 오픈소스 리팩토링 하기(전 과정) - JEDIS

문제점3. 리패키징 한 후 해결하지 못한 문제 해결단계4. 리패키징 하면서 생긴 에러 수정하기

• ListPosition 클래스와

JedisParam 클래스를 support 패

키지로 이동

Page 62: 오픈소스 리팩토링 하기(전 과정) - JEDIS

최종결과

Page 63: 오픈소스 리팩토링 하기(전 과정) - JEDIS

최종결과

- 오염도 하락

(5.57 -> 2.83) - fat 감소

- tangled 제거