Domain-Driven JavaScript Development

12,837 views

Published on

We are building more and more complex applications on the front-end of the web stack. We've done a good job of bringing engineering rigor to JavaScript development, but we can do more. We need overall architectural design for our complex applications. Domain-Driven Design offers us a way of approaching software design on the front-end. We walk through the process of setting up a small domain-driven application in Backbone.js.

Published in: Technology
0 Comments
25 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
12,837
On SlideShare
0
From Embeds
0
Number of Embeds
110
Actions
Shares
0
Downloads
76
Comments
0
Likes
25
Embeds 0
No embeds

No notes for slide
  • Today we will discuss Domain-Driven JavaScript Development. But, before we get into what that means, let’s take a quick look at this picture, because I think it provides a useful allegory for software development. If you look off in the distance of the center of the photograph, you’ll see a just-launched ship sailing away. And here at the top, you’ll notice a crane bringing in the first beam that will form the keel of a new ship to be constructed in the same drydock that just launched the previous ship. In the same way, projects never stop coming for us. We launch a project, and while it’s still in sight, we start the next. We need an architectural framework to manage the constant turnover of projects so that we don’t build sinking ships.
  • So who am I? I’m a specialist in interactive development at Sapient Global Markets. We provide business and technology services for major players in capital and commodity markets. As part of the visualization practice, we’re responsible for building large-scale business-critical web applications for our clients. Something like a trading platform for mutual fund portfolio managers or an application that helps an energy company manage the flow of resources throughout their system. Applications that have historically been built in Java or something similar and applications that CANNOT FAIL.
  • So in the spirit of building applications that can’t fail… if we look at the last few years, we’ve come a long way in bringing engineering rigor to the client side – particularly in referring to JavaScript. We’ve implemented asset and dependency management, patterns, static code analysis, testing, building…
  • So why do so many applications still look like piles of coat hangers when we’re done with them? Well-modularized piles of coat hangers, but piles of coat hangers nonetheless.
  • What we still need is an overall architectural design for our complex applications.
  • Enter: Domain-Driven Design This book, which came out in 2004, defined an approach to software development that had been maturing for quite a long time. You might imagine a book on software architecture to be a pretty exhausting read, but I found it to be very engaging. Highly recommended. The first thirdof the book talks about the theory and basic implementation of domain-driven design, which is what we’ll cover today The latter half of the book covers refactoring the application and some general software development best practices that are useful for any project.
  • So what is Domain-Driven Design? Let’s start by defining “Domain.” The domain is the subject of the program. We can also call it the “business” of the software. For example…
  • For complex projects, primary focus should be on the domain and domain logic Domain-Driven Design offers a collection of principles, techniques, and best practices to help us manage these complex projects
  • So what if you’re software isn’t complex? In that case, you probably don’t have the luxury of time, budget, or even team expertise to implement a robust domain-driven application. Even Eric Evans isn’t dogmatic about using Domain-Driven Design. In his book, he suggests…
  • In short: Just get the job done. Who cares what it looks like?
  • So in Domain-Driven Design, we’re focused on managing COMPLEX software. Complex designs should be based on some sort of model
  • This domain model is the image of the business in the head of an expert. This initial model has NOTHING TO DO with the software. It forms the backbone of language used by all team members In much the same way an economist will attempt to model an abstracted version of a real-world system with mathematics, we need to use software to represent an abstracted model of the domain. Model and implementation shape each other iteratively
  • Alright, so given these basics, let’s build an application using Domain-Driven Design
  • This is a screen shot of an example trading application we want to build. Bullsfirst is an open-source proof-of-concept project that we use to test out a variety of application technologies.
  • We use it to test both front-end client technologies and middle-tier solutions. We find it to be a bit more robust and grueling test than your typical todo list. On the front-end, we’ve built sample implementations in iOS, Silverlight, ExtJS, and now Backbone. I know this is the Backbone meetup, but I would love to see implementations in Angular or Ember if anybody’s feeling chippy.
  • But you can see this is the type of application we’re trying to build. It’s got a good bit of interaction, and there’s a very sophisticated domain model behind all of this data. So how do we go about building this?
  • The first thing we want to do is figure out our framework. We want a framework that will support our Domain-Driven ambition as much as possible. This includes staying out of our way when we need it to.
  • So, it probably comes as no surprise to anyone in this room that we chose Backbone, and I think Jeremy summed it up perfectly in his blog post announcing Backbone 1.0 last week. In our line of building complex, customized, data-driven applications, the importance of this cannot be overstated. Maybe it’s just me, but every time I’ve built even a moderately-complex application with a more “opinionated” framework, I find at least one situation where I need to override some default behavior, and it takes at least ten times longer than it should to do so. Backbone doesn’t have this flaw, and I love it for that.
  • But in giving us this freedom, Backbone leaves quite a bit up to the developer. So what we’ve done is create a semi-opinionated framework for ourselves. There’s really nothing groundbreaking here, but it gives us a base to start from, and gives us what we think are some sensible default behaviors.
  • The framework is set up so that everything in the UI can be thought of as a component. We have page-level components that themselves have child components that may be tabs or widgets, but they all follow this same pattern. The View is the Backbone View, the template is an underscore or Handlebars or whatever kind of template, and the ViewModel is a Backbone Model that we use as an adapter in case the data we get directly from the domain model isn’t quite in the format we need.
  • Because all of our views are built off of our BaseView with its child management methods, we can nest views within views within views ad infinitum.
  • So now that we have our framework squared away, let’s talk about the process of starting to think about and build a domain-driven application.
  • The first and most important step in this process is the discovery phase. In this phase, we consult with the business experts to start to piece together the domain model, which again, is just the idea in the experts’ heads. In this, we start to compile what is known as an ubiquitous language
  • Well, what’s this ubiquitous language? We want every person who touches this project, from the client to the business analyst to the project manager to all of the developers to speak the same language. Instead of trying to explain things in our lingo having to do with design patterns and databases and such, we instead rigorously define terms as the client understands them. We then don’t have to translate anything between the client and the developers, we’re all speaking the same language.
  • So here’s an example in this application of finding this ubiquitous language. Of course we wouldn’t have an application to look at necessarily, but this just illustrates the concept.
  • So the developer has a good basic understanding of the domain, but we continue to iterate on both the domain model and the ubiquitous language. Here, the developer is recapping their understanding of the domain model.
  • But it turns out that the domain expert actually thinks of this a bit differently.
  • So instead of horseshoeing this new information into our existing implementation, we’re going to take time to incorporate this new concept properly into both our mental model AND our software model.
  • The domain model (and therefore the software implementation of that model) will continue to change throughout the project. Better abstractions, epiphanies, and clarifications will cause us to continuously perfect our understanding and implementation of the model. The question comes up: does this require an agile methodology? Not necessarily, if you are still willing to iteratively perfect the domain model, but you can maybe see how an agile methodology would not only accommodate, but encourage this iterative process. But how do we iteratively change this model, which is central to the rest of our application, without breaking everything else? That brings us to the next step in our process.
  • We need to isolate the domain. We can conceptualize our application as different loosely-coupled layers. At the bottom, we have our infrastructure, which is all of our supporting framework, repositories, et cetera. Above that, we have the software implementation of our domain model. This is separated away from the rest of our application in order to preserve data integrity. Next, we have our application layer, which makes our specific appllication hum along. And above that, we have our UI layer, which in our situation will be made up entirely of Backbone Views. To preserve loose-coupling in this architecture, the levels above are allowed – but not encouraged – to have direct reference to the levels below, but going up the stack, we only want to communicate via events. And if you think about this, it doesn’t make sense for the domain model to know what kind of application is being built on top of it, or for the application to know the exact state of every view. These layers only need to fire events when they change and allow the layers above to respond however they like.
  • The first step in expressing the domain model in our software is to distinguish between entities, value objects, and services. Entities are objects that have identity – if we need to keep track of a particular instance of an object, it is an entity, and we need to treat it in a special way. Value objects are objects that do not have identity. They are mainly used as a representation of attributes – they are commodity objects. Examples would be seats on a Southwest Airlines flight. On most airlines, a seat is an entity – a particular seat is in a particular spot in an aircraft and seats a particular person. But on Southwest, there is no assigned seating, so the seat is just an object with the attribute of being able to hold a person. There is no need to distinguish between separate seats. And finally, services are the parts of the domain model that aren’t really objects – they are more actions. For example, in Bullsfirst, we have an Instrument Service that goes out and gets the current prices of all of the stocks in our system. Once we’ve distinguished the component parts of our domain model, we need to set aggregate boundaries and implement resources and factories.
  • When external objects in our UI or application layer can modify all parts of our domain model willy-nilly, it becomes impossible to maintain data integrity. Instead, we define aggregates based on closely-related objects in our domain model. External objects can then only reference the aggregate root, which must be an entity (it has identity). This root controls access, and enforces business rules within the aggregate, which can contain either entities or value objects.
  • In Backbone, dealing with the data store involves invoking the Model or Collection’s own fetch() method. In Bullsfirst, in theory, our data could quickly become stale, so we aren’t currently caching most (if any) of our data requests.
  • The Repository returns data, but the factory creates new objects out of whole cloth. Tying the responsibility of creating and validating objects to either the domain or the application can be really kludgy, so we generally want to avoid that. However, Backbone takes care of a lot of that for us between Collection.add() and Model.validate(), so in the spirit of not fighting against our framework, we’ll take that help. Thanks, Backbone!
  • So this all just scratches the surface of building a domain-driven application on the front-end, and I haven’t shown much code. Domain-Driven Design, and I’d argue architecting any complex piece of software, comes down more to how we think about and approach the problem than how we code it. When you come across what seems to be a fairly complex software problem, DON’T START CODING. Take a cue from this kid and think about it for a while. Sit on your hands if you have to. Sometimes I do. I’m Bob Holt. Thank you for listening.
  • I have a few resources here for those who are interested. I will post these slides on the Meetup event page within the next 24 hours. And now I’ll open up the floor for comments and questions.
  • Domain-Driven JavaScript Development

    1. 1. http://www.flickr.com/photos/lac-bac/4678565737/
    2. 2. Bob HoltSpecialist, Interactive Development Sapient Global Markets Visualization Practice @bobholt github.com/bobholt
    3. 3. • Asset Management • Linting• Design Patterns • Testing• Modularization • Build Process
    4. 4. http://www.flickr.com/photos/sidelong/6433552779/
    5. 5. http://en.wikipedia.org/wiki/File:Joy_Oil_gas_station_blueprints.jpg
    6. 6. DomainThe subject of the programExamples:•Airline booking program: People getting on aircraft•Stock Trading program: Securities and exchanges
    7. 7. Domain-Driven DesignManage complex software by placing primaryfocus on the domain.•Principles•Techniques•Practices
    8. 8. What if my software isn’t complex?“Put all the business logic into the user interface.[…] Use the most automated UI building and visualprogramming tools available.” -Eric Evans
    9. 9. http://www.flickr.com/photos/sinamigos/7509698756/
    10. 10. Domain-Driven DesignManage complex software by placing primaryfocus on the domain.•Principles•Techniques•Practices
    11. 11. Domain Model• Abstraction of the knowledge in a domain expert’s head• Intimately linked with the software implementation• If a domain model cannot be understood by sophisticated domain experts, then there is something wrong with the model.
    12. 12. Building a Domain-DrivenApplication
    13. 13. https://github.com/archfirst/bullsfirst-jquery-backbone
    14. 14. https://github.com/archfirst/bullsfirst-jquery-backbone
    15. 15. Building a Domain-Driven ApplicationThe Framework
    16. 16. Backbone.jsIn an ecosystem where overarching, decides-everything-for-you frameworks arecommonplace, and many libraries require yoursite to be restructured to suit their look, feel,and default behavior — Backbone shouldcontinue to be a tool that gives you the freedomto design the full experience of your webapplication. - Jeremy Ashkenas
    17. 17. Keel• Lightweight framework around Backbone.js• About patterns and practices, not fancy code• 5 Files: BaseView, ExceptionUtil, Message, MessageBus, Router https://github.com/archfirst/keel
    18. 18. Pattern• Component – View – Template – ViewModel
    19. 19. https://commons.wikimedia.org/wiki/File:Russian-Matroshka_no_bg.jpg
    20. 20. Building a Domain-Driven ApplicationThe Process
    21. 21. Discovery• Begin constructing the domain model• Develop an ubiquitous language
    22. 22. Ubiquitous Language• Concept shared with Behavior-Driven Development• Defined terminology that is shared between all members of the team• Used in all code and written and verbal communication
    23. 23. Building the domain model and ubiquitouslanguage is an iterative process
    24. 24. Isolate the Domain
    25. 25. Express the Model in Software• Distinguish Entities, Value Objects, and Services• Set Aggregate Boundaries• Implement Repositories and Factories
    26. 26. Set Aggregate Boundaries Brokerage Account Orders Positions Lots Transactions
    27. 27. Repositories• Global interface• Provides illusion of in-memory collection of all objects• Deals with the data store• Caches as necessary
    28. 28. Factories• Take on the responsibility of creating new objects• Tying to domain or application can be ungainly• However, Backbone has Collection.add and Model.validate methods that can take care of this for us
    29. 29. http://commons.wikimedia.org/wiki/File:Deep_in_thought.jpg
    30. 30. Resources• Domain-Driven Design – Domain-Driven Design: Tackling Complexity in the Heart of Software – Eric Evans – Domain Driven Design Quickly – InfoQ – Domain-Driven Design – Nettuts+• Keel.js – Keel – GitHub – Bullsfirst – GitHub – Archfirst Project

    ×