Laracon US 2018 Live Blog
📢 That's it! Thank you for following along with me, and see you next year!
Matt Stauffer, Patterns That Pay Off
Design, behavior and organization patterns that will make a real impact on your company and codebase
Presented by Your Friend Matt (@stauffermatt)
- Goal is to not talk about design patterns. Instead, design patterns that we don't think about
- Spends a lot of time to read others' code
- pattern is a regular and intelligible form or sequence discenible in certain actions or situations, a model or design used as a guide in needlework and other crafts
- Think about every time you make a dress. You start it from a pattern
- In our context, there's the template of a solution
- Think about right posture between preventative vs reactive
- Preventative patterns, like "avoid N+1 queries", "floss every day", etc.
- Not the same for everyone
- Reactive patterns: feel/see the pain then choose the fix (root canal to treat cracked tooth, microservice to isolate slow adapter infrastructure)
- "If all you have is a command bus, everything looks like a command"
- Underlying is YAGNI, KISS, etc.
- Fantastic talk by Konstantin Kudryashov, Min-Maxing Software Costs
- Architect codebase for future
- Cost of change: Time it takes to adapt the existing application logic to new business realities
- Upfront design: Illusion that one can control cost of change by applying enough analysis upfront. Can't predict future
- If code is easy to change, it's easy to delete. Try to write code that is easy to delete. More flexible for future.
- Payoff is more important than the pattern
- Three types: Process, Architecture, (Re)Factoring
- No precogs
- You think you can tell the future, but you can't. Source of process anti-patterns
- Take what's in front of you, do that
- When you try to predict future, you commit to unrelaistic timelines, unhappy clients/devs, Overarchitect to reduce Cost of Change, rigid
- Do the best work you can with what you have
- Codebase consistency
- Establish/enforce standards,
- Code style,
- Code organization
- Trusted packages
- VC naming and branching strategies
- Pull Requests strategies
- 🔑 I don't want to be able to tell who wrote the code just from looking at it
- Payoff: easier onboarding, less cognitive load, good patterns get ingrained into culture and onboarding, devs spend brainpower on stuff that matters
- Bin Scripts
- Shell scripts for common tasks (/bin/init.sh, /bin/precommit.sh, etc)
- How many times have a new developer struggled to get the environment set up when all it needed was bower?
- Payoff: easier onboarding, less cognitive load, less time wasted on it works for me, more liklihood developers discover the steps for onboarding (devs don't read docs)
- Four Eyes
- No code should be merged into prod without two sets of eyes on it
- One developer, one code reviewer OR two pair programmers
- Payoff: Avoids negative consequences of hyper focus, reviewing brain is different from writing brain, brings different perpsectives, shares load of responsibility for all new code introduced
- Bonus tip: six eyes! Review your own code diff before asking review. Less wasted senior dev review!
- Document the weird
- Running fight between PHP and Laravel; split between people who think it should be more like Java, people who think it sohuld be more like Ruby
- Self-document code; some code just takes time to grok what it does, some why it does what it does
// Show the resource
- Aim for
// Exclude the connections that match both user ID *and* service ID
- Payoff: Faster comprehension, less wasted lines/visual debt, less useless docs mean people read docs more, records business priorities in the codebase
- Lower-case agile
- Agile Manifesto is not the Agile Industrial Complex
- "Agile" is often waterfall rebranded
- Instead, return to "agility"
- Think "Spider-Man is super agile!", not "Spider-Man is a Certifified Agile ScrumMaster 3000!"
- Stay light, respond quickly, adjust often
- Militia vs large army
- Payoff: Realize Agile promises without Agile costs (nobody saying "I can't pull that because it'll mess with the burndown chart")
- Monolith first
- You've heard of API-first (design API first, then consume it with JS/mobile)
- You've heard of microservices
- Instead, consider monolith first
- API-first/microservices have their place, but aren't free especially on small teams
- Majority of people say "Well, we might need it in the future!"
- When it's time for API-first, go with that.
- Payoff: Avoid costs of more complicated/duplicated validation, sync of testing dat and expectations, complicated branching/deploy strategies, higher up-front dev costs, reduced flexibility
- Seeds, not dumps
- Don't dump production data.
- Don't rely on dumps of production data for new devs or testing
- Instead, build robust, randomized seeders
- Check features under development on randomized seeds, not the narrower set of what-we-have-in-production-now
- Everyone in our codebase has a .com email address, but we don't handle .co.nz
- Keep production data in production
- Pro-tip: reference production data to help you improve seeds
- Payoff: Easier CI/CD, testing, onboarding, bug fixing, less scared to make changes locally, reduce fragility (less likely to only work if the data is a certain way), less likely to email production emails in dev ;)
- Test to save your job
- The best place to start: "What part of this app, if broken, would make me worried for my job?"
- What's most likely to break? What do I have least control over? What are we about to refactor? What would make my clients stress out? What would make me stress out?
- Payoff: You keep your job! Testing because it provides immediate value instead of because someone told you you should, most important tests first, you get to keep your job!
- Example: Codebase has an API with iOS consumer and local resource. Local resources in active development. iOS has been in production, 10k users stay the same. Constantly change to API, ended up breaking feature that broke iOS function. Wrote series of tests specifically for iOS API calls. Makes it easier to change while preventing regressions
- Scalable tasks
- Re-entrance: If a task gets interrupted, it can be restarted/completed
- Idempotence: Task can be called multiple times without changing side effects (instead of "can't run this cron job because it'll resend emails to the first half of customers that worked")
- Concurrence: More than one of a task can be run at the same time
- Sequence Independence: Order of tasks doesn't matter
- Payoff: Easy multi-worker setup, no fears/stress about rerunning jobs/crons
- Seed every test
- Once you start seeding, it's tempting to seed everything up-front, but it's OK to seed some broad data upfront but uniquely seed data for each test
- Payoff: No magic numbers, no need to flush work affected by previous tests, order of running tests doesn't matter, data/tests on that data are in the same file, easier to connect/reason about
- Onboarding for why not magic numbers: "What does 17 mean here? IDK"
- Service Classes
- PHP object that just does a thing. Catch-all for POPO (plain-old-PHP-object) that does stuff without being tied to a design pattern/framework structure
- Get creative with naming (e.g. RetrieveMoviePower)
- Consider __invoke(): RetrieveMoviePoster()
- Payoff: shorter methods, separation of concerns, easier/clearer/obvious testing, you get to say "POPO" more
- Custom Requests
- Much app complexity comes from parsing HTTP requests (e.g. Laravel "Form Requests")
- SignupRequest has prepared() method, controller method typehints SignupRequest
- Payoff: Smaller controllers, easier testing, separate repetitive
- View Data Composition
- Many oversized controllers/methods are from cost of organizing data for a speciifc view
- Presenter: Layer on top of thing (e.g. model) to give it more powers in views
- View Model: View POPO for organizational purposes
- Responsable: Interface that can be converted to Laravel response
return new DashboardViewResponse($user)
- View Components [Sorry, missed the definition in this one]
- Payoff: Slimmer controllers, clearer grouping/composiiton of data and sources, easier testing, fun words like "responsable" and "htmlable"