Code Structural Analysis


Published on

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • Rigidity (стойкость) – изменение аффектит слишком много зависимостей (МНОГО ЗАВИСИМОСТЕЙ ОТ МОДУЛЯ)Fragility (хрупкость) – поломка в разных местах без конфептуальной связиImmobility (немобильность, тяжеловесность) – невозможность зареюзать компоненты, хвост зависимостей, сложно сделать декомпозицию (МНОГО ТЯНЕТ ЗА СОБОЙ КУЧУ)Viscosity (вязкость) – when normal change is harder to employ than hack due to design (not clear wtf) or environment (compilation 1H)Opacity – не понятна суть и предназначение артифакта, взаимосвязиNeedless Complexity – чтобы сделать что-нибудь, приходится городитьNeedless Repetition – один и тот же функционал в разных кодовых проявлениях
  • - Being Related!= Part of- Packages under Client can be tightly coupled. With an API around.- An Aggregate Root with aggregates + functions- Or a Bounded context, for example.
  • It’s not about slices-first/layers-first fighting. It’s about grouping artifacts that are closely related.“DDD” packagingFunctional components are not visible at all. How to find relations between functional items. “What if I add this, how would it impact my functionality”?What should I do to extract functionality into a separate module? FAT is high that will force you to break logical module into functional. Then you’ll end up with mess managing this layering.Ok, provide API on top.
  • Shotgun surgery instead of localized changes (imagine I move client somewhere). Imagine I put a class that changes frequently into unrelated package. It will change every time as well!
  • I gain portability!!!For example, when mapping relationships, map using ID instead of Entity.Independence – talk to as few as possible. We become mobile, don’t care about incoming/outgoing dependencies
  • E.g. Client is used everywhere! Consider creating different clients. Ideally client can have different forms: Visitor, Client, Lender… Break client into smaller partsAbstract if there is chance that client code will have different cadence (out of release scope)
  • Be conservative in what you expose.Introduce factories that hide implementations (Dependency Injection, Service Locators etc.)Make @Components package-privateSeparate “api” from “internal” packages and restrict access to “internal”Make sure “internal” depends on “api”, not opposite.
  • Two components are connascent if a change in one would require the other to be modified in order to maintain the overall correctness of the system.Strongconnescence – worse.Problem of connascence of order -> in order to achieve goal X, client package A has to invoke two methods from package B. If package A decide that B has to call something in between, or order change, it will break B. Solution: provide coarse-grained interface for goal X, for example.For example: Connascence of Name over Connescance of Entity when desigining entity relationships.
  • Reasons:No guidelines for developers.Unable to simply extract: unable to “levelize” to see what to physically extract for build parallelization
  • Code Structural Analysis

    1. 1. Code Structural Analysis
    2. 2. Eduards Sizovs @eduardsi on Twitter Who is broadcasting?
    3. 3. Agenda • Introduction to structural analysis • Logical Design principles • Q&A
    4. 4. Introduction to structural analysis
    5. 5. Most apps begin life small and neat.
    6. 6. Time goes by…
    7. 7. Hello. I am your rotting enterprise app.
    8. 8. How do we feel design rot?
    9. 9. Rigidity Fragility Immobility Viscosity Opacity Needless Complexity Needless Repetition There are different symptoms that smell…
    10. 10. What structural analysis shows…
    11. 11. Structure of Hibernate Core 3.6.6
    12. 12. Artwork by Jackson Pollock
    13. 13. However, it could be better…
    14. 14. Structure of Spring Framework 3.2.0
    15. 15. Structural analysis allows you to keep app’s structure in shape and catch design flaws early.
    16. 16. Logical Design principles
    17. 17. Package is the first-class citizen and key element of logical design.
    18. 18. Treat packages as hierarchical even if they’re represented flat.
    19. 19. Given packages com.myproject.client com.myproject.client.personal com.myproject.client.profile com.myproject.api Personal and Profile packages are part of Client.
    20. 20. Use packages to group functionally-related artifacts. Do not group artifacts that do the same thing, but are different by nature.
    21. 21. Avoid com.myproject.enums com.myproject.model com.myproject.repository com.myproject.factory com.myproject.helpers … Prefer com.myproject.client com.myproject.lending com.myproject.loyality …
    22. 22. The Common Closure Principle Group tightly coupled classes together. If classes that change together are in the same package, then the impact of change is localized.
    23. 23. Make sure artifacts are not floating away.
    24. 24. Make packages highly cohesive by following Single Responsibility Principle.
    25. 25. Keep packages loosely coupled, ideally – completely independent. Reflection doesn’t count.
    26. 26. Avoid dependency magnets. Sometimes duplication is not that evil.
    27. 27. Aggregate root relationship class Loan { } class Client { // a bunch of stuff } @ManyToOne Client client
    28. 28. Aggregate root relationship class Loan { } class Client { // a bunch of stuff } @Embedded ClientId clientId @Embeddable class ClientId { Long value }
    29. 29. Provide slim package interface and hide implementation details.
    30. 30. Strive for weak package connascence. Keep locality in mind.
    31. 31. Manage relationships. Every dependency arrow has a reason. Burn bi-directional dependences in fire.
    32. 32. Otherwise
    33. 33. Version 1.0 – A great start
    34. 34. Version 1.1 – Imperfection creeps in
    35. 35. Version 1.2 – Imperfection takes hold
    36. 36. Version 1.3 – Chaos begins
    37. 37. Version 1.4 – Explosion
    38. 38. The Acyclic Dependencies Principle The dependencies between packages must not form cycles.
    39. 39. Can be solved by: - Merging - Dependency Inversion - Escalation - Demotion
    40. 40. Client.Beans Merging Client Client
    41. 41. Tracking Dependency Inversion Guest TrackingGuest
    42. 42. Billing Escalation Customer class Customer { Collection<Bill> bills def calculateDiscount() { } } class Bill { def pay(Customer customer) { customer.calculateDiscount() … } }
    43. 43. Billing Escalation Customer class Customer { Collection<Bill> bills } class Bill { def pay(BigDecimal discount) { } } class DiscountCalculator { def calculate(Customer, Bills) } Discount
    44. 44. Billing Demotion Customer class Customer { Collection<Bill> bills def getDiscountCalculator() } class Bill { def pay(DiscountCalculator) { } } class DiscountCalculator { def calculate() } Discount
    45. 45. Class design principles (SOLID)
    46. 46. Single Responsibility Principle Open-Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle
    47. 47. Class should have only one responsibility and only one reason to change. The Single Responsibility Principle
    48. 48. Depend on abstractions, as anything concrete is volatile The Dependency Inversion Principle High Level Policy Abstraction Abstraction Impl. Impl. Package Package X Y X Y interface X Package Package
    49. 49. Client B Service «Client A method» «Client B method» «Client C method» Client C Client A Many client-specific interfaces are better than one general-purpose interface The Interface Segregation Principle Interface A «Client A method» Client B Client C Client A Interface B «Client B method» Interface C «Client C method» Service «Client A method» «Client B method» «Client C method»
    50. 50. Tools Macker JDepend
    51. 51. OO Design Principles & Metrics, Jason Gorman The Economics of Software Design, J.B. Rainsberger SOLID Principles, Eduards Sizovs Designing Object-Oriented Software, Jouni Smed Grand Unified Theory Of Software Design, Jim Weirich Fun With Modules, Kirk Knoernschild More
    52. 52. Conclusion Every application requires structure. Structure must be carefully managed. Integrate Code Structural Analysis into development: • Install CSA tool • Look at the «big picture» • Manage complexity • Prevent entropy
    53. 53. Wish you beautiful architectures.
    54. 54. Thank you!