List

Domain Driven Design and Hexagonal Architecture with Rails

Domain Driven Design and Hexagonal Architecture with Rails

by Eric Roberts and Declan Whelan

The video titled "Domain Driven Design and Hexagonal Architecture with Rails" features Eric Roberts and Declan Whelan discussing how to effectively apply design patterns in Rails applications to avoid common pitfalls like the "fat model, skinny controller" problem.

Key Points Discussed:

  • Introduction of Speakers: Both speakers share their backgrounds, emphasizing their passion for coding and maintainable software. Declan, the CTO at Printchomp, describes his journey in adopting Ruby on Rails despite initially lacking expertise in the language, while Eric, a software developer at Boltmade, highlights his transition from front-end to back-end development.

  • Challenges in Rails Development: They discuss the typical structure of Rails applications, where the responsibilities of controllers, models, and views often become blurred, leading to complex and unmanageable code. They showcase an example of a 90-line method that encapsulates too much functionality, indicating the need for better organization.

  • Domain Driven Design (DDD): Emphasizing the importance of understanding the domain of the application, the speakers explain DDD as a way of tackling complexity by creating a common language between domain experts and developers. They discuss using classes named after domain concepts such as "Customer" and "Product" to enhance clarity and reduce miscommunication.

  • Hexagonal Architecture: They introduce hexagonal architecture as a means to structure applications with a strong focus on domain logic. Layers like application-level code and various adapters connect to this core domain, emphasizing that different concerns (like database operations) should reside separately from business logic to promote more manageable codebases.

  • Practical Patterns:

    • Form Objects: Presented as an approach for handling complex form submissions where multiple models are involved, aiding clarity in controllers.
    • Request Objects: Discussed as a method for encapsulating request data and validations at the boundary of the system, helping to streamline controller logic.
    • Service Objects: Introduced to handle business logic cleanly, allowing controllers to delegate responsibilities effectively.

Conclusions and Takeaways:

  • The speakers conclude by emphasizing the fun in understanding and improving complex systems through experimentation and breaking responsibilities into smaller parts.
  • They stress the need for Rails developers to look beyond their framework and familiarize themselves with broader software design principles that can be applied across different languages and platforms.

The presentation encourages developers to adopt best practices in software design to create more maintainable and extensible applications while recognizing the inherent complexities in software development.

By Eric Roberts and Declan Whelan

You know that Domain Driven Design, Hexagonal Architecture, and the Single Responsibility Principle are important but it's hard to know how to best apply them to Rails applications. Following the path of least-resistance will get you in trouble. In this session you will learn a way out of the "fat model, skinny controller" hell. You will leave with a roadmap to guide your design based on concepts from Domain Driven Design and Hexagonal Architecture.

Declan loves to code and help others get joy from their code. When not coding he is the CTO at Printchomp, an agile coach at Leanintuit and an Agile Alliance Board Member.

Eric Roberts is a software developer at Boltmade and co-founder at 20Skaters. He is enthusiastic about creating maintainable software.

Help us caption & translate this video!

http://amara.org/v/FG1q/

RailsConf 2014

00:00:17.520 all right hi I'm uh Eric Roberts and I'm here to talk to you all about how you can use software design patterns to put
00:00:23.480 your rails app on a diet and make your test run really really
00:00:28.960 fast
00:00:36.040 uh Jokes Aside we will be telling you about some design patterns uh not so much making your test run fast um but
00:00:42.800 we're here to talk about domain driven design hexagonal architecture and rails I'm Eric Roberts I'm a software
00:00:48.039 developer and I work at a company in waterl Ontario Canada uh called bolt made um I met Dean when we worked
00:00:56.079 together at prom before that I was a frontend developer for a number of years and I'd worked around rails applications
00:01:03.600 but mostly at the view layer until Dean dragged me Kicking and Screaming into backend development and made me care
00:01:10.320 about stuff like we're talking about today and uh this is the biggest crowd
00:01:15.479 I've ever presented in front of so if you'll excuse me I need to take a picture and email my
00:01:22.720 mom okay um hi everybody uh real pleasure to be here my name is Dean um
00:01:28.360 I'm the co-founder of a company called print Chomp and um my story is about two
00:01:33.520 years ago we had an opportunity to launch print Chomp and I was looking at Technologies and I decided that Ruby on
00:01:40.040 Rails was really the best platform for us uh the only challenge was that um neither me nor anybody on my team new
00:01:46.920 Ruby nor rails so it was a kind of a brave maybe decision um but it's one I
00:01:52.880 that I don't regret and one of the things that Drew me to the community was the fact that um into the platform was
00:01:58.880 the community um around uh sharing around the openness of of of of sharing
00:02:05.840 code and also a lot about about the test Focus which has been pretty important to
00:02:11.319 me but the cool part I think about it was we intentionally took on a lot of technical debt because I knew that um I
00:02:18.200 knew that I would not know enough about our domain it was a new domain for me Printing and I also did not know enough about Ruby I did not know about enough
00:02:25.239 about rails so very intentionally decided to do what best the best that we
00:02:30.400 could knowing that we would end up very likely with a pretty heaping amount of technical debt and um that turned out to
00:02:37.200 be true and um has anyone had that experience I don't know yeah so um but
00:02:43.879 recently we had an opportunity to build an API and that was really exciting for me and I know there going to be some other talks about apis here later and I
00:02:50.879 realized that I had I had two kind of competing things that could come together the first was I
00:02:56.840 had I had logic in our application that I needed to share in our API how was I
00:03:01.920 going to do that and um all of our code was sprinkled through various bits of
00:03:07.799 our controller and model logic secondly I wanted a mechanism to to have a strategy for eliminating the te uh the
00:03:14.799 technical debt and what I turned to was domain driven design and hexagonal architectures and I want to share what
00:03:22.319 we've learned along the way of doing that and and where we're going so I I hope you're able to uh learn something
00:03:27.959 from what we've done and uh yeah that's great Dean but what are they going to get out of it here's a good idea have a
00:03:36.000 point it makes it so much more interesting for The Listener well that was from Sandy Mets
00:03:43.120 she said you know if you're going to have a talk you should really have a point and I think Steve Martin said it pretty funnily and I guess our number
00:03:50.560 one point is that there is complexity in the software that we build there's complexi in the problems that we're
00:03:56.519 solving and we need to embrace that complexity and embrace it in such a way that we tackle it and deal with it and
00:04:02.400 deal with it head on and uh by doing that then we end up having more joy and
00:04:07.480 fun in our work because it's not just about getting this functional piece to work it's about really trying to understand our domain and model it and
00:04:14.480 express that in our code and make our code AS expressive as possible and the second thing that I really realized was
00:04:21.880 I knew that our code was a mess and I knew some point refactorings that we could do but I didn't know how to how to
00:04:28.440 you know what did what did the look like if it was refactored significantly what would it look like what would the shape
00:04:34.360 be look like what would the name spaces be what would the classes be doing Etc and um domain driven design and
00:04:41.160 hexagonal architecture helped me Envision and share with my team what it might look like the third thing that that that we
00:04:49.440 would like you to take away from this talk is that there's a lot more to just being a rails developer the the ideas
00:04:57.160 and patterns if you will that we that we're talking about are some of them have been written by some of the people
00:05:03.160 that uh dhh had in his slideback including James copain but a lot of
00:05:08.479 those patterns have been around for a long time so those patterns and those ideas and those practices will serve you
00:05:14.880 well beyond rails they would work in a node application they could work in a desktop application they can work in a a
00:05:21.240 wide variety of areas so by getting some familiarity with these Concepts you're able to transfer those skills to things
00:05:28.039 Beyond rails and um so I want to ask Eric just to walk us through kind of
00:05:34.000 some of the some of the pain that we had with our initial rails development and see if it resonates with
00:05:39.199 you all right so everyone knows what this is It's a rails folder structure uh
00:05:46.759 and it's really great when you get started with rails you have these folders okay I'm I logically My Things
00:05:52.919 fall into these areas controllers models and Views are really what we're focusing on right now um but if the
00:05:59.520 responsibility of your code doesn't start with m v or uh C what do you do
00:06:05.160 then uh and and we found it kind of goes like this you have you have these areas of responsibility and you have something
00:06:12.199 that doesn't really fit and you don't know where it goes so you just put it on somewhere and things get a little bigger
00:06:17.680 uh and continuing on you keep doing this things get bigger and finally like the line between all of these things is is
00:06:24.639 blurred you don't know what's what it's hard to extract uh reusable parts from all of this because the the
00:06:30.639 responsibilities are split across all these things and you kind of end up with methods like this uh this is one method
00:06:37.080 it starts on the left and ends on the right it's about 90 lines um it's not from print Chomp it's
00:06:44.599 from another another project that I've worked on and it's about setting uh it doesn't really matter what it does the
00:06:50.520 point is it's ugly and you know it is actually about setting prices on
00:06:56.360 properties and the the date ranges that are available so I have a question uh we
00:07:01.919 need to add sales tax to the prices anybody care to take on that
00:07:08.280 refactoring um it's pretty horrible but nobody nobody sits down and says I'm going to write a 90 line method today
00:07:14.240 that does uh property prices and with date ranges the initial spec was
00:07:20.160 probably something a lot simpler uh and because it's in that spot now the next person who comes comes and looks at that
00:07:26.599 method and goes oh okay well if I just type this a little bit more it'll it'll do that now and this was a little bit of
00:07:33.400 a train wreck at some point probably the people working on this including myself probably should have realized you know
00:07:39.400 45 lines might have been the time to split it up maybe 20 maybe less um but
00:07:45.960 this is nonetheless what we ended up with or you end up with rubbe Goldberg machines uh for sharpening pencils so
00:07:53.960 there's a lot of well-known patterns that can help you out with this uh has anyone read this blog post
00:08:00.639 yeah yeah anybody use any of the patterns in them yeah yeah they're pretty great right uh we use a lot of
00:08:07.440 them and I'm we're going to tell you about some of them uh here but the one thing you've so you've extracted all of
00:08:14.199 these things into small responsibilities your models your controllers and your views they're all small again but okay
00:08:20.919 so what I have a bunch of little objects that all go they all know too much about each other they don't fit into any
00:08:27.840 logical structure they don't how does this all fit together you've made a like an awesome first step
00:08:34.880 in that you have small little pieces that you can use but where do you go from there uh and we think that looks
00:08:41.200 kind of like this um we think that your domain uh Concepts
00:08:47.839 Services entities should be in the middle and everything else is outside your your database is a an extra concern
00:08:55.519 your views are an extra concern the web uh you know when you're designing API API as Dean talked about a little bit
00:09:02.000 it's an extra concern so you can really focus in on the middle and what your application actually does and I'm going
00:09:07.040 to let Dean talk a little bit more about that domain music has anyone he heard of domain driven design oh quite a few
00:09:14.120 people awesome how many people have actually uh you know intentionally used it and and and have worked with it so a
00:09:21.519 number so cool and it can be quite it can be quite um it can be quite daunting
00:09:27.200 if you and uh this book by Eric Evans is kind of what kicked it off and this book was I think written in 2005 and it is a
00:09:34.560 really really great book but it is actually quite difficult to read but uh it's I think it might be the only
00:09:40.480 technical book I've read twice and that's partly because it was really good and partly because it's was rather
00:09:46.320 difficult to get through some of it did anyone else read this book and have a similar experience like it's really
00:09:51.440 great stuff and you kind of read it and you go wow what does that mean to me right um and we at the end at the end of
00:09:57.560 we we'll be posting Our Deck and we'll have some references to other material that that I've actually found to be a bit more uh uh addressable or a little
00:10:05.000 more consumable um but what Eric Evans talked about was really tackling complexity and um and he talks about the
00:10:13.000 you know the critical complexity is is really understanding the domain what are
00:10:18.279 the business rules that take place inside our systems if we're going to add sales tax what are the business rules
00:10:24.279 for that sales tax what are the what are the rules around who can buy what and by putting those inside and thinking them
00:10:31.240 as the domain of our system then we're able to have our outside layers just be
00:10:37.959 um um if you will relatively thin facades which allows allows us to reuse
00:10:43.480 that logic across apis across other applications we don't have to duplicate all of those business rules and the way
00:10:51.000 that he proposes to do that is through ubiquitous language and uh this is a picture of the
00:10:56.639 Tower of Babel and if anybody knows this story it's where everyone in the world was speaking a different language and I
00:11:03.760 I once worked on a on a project that was a financial transaction processing system and when I inherited it the guy
00:11:11.720 who was preceded me had this was a model train afficianado so he had the idea of
00:11:16.839 model trains so every transaction was like a car and and and the payment
00:11:22.160 engines were were were uh train tracks and he had all of these metaphors around transaction processing and trains and
00:11:28.639 was written WR in Java so when I was asked to add a new feature fix a bug I had to understand the business domain
00:11:34.920 and then I had to kind of understand how did that translate into train speak and then I had to go look at the Java code
00:11:41.000 to figure it all out right so the coding was easy the the hard part was really trying to understand what was being
00:11:47.519 asked and how did the Code Express that right and that's what Eric Evans is talking about with ubiquitous language
00:11:53.240 we want to have the language that we speak with domain experts should be readable in the code if if I'm order if
00:12:00.600 I'm a customer and I can purchase a product there should be a class called customer there should be a class called
00:12:06.600 Product and there should be a verb in there that's somewhere that says purchase Etc so that there's minimal
00:12:12.240 translation between the domain experts language and the language that my code is written and Ruby gives us a great
00:12:18.079 opportunity to do that that is much more difficult um in in in other more statically typed
00:12:24.320 languages um so that's kind of the the key thing to take away from domain driven design is to try to have
00:12:31.440 your your Concepts expressed in code that are meaningful in the words people use if they use the word customer you
00:12:38.279 should have a customer class if they use the word user you should have a user class Etc um but beyond that he also has
00:12:45.199 some kind of key I I I dare not say it patterns I'm almost nervous now to say
00:12:54.440 it but let me be clear this isn't science
00:13:01.680 it's not right because these patterns were not dreamed up in Academia Ivory
00:13:07.320 Towers these patterns that we talk about were empirically derived from people
00:13:14.160 intentionally doing what we do which is right code every day intentionally thinking about how does that how does
00:13:20.079 how do those things fit together and what is the essence of what I'm doing and can I extract that into words that I
00:13:25.760 can use to communicate with other people the beauty patterns is I can talk about a value object and if you know what a
00:13:32.560 value object is and I know what a value object is we can have a much richer conversation then oh I have to have an
00:13:38.720 object whose state is whose identity is defined by the state of its attributes and that you know we we have a much
00:13:44.519 richer conversation you might say ubiquitous language yeah so we're going
00:13:49.680 to touch a little bit on some of these patterns but uh but the idea is that these are
00:13:55.440 not academic Ivory Tower Concepts ceps these are empirically driven from people
00:14:00.759 whove worked in the field and if we're going to if we're going to be successful as an organization while I fully agree
00:14:06.360 that we need to go out and write code and we need to read code I totally think that's true but we also have to have
00:14:12.000 more effective ways of communicating knowledge so that we're not all learning the same things from each other over and
00:14:17.519 over we can learn more easily from each other and that's what these patterns are and
00:14:24.040 um the next kind of piece that we're going to talk about is hexagonal architecture and it's more than just
00:14:30.199 that and I think we've alluded it uh to a little bit it's really the idea of
00:14:35.480 you're going to have this core domain in the middle and
00:14:40.560 um in inside your core surrounding your outside core are going to be some
00:14:46.000 application Level uh code that expresses the rules of your application and I would draw it slightly differently
00:14:51.959 perhaps but on the and then we have adapters on the outside that adapt that code to uh web calls or database calls
00:14:58.040 or smt TP or in my case apis and um so that's the way that we
00:15:03.639 want you to that's the way that we are starting to approach the work at PR Chomp is thinking about it in in those
00:15:08.720 constructs and now we want to jump to some specific uh patterns and and show you some real code that actually you
00:15:15.320 know brings these to life so Eric you want to talk about the form object sure uh unfortunately I can't tell you what
00:15:21.600 your domain is or necessarily what goes in the middle of that hexagon but I can give you some ways to keep other things
00:15:28.920 of that hexagon that you don't need to be concerned with um one thing that I've been doing lately is a form object uh
00:15:35.480 one of the really cool things you know if you run rails scaffold some model name you get a form that you submit
00:15:42.199 creates the record edits the record um and that's pretty great but how do you
00:15:47.600 do that when you don't have a direct onetoone mapping with an active model record uh so instead of instantiating an
00:15:54.440 active model record uh I've taken to instantiating I'm going to call it a form object there's a lot of names for a
00:16:01.399 lot of different things but this is this is what I've been calling it uh so here's the actual thing that I was
00:16:06.680 building uh on the left hand side you see that you select a ticket price on the right hand side your name email
00:16:12.560 address and your payment details um and this is actually two active record
00:16:17.959 models in my database um the the passengers over there on the right you can add a passenger and keep adding it
00:16:25.079 um and if you've ever worked with nested attributes probably know it's not always that fun um so this is not using nested
00:16:32.079 attributes uh it's done like this uh I have a class ticket form that includes
00:16:37.680 active model model which is how I get nice things like that magic initialize method and uh validators um and the
00:16:45.800 passengers method if I don't have any returns me a passenger new that's how it puts the name and email address for that
00:16:51.360 first passenger uh and then tickets I get out of this by taking my passengers and uh mapping them into new objects uh
00:16:59.160 in the controller it looks a little bit like this so you just pass your pams off
00:17:04.240 into that you get it back out and you have tickets and so instead of if ticket. saave uh I do if ticket form
00:17:12.039 valid and ticket charger charges successfully then we've had successful and ticket charger takes care of saving
00:17:18.400 my tickets and knowing that there was because there's only one charge for all the tickets right you're paying all at
00:17:23.480 once no point to split that out um so that's a really useful thing that I've
00:17:28.760 to to help when my mappings aren't just totally I don't want to just take a record out of the database put it in or
00:17:34.520 update it uh and now de's going to tell you a little bit about request objects yeah I'm just curious Has anyone used a
00:17:40.280 form object or something like that so quite a few people cool has has anyone done use something called the request
00:17:47.919 object sort of I was hoping that I invented this so maybe I haven't I don't know okay but uh request object is now
00:17:55.400 in you know think of an API is we're trying to have similar Behavior to the uh form object except we're trying to
00:18:02.919 take the remember we're trying to take complexity out of our controllers and out of our models and put them into more uh uh to simplify our systems so the
00:18:11.640 idea with the request object is that we're going to pull that code out and put it into the into the
00:18:16.720 controller and now the request object is going to receive uh the request and the code looks sort of like this right
00:18:23.280 there's um i' I've done this slightly differently than ERX ERX way in terms of of of the kind of the core of the class
00:18:29.320 the core of this class is using a gem called verice uh which does something similar to um active uh model model
00:18:37.440 except this allows you basally have a plain old Ruby object and the way and the cool part is that or I I think it's
00:18:44.799 cool is you you can you can declare attributes like this so I have actually in my domain layer I have something
00:18:50.360 called a customer and a billing and a shipping and if if somebody supplies me those three things then I can complete
00:18:56.559 an order in my system um we've there are a couple of pieces missing here but we wanted to keep it
00:19:02.720 fitted on a slide but that's basically it and um and we have the validation and the cool part about this is that um when
00:19:10.520 a request comes in we just I just put in a before Loop in the in the controller that has a before filter that just
00:19:17.039 basically instantiates the request object using some um um some reflection
00:19:23.000 to figure out what is the you know which is what is the controller and what is the um Act being asked inferring the
00:19:29.720 request class instantiating it and then just passing it what used to be the pams hash but now it's actually a rich object
00:19:36.919 that I can have validations on Etc so the net effect of this is that um why would I bother doing this right well now
00:19:44.200 the control the you know the complexity around validating the request is at the boundary of my system that doesn't need
00:19:50.039 to leak in to the rest of my system um it's almost like you know does anybody
00:19:56.320 use you know at the beginning of your methods you want want to put the guard Clauses to catch the exceptions coming at the beginning of your method so the
00:20:02.240 rest of your method is simpler this is doing the same thing except it's doing it at at a higher level abstraction at
00:20:07.640 the API request level and and this has worked out really well for us so I quite like that
00:20:12.799 one um yeah great uh service objects are another one uh that we've been using I
00:20:19.240 think dhh actually had one in his presentation I'll give you a hint he didn't like it
00:20:26.159 um he used one it's something instantiated by the controller uh we've been looking at controllers as a little
00:20:32.280 bit of just like a okay I've received this thing pass it off to somebody else and then do something with the result um
00:20:38.840 so we want to keep out that procedural code from our controllers and service objects are one way you can do that uh
00:20:45.039 using a order service to create orders we've encapsulated all of the logic about how to create an order um in this
00:20:53.799 one area so if you want to you could use it from somewhere else right you don't have to hit a control roller action to
00:20:59.000 create an order um it's reusable and extendable um and it has Dean's magic
00:21:05.360 repository object in there that we'll get to in a bit um and the controller
00:21:11.039 again just it's very simple do this thing do on success do this on failure
00:21:17.200 do this uh so those are a few of the patterns that we've been using um to help us with this um so now what um
00:21:29.039 what's what's the elephant in the room
00:21:40.159 anybody how do you get them into rails yeah yeah well that's the one we were
00:21:47.279 thinking of that's active record yeah I mean I mean the and and how you get into rails yes there are some interesting uh
00:21:54.240 challenges around that but I'm going to flip you back to the architecture slide and just point out that you see what's
00:22:00.279 happened here is that the that we're trying to view the the the application pieces of our solution here being really
00:22:06.200 on the perimeter of our core system and the core system composed of services that may be uh servicing API or
00:22:13.360 application requests um we have some services that may be invariant across any call and
00:22:19.960 those would be at the very center and we have things called entities which are on the inside and the key part that's we
00:22:26.400 haven't talked about which which actually I'm finding the most difficult part in this is is this repository which
00:22:32.200 is the bottom which is the r in the bottom right hand corner and its job is to talk to the active record model which
00:22:38.039 is in the green and create an entity object which is the blue object and and how does that actually work so um I'm
00:22:45.880 going to show you a bit of code and uh this is this is um this is the first time I've shown my Ruby code in public
00:22:51.279 so please be kind and there are probably way better ways to do this but this is the
00:22:56.640 repository that I've I've there are some other methods here but I just wanted to fit on what hap you know show you um the
00:23:03.120 simple one so this is what a save looks like so the save takes a domain object and it converts it through something
00:23:09.320 called a mapper which maps The Domain object onto a uh active record object
00:23:14.919 which is called a record here then it then it calls uh record. saave assigns
00:23:20.000 the ID and Returns the response so that's pretty straightforward all that's really happened is and I've really tried
00:23:25.640 to do this and so far I've been able to I want to have domain. saave I want to have repository. saave domain so that
00:23:32.960 there's no persistence that's leaking into my uh domain objects persistence I want to be a secondary concern to what
00:23:40.200 that object is really doing and so far it's worked although sometimes it's cause me some difficulty um the method
00:23:47.200 missing down there is kind of cool um at least I think it's cool and uh what it's
00:23:52.640 doing is it's introducing a scope object which I'll show you in a well here's a scope object that's okay and it creates
00:23:58.200 a scope object and this was the trickiest code that I had to write but what it does what it the end result of
00:24:03.960 this code is that it allows you to chain call any of your active record find
00:24:09.760 methods or your Scopes and chain them together so you can now use so another words with this logic wherever you had
00:24:16.520 like uh active record dot uh you know find where ID greater than 122 is
00:24:23.640 activated and so on wherever you might have a chain like that you can still use that chain now because of this scope class with your domain objects except
00:24:30.720 instead of getting back your active record object you're getting back its domain representation does that make
00:24:36.799 sense yeah okay and then the mapper is what Maps them across right and some
00:24:42.720 cases the mapping is like really really simple what's the next slide here yeah
00:24:48.559 yeah there it is right there so the mapper because of the way verus works and the way uh active record works with
00:24:53.919 attributes you can almost just instantiate one from the other just pass ing the attributes back and forth so
00:24:59.640 it's actually quite easy except when it's not easy and then what happens what
00:25:04.720 I'm doing now is just wherever I have something that doesn't fit this model I just subclass this mapper with a custom
00:25:11.000 mapper and I override those methods more or less and that's the part that I think
00:25:16.080 um there are would be more expressive ways to do that mapping and that's what I'm work you know starting to look at
00:25:21.840 now but so far this has actually worked pretty well and um it's allowed me to completely separate the way I think
00:25:28.240 about persistence from the way I think about my domain object so before we before I had this we used to have an
00:25:34.799 order class and I kid you not and I'm in I'm I'm I'm a rail's Noob so you can shoot me but it had 48 uh attributes in
00:25:43.159 in the act of record model right that is now represented by about eight classes
00:25:48.200 that separate out all of the different aspects of the order like the shipping the the billing etc
00:25:55.080 etc um so that but I think the this mapping is is is is is is more the more
00:26:00.159 challenging parts and then finally you know I've then you quickly run into things
00:26:05.760 like oh well what happens if I uh get the record uh I get the record I save it
00:26:12.320 then I save it again I have to be able to keep track that I've saved it once already so that I don't have multiple
00:26:17.520 copies around and this is an identity map in in fact an identity map was built into uh rails um um and I think it might
00:26:25.720 I I don't work in rails 4 but I think it might be taken out or or changed slightly but actually on the next slide
00:26:31.399 I'll show you what the identity map looks like and this actually I stole from rails and made it a bit simpler but
00:26:36.440 all it's doing is just making sure that there's a unique instance uh on on a per uh API request call for each uh entity
00:26:43.960 object so that I I can uh and it actually serves as a really cheap cache but that's not what its intent is so uh
00:26:52.200 so that's kind of where where we're where I'm going now is most of those service object form object request those
00:26:58.240 all kind of work well for us and I'm now looking at what would a repository pattern look like fleshed out and that
00:27:04.039 is by far the most challenging piece um I Heard a question about where you put things you can really just put them
00:27:10.360 anywhere you know that's the thing like rails just seems to be um there's a part
00:27:15.760 that I just felt constrained like rails didn't give me any guidance on where do I put a service object well you can
00:27:22.279 really put it anywhere you like you could put it on the autoload path or you can put it where rails might expect to
00:27:27.320 see it but you can just create a Services directory and put your service objects there rails will find it it's
00:27:32.720 not hard but rails doesn't really kind of tell you what to do so it doesn't make it easy to do these to think of it
00:27:39.440 but actually it's not hard and um but that's where we're going with that and
00:27:45.000 we'll we'll give you a link to a to I've started a get repo where I plan to share some of these ideas and if you're
00:27:50.640 interested in sharing ideas with us on that we'll we'll happy to uh talk to you
00:27:56.039 or uh or join us on the on the get repo right so what's the point again um
00:28:04.559 at the start we had these three things Embrace complexity getting getting the solution
00:28:12.039 to work is only part of the fun right uh it's it's your first draft as dhh said
00:28:18.720 talking about writing you get you do it over and over and getting things to work
00:28:24.440 that 90 line method I showed earlier that worked but does anyone want to go back and use that
00:28:30.799 again it's no it's no fun to revisit unless you're improving it which I did do eventually and and now it's it's much
00:28:37.559 nicer to work with um that that's fun at least we think that's fun um getting
00:28:44.399 beyond the problem and and getting it to a level where we actually don't mind going into our code extending things and
00:28:50.039 changing things um and we do that by breaking them up into the smaller parts
00:28:55.519 with the patterns that we've talked about um knowing where you're going uh in Allison Wonderland to paraphrase they
00:29:01.399 said if you don't know where you're going any road will take you there um we think it's important to know where
00:29:07.519 you're going and pick a road that you think will take you there doesn't have to be our road these are things that helped us and and we think they're good
00:29:14.559 ideas but it's not going to solve every problem for everyone these aren't rules like Dean said they're not science um
00:29:21.480 you can't just take them and throw them on and expect that your code will magically Get Better by going on a diet
00:29:27.799 uh and be more than just a rails developer um not that it's bad to be a rails developer but these things apply
00:29:34.880 across a across languages and uh stuff
00:29:40.159 like don't just learn Ruby learn learn beyond that um so as Dean mentioned we
00:29:47.559 have this GitHub that uh We've set up and right now it's just a readme we don't actually have the code in there
00:29:53.919 yet uh we'll likely put some of the code we showed today especially the repository bits but we'd love to
00:29:59.519 continue the discussion via issues poll requests whatever um that would be
00:30:04.919 awesome and and we'd love to talk to you about some of it uh throughout this week as well um Dean also mentioned we have
00:30:12.720 uh reading um you'll be able to get these slides uh after so I'm just going to gloss over them these are a couple of
00:30:19.679 the books that uh we've taken a look at to help us out with these things I think
00:30:25.000 the crowd has spoken and it's time to wrap up if um if you want to come up and talk
00:30:30.200 have it answer your question thank
00:30:56.200 you