I attended RailsConf 2022 (Home Edition), and this post will be my notes from the sessions I attended before and after the event.
Bringing your Rails monolith along as the business grows
Carrick Rogers from Ontra
This was an interesting talk about how to keep your “majestic monolith” humming along. This started fairly early with an interesting question:
Are you a monolith because you want to be, or because you have to be?
Some companies and teams are perfectly happy with a monolith, and aren’t interested in breaking up to microservices. That is a valid approach.
Some tools suggested:
- Capybara for end-to-end testing.
- Rubocop as an ergonomic change.
- If you run
rubocop -a
on your code base, you can ignore that commit from yourgit blame
.
- If you run
- JSON:API to serialize API data can be faster than alternatives.
- Using patterns from Rails within the monolith, even when sub-optimal makes it easier to on-board developers.
- They wished they had picked up Ember testing for JavaScript earlier than they did.
Do you trust me?
John DeWyze from Shopify
This talk focused on how to build trust within a team and an organization.
Definitions:
- Trust is a reliance which can breed betrayal or camaraderie.
- Components of Trust:
- Predictability - Same every time.
- Competence - Does the job well.
- Integrity - Matches intent.
- Slightly different than predictability as you can be predictably bad.
- Benevolence - Generally act in good faith.
The tools your team uses can either build or betray trust. Some examples:
- Rubocop - Trust ritual to enforce predictability.
- Code Reviews - Trust ritual to enforce integrity.
- Must trust the competence and benevolence of all involved.
Your test suite is making too many database calls!
Joel Quenneville from Thoughtbot
This talk helps to describe patterns and issues with database calls which slow down tests.
Longer feedback loops slow down developers
- Avoid persisting data if you can.
- Know what objects are created into the database for each test.
- Shared test setups are a huge culprit.
- Often you’re creating database objects for one test, but you extract that out because DRY. But then you add another test, so you add to your extracted method. Now you are creating all the objects for the second test when you run the first.
- Updating the result of your Factory is a code smell.
- Someone set up something that you’re depending on, and it’s not quite the right data.
- Solution is to inline the setup.
- Use fewer
let
s, and ensure the ones you have are not getting entangled.- Example:
:blog
is created withauthor: author
. Now you’re creating anauthor
even if you don’t need one.
- Example:
- Use fewer
steventen/sql_tracker
is a gem to tell you how many queries are made.- Expensive Factory’s will compound the queries when composed together.
- Base factories should be minimal.
- Only the things which are required to get the info into the database.
- If you want to extend the Base factories, use traits.
testprof
gem will profile your Factories to see which are slow.
- Base factories should be minimal.
- Active Record callbacks which create records can be tricky.
- Adds records you don’t actually need for a spec.
- Sometimes cannot refactor the callback.
- “Test pain means you should change the implementation.”
- “Listen to your tests.
- Debugging techniques:
- Diagramming.
- Inspect the log.
- In debug mode, shows how many queries are running.
- Profilers.
Laying the cultural and Technical Foundation for Big Rails
Alex Evanczuk from Gusto
Gusto tried to extract code into gems and engines, as well as microservices. But none of those really solved the problems of Gusto’s growing monolith.
Big Rails is a system of sociotechnical tools, practices, and conventions that scale Rails development in terms of lifespan, number of contributors and complexity.
Tools:
- CodeOwnership - Declare ownership of code.
- CodeTeams.
- StimPack - Setup load paths for domain-centric packages
rather than grouping by architectural concepts.
order/models/
instead ofmodels/order
.order/views/
instead ofviews/order
.
- Packwerk - Helps to define a domain of objects, with
a public interface, and manage and map dependencies among the domains.
- Not required at all in production.
- Sorbet (and probably other Ruby static types?) can super-power Packwerk.
- VS Code Extension.
- PackageProtections - Checks for ensuring new code does not violate/worsen Packwerk packages.
Major principals of Big Rails are:
- Accountability and Ownership.
- Who owns a given portion of the codebase
- Can tag jobs, metrics, and performance, to a given team.
- Clear boundaries.
- Separation of domains through public API’s.
- Gusto moved code to folders based on the domain of the objects, rather than the architectural components.
- Thoughtful dependency management.
- Create packages (with ownership defined in
package.yml
) with Packwerk. - Gusto defaults to everything private, and creates a
public/
directory for each package’s public interface. - Packwerk generates a todo list similar to Rubocop.
- Gems and engines have a “hard” modularity, and moving files between them is difficult. Packages are not as “hard” with modularity since Packwerk does not exist in prod.
- Create packages (with ownership defined in
- Gradual Adoption.
- Start by adding package owners.
- May require refactoring code to allow for stricter ownership.
- Get teams to commit to defining packages and dependencies.
- Start by adding package owners.
- Intentionally curated and sustainable feedback loops.
- Educating developers why the changes are important.
- Created Packwerk and CodeOwnership VS Code extensions to shorten feedback loops.