Dependency Breaking Techniques

5,569
-1

Published on

LegacyCode

아꿈사 스터디 발표자료.

Published in: Technology
1 Comment
4 Likes
Statistics
Notes
No Downloads
Views
Total Views
5,569
On Slideshare
0
From Embeds
0
Number of Embeds
12
Actions
Shares
0
Downloads
0
Comments
1
Likes
4
Embeds 0
No embeds

No notes for slide

Dependency Breaking Techniques

  1. 1. Dependency Breaking Techniques Working Effectively with LegacyCode Ver 1.0 아키텍트를 꿈꾸는 사람들 cafe.naver.com/architect1 현수명 soomong.net #soomong
  2. 2. before after24 dependency breaking techniques
  3. 3. 1. Adapt Parameter Interface A’ Method ( A ){ ... } Concrete A’ Concrete A’ for production for test
  4. 4. When to use? - parameter is difficult to test. - can’t use Extract Interface on a parameter’s class.
  5. 5. 2. Break Out Method Object Class longMethod A() { … … … New Class A } longMethod () { … … … }
  6. 6. When to use?- method is too large- use instance data and methods
  7. 7. 3. Definition Completion Definition for Definition Test Concrete Class Concrete Class
  8. 8. When to use? - language supplies that can declare a type in on place anddefine it another.- to break dependencies in procedural language like C.
  9. 9. 4. Encapsulate Global References Class New Class A Global reference Global reference
  10. 10. When to use?- to separate dependencies on global references.
  11. 11. 5. Expose Static Method Class Class Static Method () { … Method () { } … }
  12. 12. When to use?- trying to test code that can’t be instantiated.
  13. 13. 6. Extract and Override CallClass Class Class for test Method ( ) { Method ( ) { … … logic call A(); … … } } @Override Method A ( ) { Method A( ) { logic test logic } }
  14. 14. When to use?- trying to test only single method call.
  15. 15. 7. Extract and Override Factory MethodClass Class Class for testconstructor( ) { constructor( ) { … … object = new A() object = call A(); … …} } @Override Factory method A(){ Factory method A(){ return new A() … } }
  16. 16. When to use?- trying to test code that creates objects in constructor.
  17. 17. 8. Extract and Override GetterClass Class Class for testconstructor( ) { constructor( ) { … … object = New A() object = null; … …} } @Overrideobject Getter Method getA(){ Getter Method getA(){ if A is null … object return new A(); } return A; } getA() getA() Lazy initialize
  18. 18. When to use? - trying to test code that creates objects in constructor - language doesn’t support virtual function call in a derived classfrom base class’s constructor
  19. 19. 9. Extract Implementer Duplicated Class Method A() { InterfaceClass … } virtual Method A() Method A() { … Method B() { virtual Method B() } … } Method B() { … }
  20. 20. When to use?- hard to naming the interface
  21. 21. 10. Extract Interface Interface virtual Method A() Concrete ClassClass Method A() { virtual Method B() Method A() { … … } } Method A() { Method B() { … … } }
  22. 22. When to use?- trying to test code that break dependency
  23. 23. 11. Introduce Instance DelegatorClass Class Class for testStatic Method A( ) { Static Method A( ) { … …} } @Override Method A’(){ Method A’(){ Class.A() A(); … } } Class.A() instance.A’() instance.A’()
  24. 24. When to use?- static method has logic that hard to test- it’s weird- 더 큰 리팩토링의 시작
  25. 25. 12. Introduce Static SetterClass Class Class for testStatic instance Static instanceprivate constructor( ) { protected constructor( ) {} }Static Method getInst(){ Static Method getInst(){ if instance is null if instance is null instance = new Class(); instance = new Class(); return instance; return instance;} } @Override Method setInstance(…) { Method setInstance(…) { instance = … test logic } }
  26. 26. When to use? - Singleton test - Protected constructor = can subclassing = 구리다 - singleton을 코드로 강제하는 것보다는 팀원들이모두 이해하는게 더 중요하다?
  27. 27. 13. Link Substitution Global reference for test Call history Value history Method A() { … } Method A() { record call history record value history … }
  28. 28. When to use?- to break dependencies in procedural language like C.
  29. 29. 14. Parameterize ConstructorClass Class Class for testconstructor( ) { constructor( ) { … this( new A() ); object = new A(); } …} constructor( A ) { constructor( A ) { … … object = A; object = test; … … } }
  30. 30. When to use?- to separate the object that created in constructor.has dependencies on parameter’s class.but it’s a small concern.
  31. 31. 15. Parameterize Method Class Class Method( ) { Method( A ) { … … object = new A(); object = A; … … } }
  32. 32. When to use? -to separate the object that created in method.dependency issue?Extract and Override Factory Method is alternative way.
  33. 33. 16. Primitivize ParameterClass Class TestClassMethod ( ) { Method ( ) { TEST( ) { … … … logic call free function(); call free function(); … … }} } free function( ) { logic }
  34. 34. When to use?- work to get a class under test is too large.- what the…
  35. 35. 17. Pull Up Feature New Abstract Class Method A( ) { … } abstract Method B abstract Method C Class Method A( ) { … Class Class for test } Method B( ) { TEST( ) { Method B( ) { … CHECK(A()); … } } } Method C( ) { Method C( ) { … … } }
  36. 36. When to use?- to test just one method that clustered with other methods.
  37. 37. 18. Push Down Dependency Abstract ClassClass Method A( ) { Method A( ) { … … } } Method B( ) { Method B( ) { … … } } abstract drawUI()Method drawUI( ) { …} New Concrete Class Concrete Class for test Method drawUI( ) { Method drawUI( ) { … // do nothing } }
  38. 38. When to use? - dependencies are pervasive like drawing UI.
  39. 39. 19. Replace Function with Function Pointer Method main( ) { Method main( ) { … … A(); *pointer … … } } *Method testA( ) { test logic } Method A( ) { … } *Method A( ) { … }
  40. 40. When to use?- to break dependencies in procedural language like C.Different points of view- horribly unsafe VS useful tool
  41. 41. 20. Replace Global Reference with GetterClass Class Class for test Global references A Global references AA getA A getA @Override Getter Method getA() { Getter Method getA() { return A; … } }
  42. 42. When to use?- separate dependencies on global references
  43. 43. 21. Subclass and Override Method Class Class private Method A(){ protected Method A(){ … … } } subClass for test @Override protected Method A(){ … }
  44. 44. When to use? - break dependencies in object-oriented language.Many of the other dependency-breaking techniquesare variations on it.
  45. 45. 22. Supersede Instance Variable Class Class Class for test variable variable constructor( ) { constructor( ) { variable; variable; } } @Override supersedeVariable(A) { supersedeVariable(A) { variable = A; … } }
  46. 46. When to use? - separate objects that created in constructor. - language disallows overrides of virtual function callsin constructors.Use uncommon prefix : supersede개발자들이 잘못 사용할지도 모르니잘 모르는 uncommon 한 단어를 prefix 로 사용하자??
  47. 47. 23. Template Redefinition generics Method ( A ){ ... } Concrete type Concrete type for production for test
  48. 48. When to use? - language supplies generics and a way of aliasing types.
  49. 49. 24. Text Redefinition TestClass Class Class def Method A() def Method A() end … logic … end TEST( ) { … test Class }
  50. 50. When to use?- break dependencies in interpreted language like Ruby.
  51. 51. 전체 정리하면서 느낀 점- 억지스러운 면이 자주 보인다.- dependency 는 깨질지 몰라도 Readability는 더 낮아진다.- 코드가 잘못 사용될 수 있으니 개발자가 더 주의 깊게 살펴봐야 한다.- 아무래도 LegacyCode 와의 싸움이 힘겹긴 한가보다. 이해하자.- 억지스럽고 지저분한 방법일지라도 대안이 없다면 그게 바로 최선의 방법이다.- 원문이 훨씬 보기 쉽다. (번역 X)
  52. 52. Reference 레거시코드 활용 전략 http://www.yes24.com/24/goods/3092523
  53. 53. 감사합니다

×