From Legacy to Reactive: The First Mile

From Legacy to Reactive: The First Mile

The first few decisions an architect must make on a modernization project are critical, but while most learning materials concentrate on the end goal of a modern architecture, we’re going to focus on the first few steps. While not revolutionary, the most common question asked by architects and consultants in the modernization space is “where do we even begin?”

Many teams get stuck on how to properly kick off a project of this scope. We’ll discuss modernization from the very first few steps. Event storming will bring all key stakeholders together in a collaborative environment in order to define the business processes involved and how to translate them into event-driven systems. This will show us a path towards the scope of initial work, while also planting the seeds for cultural change within an organization by focusing on the most interesting events that already occur within your business.

Once we have define the scope of initial work, we’ll pick up speed by diving into the first key architectural decisions and how make those decisions guided by the first-principles of Domain-Driven Design. We’ll dive deep into the nitty gritty by turning our DDD models into user stories and then implementing a few of those stories. We must do this while balancing the complexities of enterprise integration. How do we integrate new microservices into an old, brittle legacy system? How do we handle new and old systems living alongside each other?

This talk is inspired by Kevin’s upcoming mini-book from O’Reilly, Migrating Java to the Cloud: Modernize Enterprise Systems Without Starting From Scratch. By the end of this session, it will be apparent why a forceful revolution doesn’t work at enterprise scale. Instead, we’ll make the case for a calm, methodical, and measurable evolution of enterprise systems.

“You say you got a real solution? Well, you know, we'd all love to see the plan.”

665a7ca82af87606f4fc83b3d94b5fd5?s=128

Kevin Webber

October 19, 2017
Tweet

Transcript

  1. From Legacy to Reactive: The First Mile Kevin Webber Principal

    Consultant @ RedElastic e: kevin.webber@redelastic.com m: medium.com/@kvnwbbr t: @kvnwbbr
  2. Why? — Enterprise software continues to be built piecemeal as

    applications rather than systems — Complex integrations — Most enterprise software is complex because we continue to be encumbered by the chains of the past
  3. Traditional architecture — Unbounded in complexity and side effects —

    Batch-mode, high-latency, high-failure rates — Has an impact — Customer happiness — The ability to hire the best — Visit TheDailyWTF
  4. Traditional infrastructure — Active/passive with crude failover — Complex state

    replication between active and passive
  5. Focus on goals — complex/brittle → simple/predictable — unbounded complexity

    → defined boundaries — batch → real-time
  6. Stay skeptical — Industry still debating over key terminology —

    Emerging buzzwords terms
  7. Steps to enterprise modernization 1. Define business processes → Events

    & Event Storming 2. Create structure for systems → Domain Driven Design 3. Translate models into requirements → User Stories 4. Code → Java, Play, Akka
  8. 1. Events 2. DDD 3. Requirements 4. Implementation

  9. Events are — Interesting things, that have — happened in

    the past.
  10. Events enable flexibility — Publishers publish interesting events by default

    — System components integrate with minimal coordination costs
  11. Systems have been event driven for centuries!

  12. Commands and events — We can model cause and effect

    more directly using commands
  13. The most interesting events cause a reaction. O!en you need

    to know why a system reacts in the way it did. — Martin Fowler
  14. Fear the fear — Fear paralyzes progress because cause and

    effect is unclear in traditional legacy systems — One of our first goals should be to remove fear and increase confidence — Events help us with both
  15. Event Storming — A design and collaboration methodology in workshop

    format — Use event storming to collaborate on design with all stakeholders — Define new business processes and revisit existing ones — Create high-level models that can be shaped into blueprints for software
  16. Modeling event flows What you'll need: — A room —

    Sticky notes — A wall Sounds simple? It is!
  17. Complete business processes emerge...

  18. 1. Events 2. DDD 3. Requirements 4. Implementation

  19. Event Storming + DDD

  20. Translating Events to DDD — The one thing missing from

    event storming models is a root entity — This models state changes caused by commands and events — State changes must be modeled explicitly
  21. Defining aggregate boundaries — Structures implementation around related items —

    The yellow sticky in the middle represents state
  22. Defining bounded contexts — Group together related business concepts —

    Contain domain complexity — A single person can master an aggregate — A single team can master a bounded context
  23. 1. Events 2. DDD 3. Requirements 4. Implementation

  24. — As a user — I can add items to

    my cart — So that I may continue shopping
  25. — As a user — I can receive an email

    about my cart contents — So that I may remember to fulfill my order
  26. Acceptance Criteria — Given a user is inactive for x

    minutes — When they have products in their cart — Then send them a follow up email and emit an event
  27. 1. Events 2. DDD 3. Requirements 4. Implementation

  28. Akka and DDD — Akka provides isolation around state —

    State can only be influenced through messaging — Actors are a perfect abstraction for aggregates
  29. Shopping Cart Example (Scala) def receive = { case AddItem(item)

    => // 1. accept a command persist(ItemAdded(item)) { // 2. create the event and persist contents += item // 3. apply the event emitEvent(ItemAdded(item)) // 4. emit the event } case AbandonSession => // 5. handle reminders emitEvent(SessionAbandoned) }
  30. Journal backed actors — Actors handle commands and queries —

    Events are generated from commands and journaled — The log is immutable and durable — Each actor is resilient without requiring databases
  31. None
  32. None
  33. Cluster Sharding (Java) — Distribute aggregates (actors) across several nodes

    in the cluster — Interact with aggregates using their logical identifier — Not care about their physical location in the cluster public CompletionStage updateCartItems(String userId, List<CartItem> cartItems) { return PatternsCS.ask( shardRegion, new UpdateCart(userId, cartItems), timeout); }
  34. None
  35. Persistent Cart Actor (Java) @Override public Receive createReceive() { return

    receiveBuilder() .match(UpdateCart.class, msg -> { persist(msg, (UpdateCart m) -> { // apply the command setCartItems(m.getCartItems()); // tell the sender we're successful sender().tell("done", null); // TODO, emit an event to Kafka? }); }) .matchEquals(ReceiveTimeout.getInstance(), msg -> passivate()) .build(); }
  36. Modernization pa!erns

  37. Onion architecture Onion architecture fits DDD perfectly. — Infrastructure →

    health checks, tracing, auth — API → routing, validations — Domain → bounded context — Core → aggregates
  38. Play structure Onion architecture lends well to Play package structures.

    !"" controllers !"" domain | !"" cart # | !"" api # | $"" core | !"" order # | !"" api # | $"" core | $"" product # !"" api # $"" core $"" infrastructure
  39. Anti-corruption layer

  40. Decompose without destroying — The legacy system is never modified

    — Transaction scripts can be thousands of lines long and have numerous side effects! — Our worst case scenario with this approach is that we revert to an unmodified, still working legacy system
  41. Strangler pa!ern Named after the strangler vine that grows upward

    and around existing trees, “replacing” them. Goals: — Replace legacy functionality with the target system — Implement new functionality without modifying the existing system
  42. None
  43. None
  44. None
  45. From Monolith to Microservices !"" domain !"" product #"" api

    | #"" Price.java | #"" Product.java | !"" ProductService.java !"" core !"" ProductServiceImpl.java
  46. What is Cloud Native? The Cloud Native Computing Foundation defines

    cloud native systems as: 1. Container packaged 2. Dynamically managed 3. Microservices oriented
  47. Container packaged

  48. Dynamically managed

  49. Microservices oriented

  50. Conclusion

  51. Business Value — Revisit prior assumptions through event storming —

    Transition to a target system without modifying your existing system — Gain cloud readiness incrementally — Get the most out of microservices (as a refactoring pattern) — Break the chains of the past
  52. Migrating Java to the Cloud Stop by the RedElastic booth

    for a free copy of our latest book from O'Reilly. — kevin.webber@redelastic.com — Twitter: @kvnwbbr — redelastic.com