RubyConf AU 2015
Rewriting Code and Culture
Summarized using AI

Rewriting Code and Culture

by Sabrina Leandro

In the RubyConf AU 2015 presentation titled "Rewriting Code and Culture," speaker Sabrina Leandro discusses how her team at Songkick transformed both their codebase and company culture during an intensive rewrite project. This presentation outlines the journey of overcoming slow product development and the lessons learned in creating a more agile and responsive environment for delivering great products.

Key Points:

  • Initial Challenges: Songkick initially faced lengthy release cycles affected by a complex codebase characterized by many dependencies, which hindered agility and innovation.
  • Change in Architecture: To tackle these issues, the team adopted a service-oriented architecture (SOA). This involved breaking down tightly coupled projects into manageable services, allowing for parallel development and reduced dependencies.
  • Identifying Core Product Proposition: The team conducted user research to understand the primary reason users returned to Songkick. It was determined that tracking favorite artists was crucial, guiding the development and enhancement of the iPhone app based on this insight.
  • Focused Rewrite Goals: A central lesson was defining a specific goal for the rewrite. The team aimed to simplify the website and prioritize key features, avoiding the temptation to simultaneously tackle multiple features or technology upgrades, which often lead to project delays.
  • Iterative Approach: Instead of a complete overhaul, the team rewrote one page at a time. This incremental strategy allowed for continuous release and validation of functionality while implementing a shift towards continuous delivery practices.
  • Empowering Developers: By giving developers more responsibility for testing and decision-making regarding design and functionality, the team improved efficiency. This cultural shift allowed developers to take ownership of the product quality.
  • Collaboration and Communication: Improved collaboration between developers, designers, and product managers fostered a stronger understanding of roles and challenges, enhancing teamwork and project outcomes.
  • Outcome of the Rewrite: The project culminated in a decoupled Rails application with a significant increase in development velocity and product releases. The new architecture facilitated a happier work environment, further enhancing the company culture.

Conclusions and Takeaways:

  • Leandro emphasizes the importance of maintaining a clean codebase as a means to an end rather than an end itself. The ultimate goal is to deliver valuable products to users through effective teamwork and understanding of product goals.
  • The talk concludes with a call to work collaboratively in multidisciplinary teams to improve both code quality and user satisfaction, encouraging attendees to adopt similar practices in their environments.
00:00:00.640 This talk is about how our team at Songkick changed our code and our culture during an intensive rewrite project. We're going to go through the lessons we've learned and our approach to that project. Then, I'll show you some code and how we actually implemented those changes, so don't worry, I’ll use the 'A' word. Finally, I’m going to discuss how this project changed our company's culture and how we work.
00:00:10.880 As I said, I work for Songkick. This is a story about Songkick. We are a live music company helping fans around the world attend more concerts. We launched a new version of the website way back in 2009. In the following years, we built new features, experimented with the product, and saw its popularity grow. It was all very exciting, but then over time, we noticed that it was taking longer and longer for us to release new changes and features to our users. This graph shows a great visual representation of the mess we were in.
00:00:38.719 This is a dependency graph of our projects and libraries. Any change to the top project, with all the lines coming off of it, meant we had to ensure we didn't break all the other projects below that depended on it. We had to have a lot of implicit knowledge about the codebase, making it very hard to make changes. It was basically hell. Small improvements to the codebase weren't cutting it anymore, and something drastic had to change. We made the decision, which is quite popular nowadays but maybe not so much when we did it, to go to a service-oriented architecture. We decided to break up the codependencies by splitting the domain into services, ensuring each product had its own frontend app using those services.
00:01:21.080 It has been over three years since we made that decision, and we are much more productive nowadays. Now, I'll share with you some of the lessons we learned about going through and finishing a rewrite project like this. The first lesson is to know your product. Sometime before the rewrite project started, the product team at Songkick was working diligently to find out what Songkick's primary proposition was. We had a bunch of features related to live music that we built over the years but wanted to identify the main reason users came back to Songkick.
00:01:52.680 After a lot of user research, we discovered that users came to track their favorite artists to ensure they never missed them live. Therefore, the most important feature for Songkick was to have all the events happening worldwide so that we could notify the right users about them, enabling them to buy tickets. We built our iPhone app based solely on this proposition, and it was a significant success from the start, and it still is.
00:02:35.680 We knew what our product was and had a vision of where we wanted it to go. This is a diagram we drew at the time of what we wanted the future to look like. As Caroline said yesterday, if you don't design your data model, having a service-oriented architecture will only break up your code and add latency to it, possibly making you even slower. We understood some products and their main models, so we knew what the end result should look like. But we needed to start somewhere.
00:03:05.600 We decided to start where it hurt the most and where we could see the most benefits quickly because a rewrite is a very risky project. This was our end goal for the rewrite: we wanted to iterate quickly on our Rails application. So, we started there by pushing the complexity down and hiding it behind Ruby service classes. This would also enable us to better understand the resources and API endpoints we needed so we could later use that knowledge to build HTTP services.
00:03:39.280 We weren't trying to change everything at the same time. By the end, we still had our Rails app in a happy state, capable of making quick changes, while still having the legacy code and highly coupled projects below that. It was fine because it was related to that. One important lesson we learned was to have one specific goal for your rewrite project. We knew that if we simplified our website to implement our main proposition, our users wouldn't leave because that was their main reason for being there. Improving our velocity was our main reason for doing this project. The reason for having one specific goal is that the possibility of starting over is very exciting. It's tempting to try to work on everyone's favorite features and issues, trying new technologies and ensuring everything is perfect and new.
00:06:09.919 However, this lack of focus makes it very difficult to finish a project like this. Having one goal in mind made it easier for us to focus and reject unrelated changes. This lesson was very hard for us to learn: we needed to explicitly define the full project scope and have a clear deadline. We ended up writing down every single feature we wanted to keep on the website, estimated how long it would take, and concluded that it would take way longer than we could afford.
00:06:50.760 Thus, we went back and removed features until we had a manageable deadline. Even after establishing that, we would reevaluate the deadline weekly to ensure we were still on schedule. If we needed to, we would simplify and delete even more features. For us, at the time, having a new feature was less valuable than moving forward quickly. During that project, we avoided adding any new features until we finished. It was either rewriting or deleting.
00:07:34.840 Speaking of deleting: deleting is faster than rewriting. We analyzed data about how features were used at Songkick, and we also got input from the development team about which areas of the code were challenging to maintain. Personally, it was very hard for me to delete features that I liked and used often, but I recognized that I wasn't an average Songkick user. Knowing your product gives you the confidence to know what is okay to delete without scaring users away.
00:08:14.440 Another critical decision we made was to rewrite the application on the master branch instead of starting new projects from scratch. We would rewrite one page at a time and release it to our users as we progressed. This approach allowed us to validate the new architecture, which I’ll mention in a bit. It also pushed us toward improving our release process and moving towards continuous delivery, thanks largely to Joe W. He was our biggest advocate for continuous delivery.
00:09:08.240 Another challenging lesson we learned was to iterate. When you're used to a very slow release process, it's hard to shift your mindset to realize that you can go faster. When we started this project, we were pressing very slowly; every change still had to be manually tested by our testers, and every small decision regarding copy and design had to be reviewed by our product manager or a designer. We needed to realize that a release cycle encompasses more than just software development.
00:09:58.200 We found one way to reduce this bottleneck was to give developers more responsibility for testing their own code and making decisions about copy and design. If developers have the right context and trust, they can make better decisions and take ownership of the code and product quality. Now, let me talk about our new frontend architecture, which isn’t so new anymore but was a crucial part of our rewrite.
00:10:43.080 The goal was to allow us to iterate quickly where we needed it most. Here’s one of my favorite bands, The Luxy, from Melbourne, which played just before the break. This is Songkick's event page for the latest concert. The rewrite was an iterative process; we picked our most popular pages first. For each page, the developers rewriting it collaborated with product managers and designers to define each component.
00:11:39.360 A component for us is a discrete module of functionality on a page. These components function independently of one another. We also simplified or removed complex features on those pages. The newly rewritten application is quite straightforward. For the event page, the new architecture involves defining the presentation logic, which simplifies the process significantly.
00:12:32.400 The controller is simplified, with the action methods only instantiating new page models, which are Ruby class representations of those pages. The page model itself has methods to create its components and retrieve the necessary data for display. We are happy now that by defining components and pages with designers and product managers, we established a shared language used throughout the entire development process.
00:13:48.680 This shared understanding helps everyone communicate more effectively about what we’re building. It seems simple, but it's incredibly powerful. This consistency in naming also benefits new developers or anyone new to the codebase by making it easier to navigate. If someone reports a bug in the event brief, even if I’m not sure where it is, I can expect to find it in the codebase. A fast release cycle requires a fast build; builds used to take hours but now run in under a minute.
00:14:43.600 Our end-to-end tests run at around 5 minutes. To achieve this speed, we deleted tests. The only end-to-end integration tests kept are the ones our tester and product owner selected, which they deemed sufficient to avoid breaking Songkick's main proposition. All other tests were either rewritten as unit tests or deleted. We established error logging and monitoring to alert us when sudden error spikes happen and implemented a daily error email to keep us informed.
00:15:37.680 While rewriting our controllers and views, we also began our journey towards a service-oriented architecture. For example, if we had a controller with an ActiveRecord model called Event, we replaced it with an application-specific client model. This class calls a service instance to get the data it needs to instantiate itself, which encapsulates how the services interact with ActiveRecord models.
00:16:24.000 The ActiveRecord model would define a method that sets the data it returns. This structured approach allows us to easily change how the services and methods operate since they remain in the same codebase. We iterated and improved our services until we got everything right. After just three months, we had a decoupled rewritten Rails app with no downtime. Users were still there, and we observed immediate benefits to our development velocity.
00:17:19.440 The rewrite completed exactly three years ago, and you can see the significant spike in the number of releases, which also reflected our happiness. During those months, we collaborated closely with designers and product managers, which fostered a stronger culture of teamwork within our company. This collaboration allowed us to better understand each other’s roles in the product development process.
00:18:09.520 As developers, we felt more comfortable suggesting simpler solutions, while designers and product managers understood the risks involved in implementing their ideas. Our cultural transformation translated into our processes, which emphasized shared language, small releases, and iterating over product development and design.
00:18:58.960 We used to deliver fully formed features to developers after weeks of discussions. Now, we involve developers much earlier in the idea development process, so we understand the context and can provide feedback early on. Features are defined during kickoff meetings that include developers, product managers, testers, and everyone else involved, allowing all questions to be raised and the feature's intent to be clarified.
00:19:52.560 Another change in our process is that designers and developers now pair and write code together. As a designer pairs with a developer, the browser becomes the artboard. Developers are happier because they can ask questions and provide feedback more easily, while designers gain a better understanding of the codebase and what's possible to achieve. This collaboration encourages the team to engage more actively with the final product's look and feel.
00:20:24.159 To conclude, having a clean codebase is just a means to an end. No matter how perfect the architecture is, if it doesn't serve anyone, it doesn't truly matter. The reason we're doing this is to deliver great products to our users. I advise you to learn to collaborate and work in a multidisciplinary team, getting closer to the product and business teams within your company. Help them understand how you work and what’s essential to you, while also learning how they work and what’s important to them.
00:20:57.839 A better understanding of how your work fits with others can enhance your own performance. For us at Songkick, working in a multidisciplinary team has made us happier and enabled us to deliver better products, which also improved our code quality in the process. I'd recommend that you give it a try. There’s much more I can discuss on this topic, so feel free to approach me afterwards. Thank you so much for having me.
Explore all talks recorded at RubyConf AU 2015
+14