We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

The Chirpolith: Successfully Migrating A Mess App to Ember

00:00

Formal Metadata

Title
The Chirpolith: Successfully Migrating A Mess App to Ember
Title of Series
Number of Parts
27
Author
License
CC Attribution - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language
Producer
Production Year2018

Content Metadata

Subject Area
Genre
VideoconferencingMobile appLinker (computing)Cartesian coordinate systemXMLComputer animationLecture/Conference
ArchitectureQuicksortDifferent (Kate Ryan album)Physical systemLibrary (computing)Cartesian coordinate systemRight angleMultiplication signLevel (video gaming)Scheduling (computing)State of matterView (database)Decision theoryInterface (computing)CuboidSoftware frameworkProcess (computing)Number
Product (business)MathematicsPoint (geometry)Cartesian coordinate systemWeb page
Complex (psychology)MomentumArchitectureView (database)Right angleProcess (computing)Multiplication signNumberCodeMathematicsCartesian coordinate systemPattern matchingView (database)Reduction of orderFigurate numberProjective planeFunctional (mathematics)Pattern languageUniform resource locatorMobile appMomentumComputer animationLecture/Conference
RoutingEndliche ModelltheorieAuthorizationWave packetConnectivity (graph theory)Bit rateCartesian coordinate systemMultiplication signDebuggerMessage passingMobile appLecture/Conference
Scripting languageCodeBitMultiplication signVideo gameMobile appLecture/Conference
CodeFunction (mathematics)Router (computing)Level (video gaming)Default (computer science)Data modelVolumenvisualisierungEuclidean vectorView (database)Mechanism designWeb pageElement (mathematics)Endliche ModelltheorieSystem callRight angleRouter (computing)View (database)Library (computing)BitNumberOffice suiteComputer scienceConnectivity (graph theory)MereologyRoutingQuicksortHookingTable (information)Web browserCache (computing)WritingStructural loadPattern languageEvent horizonComputer animationLecture/Conference
Computer fileFunction (mathematics)Router (computing)Instance (computer science)Default (computer science)Hash functionMereologyUniform resource locatorBitRoutingAsynchronous Transfer ModeMultiplication signInstance (computer science)Mobile appCodeLink (knot theory)Home pageStructural loadCartesian coordinate systemTable (information)MathematicsCuboidWeb pageNumberLengthConnectivity (graph theory)Hash functionPhysical systemRouter (computing)QuicksortComputer animation
Euclidean vectorRoutingCodeSingle-precision floating-point formatView (database)Connectivity (graph theory)NumberLogicMultiplication signLecture/Conference
Euclidean vectorView (database)Uniform resource locatorRootElement (mathematics)Error messageUniform resource locatorFocus (optics)Element (mathematics)Attribute grammarRootConsistencyCodeError messageGoodness of fitData modelMultiplication signView (database)Coordinate systemConnectivity (graph theory)Series (mathematics)Electronic mailing listEndliche ModelltheorieLogicProcess (computing)MathematicsRight angleNumberRoutingComputer animationLecture/Conference
Mobile appConnectivity (graph theory)Multiplication signPhysical systemMathematicsBitCartesian coordinate systemMeeting/InterviewComputer animationLecture/Conference
Broadcast programmingComponent-based software engineeringService (economics)CodeEndliche ModelltheorieSpacetimeEmpennageIdentical particlesComplex (psychology)Router (computing)Revision controlScheduling (computing)GodTerm (mathematics)Suite (music)Software testingConnectivity (graph theory)Endliche ModelltheorieQuicksortMobile appBitCartesian coordinate systemWeb pageMultiplication signCASE <Informatik>Link (knot theory)CodeLine (geometry)Branch (computer science)Electronic mailing listGoodness of fitNumberNamespaceRight angleHadamard matrixShape (magazine)Complex (psychology)Computer animation
Hash functionExecution unitInclusion mapCuboidAmsterdam Ordnance DatumConnectivity (graph theory)Cartesian coordinate systemMobile appWeb page
Projective planeDifferent (Kate Ryan album)Multiplication signTerm (mathematics)Scripting languageCore dumpNumberTrailMathematicsMobile appQuicksortCodeLecture/Conference
Multiplication signMathematicsRight angleProduct (business)
MereologyQuicksortElectronic mailing listCore dumpCodeFrame problemCircleComputer animation
Endliche ModelltheorieComponent-based software engineeringCodeEuclidean vectorMobile appFrame problemCartesian coordinate systemDebuggerEntire functionMereologyMomentumConnectivity (graph theory)Computer architectureEndliche ModelltheorieMultiplication signWordOnline helpCodeRoutingMobile appComputer animation
Linker (computing)AverageDaylight saving timeSquare numberLecture/ConferenceComputer animation
Coma BerenicesBlock (periodic table)Data typeComputer animationXML
Transcript: English(auto-generated)
Yeah, so my name's Alex Rossenburg and I'm going to be talking about the Chirpilas and
how we spent the last year migrating our messy application to Ember. So I work at a company called Iora Health and we're founded by doctors and our mission is to restore humanity to healthcare. So we do that by running primary care practices around the country where we serve
about 15,000 patients right now and you know if you've been to your doctor recently you've probably noticed them in the corner typing on a computer and if you've looked over their shoulder you may have seen sort of an ugly application with lots of gray boxes and complicated interface it's hard to understand.
And that's because those applications are typically been built for billing systems for insurance reasons not for patient care. So you know our CEO had used a lot of those systems in the past and one of the first decisions we made as a company was we were going to build our own because he hated pretty much everything he had used in the past. So we call our system Chirp and you know it's really designed to do everything that we
need to do to help the practices run. So everything from scheduling to documenting a visit to ordering labs to you know refilling prescriptions and you know from day one it's been a JavaScript heavy application
because we wanted it to be friendly and easy to use and really get out of the way between the doctor and the patient. But you know day one was a long time ago. So we started building it back in 2011 and at the time the state of the art for JavaScript was backbone. So we started as a backbone application and backbone was great but it's much lower level
than a tool like Ember is today right it's a much lower level library. And before long we realized we weren't only building our own application we were building a custom ad hoc framework on top of backbone. So you know we looked around the community and there was something called backbone marionette that was emerging.
So we start to take pieces of our application extract them into separate application built using backbone marionette and that worked well but we know we kept looking around and we saw ember and you know we got excited about ember so we did the same thing we took other pieces of our application extracted it out and you know you can imagine right
we're beginning to get a pretty messy system right lots of different technologies lots of different applications but you know we weren't even done yet because we also looked around and we saw react and you know we thought you know this time we wouldn't make the same mistake we'd do something different so reactive view layer we thought can we just use it as a view layer inside our backbone application and we did that
and that worked pretty well but you know we had really sort of painted ourselves into a corner you know at this point we had a pretty complicated you know bunch of technology and bunch of application that we as engineers didn't really want to work on and to the product team it was frustrating to them because everything was expensive
and hard to make changes to so you know it took us about five years to create this mess and what I'm going to talk about is how we spent you know basically the last year plus digging ourselves out of this mess so you know what we decided was we weren't
going to make the same mistakes we made in the past we're probably going to make our own special new mistakes but you know we're going to try and learn from the past so we thought about the things we had done wrong before you know and you know the first thing is you know each time we tried to dig ourselves out we didn't really know where we were headed so we knew the small little thing but if it was wildly successful
we didn't know what wild success would look like so this time we decided on a wild success would look like a nice clean member app you know something similar to what you would create if we'd start in a greenfield world instead of the brownfield world we were in you know the second thing we did is each time we extracted a chunk of functionality
we did is a big bang release right so users saw nothing nothing nothing and then we dropped this big change on them so we weren't going to do that again we were going to work in really small incremental changes you know the last thing we did is each change just made our world more and more complex so we weren't going to do that right we were going to reduce the number of technologies we had reduce the number of applications and the last thing is we
can never you know maintain our momentum every time we started off it started like gangbusters but then we you know we lost you know we lost interest we lost motivation and you know this so we came up with some techniques to keep motivation throughout this process
so because we had worked with all these technologies in the past you know we realized that you know if you squinted hard enough so you ignored all the details about the application they'll pretty much do the same thing right so they take a url in they do some pattern matching on the url to figure out what to do with it they call some api so load your
data and then they build an interactive dom you know with that data in it and you know that was true of all of them and we also realized that from when we had done the experiment with you know using react as our view layer inside the backbone app you can mix these technologies together so we thought what if we did the same thing as that experiment but we flipped it around
what if we put ember in charge let it take over the routing layer but made use of all of our existing backbone code and then slowly over time we could replace that backbone code with ember code until we'd end up with a nice clean ember app so that's you know the project i'm going to talk about and what we did so let's get started so the first thing
we needed to do if we were aiming towards having a nice clean ember app at the end of the day was we needed to admit we didn't know how to do that so we brought in mike north from front end masters to do some training and and it was really great you know he came in for a couple
days and really gave us a great foundation of how ember worked the philosophy behind ember how to think of routes components models right all of it but something else he gave us was also just a voice of authority so later when the time came to start building our application
and we would begin to get into the religious debates that all teams get into we could back off and say let's just do it the way we learned in training and cut those debates off at the pass so we want to build a nice clean ember app you know we did it the way all of you guys would do it right ember knew we'd start our ember app
but you know we weren't really building a greenfield app this was a brownfield world so we had to do a little bit of work to integrate it with our existing build scripts our existing deployment scripts and you know basically we treated all of our legacy backbone code as a third-party vendor code so we could just call into it by
loading it that way so now we had a nice ember app that did absolutely nothing the time came to make it start doing something so you know we started the top layer with the router and you know one of the things that our doctors do a lot in the office is they're documenting the visit right so they're writing notes and reading the old notes to remind them
what happened in previous visits and you know we looked at our old backbone routing tables and you know when we started creating the ember routes you know they they did the same things but the fact that ember pushed us into having these nice nested routes
all of a sudden got us really excited right so when we started having a note view route a note show route it could really focus on just the note right it didn't have to load the patient and everything else for the other parts of the page right we had an ancestor route that could take care of all that and the note show route could really just focus on the note
so we went in and started building that route out and you know when you typically think of building a route and the model hook right you you're probably used to thinking of calling into ember data to load your model but there's nothing that says it has to be ember data so we were able to call into our old backbone model and load the data that way which was great and
if you look really carefully here you might notice right this is not just loading the note it's get or fetch because in our old backbone world we didn't have something like ember data that would do some intelligent caching of what's in the browser what's already been loaded or not so we built our own caching mechanism and you know it's kind of a joke in computer
science that caching is one of the hard problems but it really is one of the hard problems and we really didn't want to be in the business of maintaining our own caching library so again we were excited for the day where this would go away and we could just live in ember data land where this would take care we would take care of this for us so we had our route
we went in to build the component so we did pretty much a similar pattern where we would call into our old backbone view that would load the view for us passing in you know the model which remember is the backbone model so it all worked fine and the only trick here
was we had to get that backbone view to render itself in the part of the page that ember had set aside for the component so it turned out that wasn't that hard you know in the component we could ask the component for the DOM element that ember set
aside for us and just pass that into the backbone view and it would render itself so the last thing we did is just a little bit of cleanup when ember tears down the component we just tell the backbone view to clean up after itself unbind events whatever else it might need to do so will this work and you know the answer is for the most part yes you know inside the
red box we have that component we just built right so it is loading data from the API and displaying it on the page so that that was great but if you look up at the top you can see a link to notes so that's taking us back to the index page of all notes and if you sort of look carefully at the link here right starting with a hash and again that's because back when we
started this application you know hash URLs was how you did front-end navigation now of course that's not going to work in a modern ember app where we use real URLs so you know at first you know we all started getting depressed this was you know we were going to have to go into
all of our old code find all the links and start rewriting them and that seemed like a huge pain and exactly what we want to avoid which is you know going into that old backbone code but you know then we realized ember was actually gave us the tools where we didn't have to do that so we wrote now a little bit of code stuck in an instance initializer and what it
does is it uses ember's hash location API to ask it to notify us anytime the hash URL changes and whenever it does we just strip off that leading hash and send the rest of the URL into the ember router where you know if it's a URL that we've already rewritten and we have a route
for everything's going to work great you know the ember router will route it to the appropriate route and if it doesn't we just stuck you know a new wildcard route at the bottom of our routing table that would navigate us out of our new ember app back to the old legacy app and you know once we did that it actually worked you know we could
not only display the data but we could link back you know across you know URLs and links worked as well you know but there was a problem now navigating between two apps was really slow you know every time you leave an app you know you left the ember app loaded the backbone app you click to link load the ember app right loading a new app takes time so you know
luckily we had a good feature toggling system so we were able to keep you know migrating these routes and releasing them without turning them on for users so without inflicting that slow pain on our users and took about six weeks for us to get all you know 32 of our routes migrated
over and then we were able to turn it on for all our users and that made us really happy because then we were able to start deleting some backbone code right all the old backbone routes were unused so we started deleting and we felt like we were on our way so once we had these
you know 32 routes in place each one wrapping a single backbone or yeah each one with its own component and each component wrapping a single backbone view it's time to start rewriting you know those backbone views and putting the logic into ember but before too long we started seeing pull requests that looked like this you know they were enormous they were too big to
deal with you know too big to review too big to you know make the changes incrementally and quickly so what was going on so we thought we were living in a world like this where you had one component wrapping one view but once we dug into the backbone a little more you know each
view is really coordinating with many child views and there's you know just a lot of logic in there so we did what you do when you have a problem that's too big to handle and we broke it down to a series of smaller problems so we realized if we could wrap each of those child views and then replace you know that coordination from backbone in ember now we had you know smaller
problems and we could just rewrite each component one at a time until we were left with a clean ember you know pure ember ember only solution so that's how we rewrote the view later but what about the data right we didn't want to deal with backbone models we wanted ember data models
so we had to also rewrite the model layer and you know we thought we had done a really good job designing our apis that we were really consistent but once we moved into an ember data land which really pushes towards the consistency and anything that's not you know conventional it you got to fight ember data on we realized we weren't so you know we usually had root
elements but not always we sometimes had two different URLs serving the same resource often with slightly different attributes coming down and you know some of our URLs were non-restful and you know we'd built our own homegrown errors and pagination
solution so we were able to work through all these problems but there was pain and you know we started asking ourselves should we just rewrite our apis you know in something like JSON API or GraphQL you know something conventional and you know the answer was maybe we should but not right now that we wanted to you know keep our focus on deleting backbone
code and rewriting the apis was a good idea but wasn't going to help us delete backbone code so you know basically we had a list of technical debt that we'd get to later and we put it on the list and we moved on with the existing apis and now we were in a place where we had a system and we could work through these components one at a time
and tackle them and make the changes so so that was all good now I want to you know switch gears a little bit and talk about some of the other problems we had made you know when we had extracted all those different applications so one of the applications we had
was our scheduling application where you know you'd schedule patient visits see who's coming in for the day and you know a really common use case was to go from the schedule into a patient's face sheet back to the schedule you'd go back and forth a lot and that's the same problem we had before where you're leaving an ember app loading a new ember app leaving that ember app
loading a new ember out right so it's the same problem of it being slow in the past when everything was sort of slow you know users noticed but didn't notice a huge amount as we migrate more and more into ember and the ember apps are getting faster users didn't always notice
the app getting faster they noticed the things that remained feeling slower so we knew we had to tackle this problem and this is where we decided to take the chirp face sheet and the chirp scheduling app and combine them together into one chirp list and so you know the problem we had when you know combining two apps is similar to the problems you have when you're merging two
git branches right you know as long as you have no conflicts it goes super smoothly but anytime there are conflicts you know you're in a world of pain so where you know where did we see the conflicts you know the first place we saw conflicts was just in our own code so that could
be you know any you know any of the code we wrote you know routers models components and pretty much if you had the same thing that was named the same way but was not exactly identical that's a potential conflict so for example you know both of these two apps had a patient details page and in the face sheet right the patient details displayed pretty much everything
about the patient whereas in the scheduling app it displayed just a little bit about the patient and a link over to the face sheet page so we realized what we could do before merging them was just to namespace each of them differently so instead of calling them both patient details
we'd call them you know rename it so it's the face sheet patient details and the scheduling patient details that way when the merge happens there's no conflict you wind up with two separate components and again you know somewhere down the line we can decide how to merge you know how to actually combine them if they really are doing the same thing so the other place we saw conflicts was in our package json and you know immediately we
realized things like ember js had to be on the same version in both applications but what surprised us was there were other packages that were only in the face sheet or only in the scheduling app that we didn't think would cause any problems but once we combined them both into the same
package json there were you know surprising conflicts that we didn't expect so the way we solved that was to just you know basically add all the missing packages from one application to the other and vice versa until we wound up with two package jasons that were identical in the original apps and then the merge could go through smoothly in this case you know having
a really good test suite helped you know saved our bacon in terms of knowing you know when things failed and working through them in small pieces rather than you know a huge thing where everything's broken god knows why so you know so we were able to do the merge successfully
and it went really well but you know it again it sort of distracted us from deleting the backbone code in the scheduling case it was really important right our users were feeling real pain and it was the right thing to do but you know we had a bunch of other apps and we didn't want to pay that price of doing the merge and you know spending all that time
on it instead of deleting backbone code so we wondered you know was there a different solution and we came up with you know an old favorite or an old you know not a favorite the iframe you know we realized if we built a component that had an iframe in it and we changed you know those
other apps to be skinned so they would fit nicely in this red box with no nav bar or anything like that you know this component could just load a brand new other application inside of it so this is the approach we went to you know to merge or to fake merge all of our other applications now the last thing i want to talk about is
how we stayed motivated over time so you know we worked on this project for a little over a year and you know a year is a long time so we you know came up with a bunch of different
techniques that helped us stay motivated and the first one was drawing a pretty picture so what we did is we wrote some scripts that would just count up you know the number of bytes of backbone code in our app and the number of bytes of ember code in our app and you know every monday morning we ran that script and updated this chart so that we could see over time you know
the red bar is going down we were deleting backbone code and again right it made us feel good to know that we were on the right track here in fact you know this chart you know i made this chart my home page that i'd come in and i'd see it you know first thing because it was really exciting and if you look closely sort of over in the bottom right corner
we're this close away to getting you know the last of that backbone out but didn't quite make it in time for today so the second thing we did is we defined what we were doing in business terms so we said you know a core goal of our team was to speed up our ability to deliver changes to the chart and the reason for this is you know technical initiatives often get
deprioritized and forgotten about compared to user facing initiatives so and that did happen to us but having this written down in black and white and sort of agreed as a core goal of our team helped us you know whenever that started to happen was to you know reprioritize it and bring
it back into discussion instead of being forgotten about forever and you know on the flip side you know it can be exhausting you know as an engineer to work on technical cleanup for a year so over this time you know we kept shipping features we you know we didn't only work on this we also did stuff to help our users and to make
chirp better and you know in fact somewhere midway through the year our users and our product team started getting excited when they saw that changes were becoming easier right it became faster to make these changes and we started getting payoff in doing these you know and the last
thing we did and this you know I sort of mentioned when we were talking about our API redesign or the iframes is things that were not part of our core goal of deleting backbone code we you know shamelessly put them on a technical debt list of things to get to later and you know so far it's worked out well for us in that you know it hasn't been a black hole
of things that just get forgotten about you know we have circled back to them and taken care of them and gotten them done so where are we today and basically over the last year we have you know swapped out our entire front-end application from underneath our users
you know for the most part without them noticing so that's been really good and today you know we have about 95 routes 75 models you know over 200 components which you know I don't know if that feels like a big app to you it feels pretty big to us and you know how we did this was just by remembering that you know at the end of the
day we were aiming towards having a nice clean Ember app by really focusing on the small incremental releases by reusing as much of our backbone code as we could in the beginning by rewriting one component at a time and by you know deferring everything that was off the critical
path of deleting backbone code and we also you know focused on simplifying our architecture so we wanted you know to have one application one technology so it's so much easier now that we you know when we have to work on this code base we can go in and think Ember rather than go in and think was this the backbone piece or the marionette piece or maybe
the piece with a little react so so much easier to do that and then all those tricks I just talked about right to help us stay motivated and keep the momentum as we went of course I'm standing up here today but it's you know thanks to the whole team who worked on this that we got it done so thank you guys very much