The majority of Ruby on Rails applications that we provide long-term maintenance and development on are inherited. Our clients usually bring applications to us that were originally built by a freelancer, in-house developers, or another agency.
Over a dozen years of working on apps, I believe we do our best work when improving and evolving existing Ruby on Rails application.
One of the best aspects about Ruby on Rails community is that when conventions are followed we're able to dive in fairly quickly to an existing code base and have a sense of how things fit together.
But inheriting a "legacy" Rails application requires a certain few steps before you ever type a line of code. It’s impossible to accurately estimate the amount of time it will take to accomplish a task, let alone actually complete the task itself, without taking the time to explore and understand how the app is currently architected and working.
So what does our process look like before we begin working on an existing Rails application?
Here are seven steps that we take when we inherit a legacy Ruby on Rails app, why they're important, and how these processes support our ability to improve our clients’ products.
Step 1. Have the stakeholder(s) explain their business
We do this through a series of questions in our initial calls with a potential client. Depending on the company, we meet with anyone from marketing managers to designers to directors of technology. Here are some of the questions we ask about in our first few conversation.
- What does their business do?
- What industry do they work in?
- Who are some of their biggest competitors?
- How do they make decisions?
- How would they describe their company culture?
- How does this application fit into their software ecosystem?
- Do their customers interact with it?
- Do third-party vendors/partners need to interact with it?
- And/or is this primarily for behind-the-scenes operations?
- Have they developed APIs within the app that need to be exposed for external and/or internal tools? If so, who relies on those?
- Does this application facilitate any financial transactions?
- Does this application store any extremely sensitive data? (i.e., Health records, billing information, personal data, etc.)
- Is it mission-critical? If the project went down in the middle of a Saturday evening -- what impact would that have on their business?
Step 2: What isn't working?
Every client, with an existing application, comes to us with a story of things that have worked well (and not so well) with their application.
Are their areas of their app that seem brittle? Are there pieces that seem to repeatedly break, get fixed, break again, get patched, break, rinse, lather, and repeat? This could highlight an area of the code base that might be really complicated and/or under tested.
Are there features that were developed that nobody appears to use? Is this an area that could get removed and/or does it need to improve so that is becomes useful?
What area(s) of the application do they dread having to deal with? What parts of the app are they complaining about – or they have an ongoing joke about dealing with?
What area(s) of the app did they end up creating "creative" workarounds for? This could hint at a poorly designed set of features -- perhaps an area to improve at some point.
We document this for future reference. An important aspect to our job here is to listen. These pain points might not be at the top of their priority list at the moment -- but at some point, these areas would be good to raise in the future.
Four months later, asking a question like, "Hi Sarah -- is that importing tool still a pain in the ass for your team? Should we take a look into that in the near future?"
Humans have a funny way of just accepting and getting used to annoyances in their software. It's our position that good partners listen for that and find ways to make their life a better – even if it’s as minor as making a textarea box a little bigger so that they aren't having to type several paragraphs into a text field or cleaning up an awkward navigation pattern. Sometimes, we get the biggest thanks for the smallest of solutions.
Step 3. Get a walk-through of the application
Before we start diving too far into the code base, we'll schedule an in-person or screen sharing meeting and have our new client walk us through their web application. We record this session, if possible, so that we can go back for reference and/or onboard other team members to the project.
This is really helpful to connect back to their user roles and business goals. As we will not have time (nor cognitive ability to remember) to dive into every nook and cranny of the application, we typically ask them to demo the 2-3 tasks that each role needs to reliably interface with.
During this process, we'll take notes on their user roles, document these in Confluence, and determine which stakeholders would be best to approach if we have further questions about the application. For example, "Maggie is a good point of contact for their reporting tools", "Geoffrey is a good point of contact for their data importing features", "Lindsay appears to know the most about their API functionality", etc.
Our aim here is to supply our team with useful information so that they can reach out to the right people.
Step 4. Show us your backlog
From here, we ask to see any existing backlog documentation that the team has in place. We've seen clients approach us with access to their existing Pivotal Tracker account, JIRA Kanban boards, huge spreadsheets (we see this far more often than you'd think!), a list of requests in an email, or formal PDF documents that outline thorough user stories and mockups.
More often than not, we typically move our clients into our own JIRA Cloud account and help them import and/or add tickets for us to begin prioritizing. While some clients may want to keep their history intact, migrating future to-dos into one cohesive system is the most efficient route forward. Here are just a few things we love about JIRA.
Step 5. Document all the things!
Before we start coding, we need to get a lay of the land. Some of these are asked and determined when we conduct a formal code audit/review of their application. Others we will ask in early meetings.
Here are a few of the application specifics that we’ll document.
- Is it hosted on Github, Bitbucket, etc.?
- Will our developers need to interact with a VPN? Who are our primary contacts to dealing with any access/permissions there?
- Do they have any architecture documentation, mockups, etc?
- Where is the application being hosted? (Heroku, AWS, Rackspace, EngineYard, internal servers, etc.?)
- Do they have staging environments? How closely do these match their production environment?
- Does the application run through any CDNs (Akamai, CloudFlare, CloudFront, etc.)
- Do they have any performance monitoring tools in place (New Relic, Skylight, Scout, etc?)
- Are they using any automated bug reporting tools (Bugsnag, Airbrake, Honeybadger, etc.)
- Is their documentation on how their existing developers have been handling deployments?
Step 6: Audit the Ruby on Rails code base
We’re firm believers that beginning a new partnership with a thorough code audit of an existing application is a solid way to start on the right foot. When there aren’t crunched timelines to begin new development, we’ll begin development with a flat-rate audit of the Rails application’s code base.
This audit gives us more information about potential security and stability issues that may not have been uncovered previously. It also documents how the application is structured. After a code audit, we know tons more about the application than we would without one – and usually, the client learns a lot about their application as well.
We’ll keep it brief as we’ve written about code audits extensively before. You can read about eight steps we take when auditing a Rails application for more information.
Step 7: Start coding (on something small first)
Before we dive into any of the big updates that our new client desires, we always try to identify a small update (i.e., that we can code and test within a few hours). The aim here is to have a test run through our communication tools, stage the update, get approval from the client, push to production, get final approval and close out the request.
We tend to spot small issues with server access, communication between our teams, and/or need to provide some more training on our tools. After we've collectively built up some confidence -- we are able to then start tackling bigger ticket items.
From my perspective, this ease into it approach is so vital early on. If a client has an urgent bug pop up a few days into our relationship – and we've yet to demonstrate to them (nor ourselves!) that we can successfully push an update to their environment – we might not be able to respond to the issue quick enough.
At this point, we should have a decent understanding of how our new (to us) client's business operates, how their existing Rails web application fits into that, a general idea of what it offers them, how critical it is, where it's hosted, and what technical debt we need to be mindful of. From here, we can start diving into their backlog and checking off their feature requests and fixes.
Do you have an existing Rails application that you’re looking to rebuild, redesign, scale, or update?
We’d love to talk to you about your project challenges and goals. Click below to schedule a call with us.