A podcast about development and design.
We do our best to be code-agnostic but we talk a lot about Rails, JavaScript, React, React Native, design, business and startups.
php/* */ ?>
A podcast about development and design.
We do our best to be code-agnostic but we talk a lot about Rails, JavaScript, React, React Native, design, business and startups.
Copyright: © ¯_(ツ)_/¯
Welcome to Iteration, a podcast about programming, development, and design.
Basic framework John follows:
Welcome to Iteration, a podcast about programming, development, and design.
Context:
John ran an agency for a couple years with a few developers + Designers, now runs a team of 12(ish) developers + Designers
Few Topics
IC vs Manager
Right sizing a team
Mythical Man Month
Remove bottlenecks
Safety + Empowerment
Leading by example
Don't scar on the first cut
Forbidden Conversations / honesty
John has been asked:
Questions JP has been asked:
Maybe some from our own?
John: YNAB (https://www.youneedabudget.com/)
NOTE THIS IS A RE-UPLOAD AS THERE WAS ISSUES WITH OUR PREVIOUS UPLOAD
> Welcome to Iteration, a podcast about programming, development, and design.
* John Intro — My name is John and I am a software developer for a home services startup.
* JP Intro — Hi, I'm JP and I am a software developer.
# Questions
* What is your testing philosophy?
* Why work on that team specifically? Why are you interested in this job?
* What kind of problems he like's to work on?
* What are some challenges with maintaining a public api?
* If I was your manager, what can I do to get the most out of your contribution? What do you need from me to succeed as a developer?
### Picks
* John M1 MacBook — So throughly impressed
* JP - [https://github.com/procore/handcuffs](https://github.com/procore/handcuffs)
Welcome to Iteration, a podcast about programming, development, and design.
https://www.planview.com/resources/guide/introduction-to-kanban/kanban-vs-scrum/
AGILE!!! SCRUM!!! KANBAN!!!
New Blood
John: Welcome to Iteration, a podcast about programming, development, and design.
Inventory and More (full stack)
Saas Solutions
References
John: Welcome to Iteration, a podcast about programming, development, and design.
JP
John
Picks
JP: https://www.rrauction.com/preview_gallery.cfm?Category=449
John: Rails starters: https://jumpstartrails.com/ — https://bullettrain.co/
John: Welcome to Iteration, a podcast about programming, development, and design.
https://macwright.com/2020/05/10/spa-fatigue.html
From the article
The more techincal one:
https://developer.mozilla.org/en-US/docs/Glossary/SPA
An SPA (Single-page application) is a web app implementation that loads only a single web document, and then updates the body content of that single document via JavaScript APIs such as [XMLHttpRequest]() and Fetch when different content is to be shown.
This therefore allows users to use websites without loading whole new pages from the server, which can result in performance gains and a more dynamic experience, with some tradeoff disadvantages such as SEO, more effort required to maintain state, implement navigation, and do meaningful performance monitoring.
Increased complexity — Development and deployment
SEO + Speed — Have to do "Server Side Rendering"
Maintainability? Stability?
In this episode we dive deep on tech stack choices, why they matter, how to choose one, when tech stack doesn't matter and when it makes all the difference in the world.
Back from break: In this episode JP + John cover all kinds of topics. Balancing life with a baby, testing, API dependencies and more.
JP: Welcome to Iteration, a podcast about programming, development, and design.
The "Codeless" movement, otherwise known as "Low Code / No Code"
Said another way: Is Bubble and GPT-3 coming to take all of our jobs?
We aren't talking about "Serverless" (Ex: Firebase / Aws Amplify / Parse) — Could be a good future episode.
NOT tools like Auth0 or Twillio
This is a "Full Stack" — No code app development framework in the cloud.
WYSIWYG for "Apps"
This isn't software!
Full "App" Development
Internal Tool replacements — Kind of mini-modern salesforce or filemaker clones
Domain Specific Codeless
John's Opinion:
Welcome to Iteration, a podcast about programming, development, and design.
This week we talk through the most common abbreviations in software.
For a whole complete list and discussion — visit this link
Today's topic:
Onboarding into a new codebase
From JP:
From John:
From JP
From John
JP: https://apps.apple.com/de/app/meeter-fast-call-initiation/id1510445899?l=en&mt=12
John:
Welcome to Iteration, a weekly podcast about programming, development, and design.
What are soft skills? Why are they important? Are they important?
Wikipedia defines "soft skills" ...
Soft skills are a combination of people skills, social skills, communication skills, character or personality traits, attitudes, career attributes, social intelligence and emotional intelligence quotients, among others, that enable people to navigate their environment, work well with others, perform well, and achieve their goals with complementing hard skills.
tldr; people skills
Hard skills, also called technical skills, are any skills relating to a specific task or situation. It involves both understanding and proficiency in such specific activity that involves methods, processes, procedures, or techniques
Conversation is loosely based on this book, the author is famously kind of a dick. Doesn't mean there aren't some solid takeaways, using it as a framework for conversation.
Few tips to improve your career:
John
JP
Recommended Career Books
John
JP
From SS: "Learn you want? Teach you must."
John:
JP:
From SS: Focus
From SS: Pomodoro Technique
From SS: Kanban
John:
JP:
Sections 5 and 6 — Financial and Fitness
From SS: power of positive thinking
From John:
JP:
BONUS From John: Communication
Picks
Welcome to Iteration, a weekly podcast about programming, development, and design.
This week — javascript frameworks
John
:JP
: wrappers around document.querySelector + some sort of state managementJP
JavaScript Ecosystem is FrustratingThere are SO MANY JS frameworks, feels like new ones every day.
https://www.instagram.com/archipics.ig/
Welcome to Iteration, a weekly podcast about programming, development, and design.
JP
LayoffsJohn
LayoffsJohn
Bad IRS SiteJP
Government Websites are just kind of funny in generalsave for another convo? vvv Yea for sure — Going too long.
Let's wrap
John - Notion Pro — Notion Examples - Progress bars, advanced formulas Dependent tasks. A lot of fun tips / tricks / hacks
command + k
for links!
Shift + Enter
for new lines JP -
Welcome to Iteration, a weekly podcast about programming, development, and design.
Article that inspired the episode
Quick notes from this article:
How many interviews have you conducted?
JP: At 2 years of Opendoor, I have conducted somewhere between 30-40 interviews. I wouldn't consider this a lot, but my last 10 have definitely been an improvement from my first 10.
John: Pre-tech I did around 50+ interviews. In tech I've done as well 30-40 interviews
What type of interviews do you conduct? Behavioral? Technical?
JP: I've only ever conducted technical interviews
John: I cover mostly behavioral/cultural and cover technical as well.
what should a candidate expect if they were to be interviewed by you?
JP: I set expectations really early on and give candidates a whole layout for the entire interview. The basic format for my interview is:
John: I always over-communicate and try to "do" as little as possible during the interview. I prioritize "Async" interviews as much as possible.
JP
Don't let a candidate spin their wheels - try to unblock them. See what working with them would actually be like.
John
My interview style is a bit different.
JP: https://github.com/ayu-theme/ayu-vim - I've moved away from Dracula
John: Book: Every Tool's a Hammer by Adam Savage — Yes, Mythbusters guy but also incredible maker and leader of technical teams building really complex things
Welcome to Iteration, a weekly podcast about programming, development, and design.
👍or 👎 on writing CSS?
What do you love about CSS, what do you hate?
To this day, what are some of the things you don't understand?
WTF ?— Here is a set of components you can build, pre-defined styles, gives you a starting point. Pre-buit UI.
Popular Ones
Boostrap — Pre-defined class "Components" card shadow
Tailwinds — Much more like Tachyons md:flex g-white rounded-lg p-6
Material UI
Foundation
Atomic CSS / Tachyons
Skeleton
Tailwind
Pro: Using tailwind for side project. Wrote 0 css
Con: Output is derivative
JP's argument — you could design anything you wanted
It's more of a function of what the docs provide.
Pro for Tailwind — Tailwind doesn't come with baked in components
How do we overcome derivative sites?
Could be tools
But I think it's more about pushing the design side more
Thinking in terms of "Bootstrap Components"
Think more first principle
Strong designer to push you too break the bounds of these frameworks
Boostrap
Tailwinds
Tachyons
John: Worked with it a lot, had some client projects use their own fork. Really powerful but it starts just feeling like "inline styles" SO MANY Classes
bg-dark-green ba bw5 dshadow2 br2 pb3
It's like ok ok calm down.
Material UI
Skeleton
Customizing it
Tailwind
Example: H1's — identifying patterns
Take a set of classes and use the "apply" function
Single set to define your custom classes.
You throw those into a single class called "Heading"
Bootstrap
Starts with customizing variables
These variabels are used in the
JP: https://thoughtbot.com/blog/running-specs-from-vim
John:
"Copy css" from sketch
Css in Figma
Re-pick: https://refactoringui.com/ (Same guy behind Tailwind)
Referenced: https://a.singlediv.com/
Welcome to Iteration, a weekly podcast about programming, development, and design.
1 — If you are new to development, this helps you make sense of all the resources, languages and frameworks. These roadmaps cover everything that is there to learn. Don't feel overwhelmed, you don't need to learn it all in the beginning if you are just getting started, focus on the core and the rest comes over time
2 — If you are experienced it helps you identify and organize gaps in your knowledge.
John: What about Mobile? This is called the "Web Developer Roadmap" but there is a lot of overlap
Web Dev 2020
John: How does someone choose a path?
"Everything the user sees"
"Everything that the user doesn't see"
JP: I wonder why javascript is the personal recommendation for back end language
John: Web: JavaScript, Ruby, Go or PHP seem to be good choices in today's landscape. Mobile of course is C# or Java
"The equipment it all runs on" — The boiler room in titanic
JP and John are least experienced in this bucket.
JP: Learn heroku lol
Today we're going to be talking about something that's frequently discussed on the Twitters-phere:
(day in the life of a remote developer)
Get dressed every morning
Have a dedicated space or device
Get good at notification settings and use them
Office Hours / Schedule
Over communicate in passive channels
Video / Audio Setup
Change your scenery
Work from energy not time.
Reduce distractions. Really don’t work with Netflix on in the background.
https://github.com/KyleAMathews/typefaces
We are going to be talking through the main / really popular API partners out there and give some quick feedback on how to integrate/go about them. Plus some lessons learned to keep in mind when planning integrations like this.
Sendgrid + Other Transactional Email
John: Formatting emails — inline styles only.
John: Some services have "Templates" with "Placeholders", some you pass the full HTML
John: Having some kind fo "log" object in your own domain can be very helpful.
John: Priority on background jobs for timely emails —
JP: Iterable. Opendoor uses this tool to send text, email, and push notifications. Everything hinges around handlebars / mustache and OOF - inline styles
JP: Side project with send grid, just a list of template ids
await deliverTemplateEmail({ to: user.emailAddress, templateId: SOME_TEMPLATE_ID, data: { contactFirstName: user.firstName, viewMyAccountLink: ${config.BASE_URL}/user/dashboard, }, });
Stripe + Other Payment Providers
Twilio (SMS)
Scheduler / Chron Jobs
OAuth Login?
Other?
Welcome to Iteration, a weekly podcast about programming, development, and design.
This week on code reviews
What makes good code review? Here's a link I found on reddit a while ago:
http://cassandra.apache.org/doc/latest/development/how_to_review.html
Another tweet:
https://twitter.com/addyosmani/status/1198502828425150465
JP's Experience
John's experience with freelance
Pros of freelancing
Cons of freelance
Links / Resources
Welcome to Iteration, a weekly podcast about programming, development, and design.
Ruby on Rails: 5 Things we hate 5 things we love. A quick overview of some of the key concepts, limitations, and strengths of the Ruby on Rails Framework.
There is a strong "Rails way" this lets you focus on product, higher level abstractions, and move quicker through your day to day. You have less decisions to make.
The "Rails way" is stupid, puts you in a box. Sometimes my needs and problems don't fit into the rails conventions.
No "shiny object" syndrome that you get in the JavaScript community.
I never know the right balance of "React" sprinkles inside of my .erb files. Sometimes it feels like I should just do a full blown SPA? Plus, sometimes making a form in React is so much easier for me than remembering all of the weird Rails Form shit
Why are forms so damn complicated? Maybe I just don't have a good understanding of data modeling...
JP: 🧦 https://bombas.com/
John: Abstract — Netfilx
John: Hey I'm John I run a firm that builds web and mobile apps.
Happy new year — this week we're talking through resolutions and goals for 2020 as software developers:
Join us this week as we talk about JavaScript. So much to love. We go deep with Author Luis Atencio. We talk through JavaScript's future, keeping up, learning and walk through a lot of nitty-gritty technical parts.
Books by Luis
I'm John, I run a design and development firm that builds apps and websites.
I'm joined by JP:
Hi everyone! I'm a full stack software engineer at a real estate tech start up.
Catch up / What's today's episode about?
John: California is on fire 🔥Making my job — complicated
Let's talk about git!
I recently watched this quick 4 hour course which is going to be my pick: https://frontendmasters.com/courses/git-in-depth/
Let's assume that listeners use git daily
git checkout
is just moving the pointer to the particular commit hash)i.e. walk me through how you might use git when you implement a new feature
this can be a longer section where we talk about git / github as it relates to working on a product
--no-pager
git diff
or a git branch
and your terminal opens up a "new page"? You can throw in the --no-pager
flag and it will display the contents in the same window insteadgit commit
without the -m
flag-m
flag is only for short commit messagesgit stash
stash list
A weekly podcast about programming, development, and design.
I'm John, I run a design and development firm that builds apps and websites.
I'm joined by JP:
Hi, I'm a software engineer at a real estate tech start up
Catch up / What's today's episode about?
This week Best and Worst Apps
Web app: Iterable - every "save" reloads the page
Mobile app: Notion - every change to a kanban board reloads the page; every time you swipe back, the page reloads
Takeaway: Optimistic rendering
Mobile app: apartments.com; I would need to register to save my settings. Maybe this is intended?
If you log out of the facebook app it doesn't actually log you out.
It goes to this screen with your profile photo and a password field, it's still collecting data on accounts associated with that phone.
"Would you like to be rich and beautiful?"
Desktop app: Slack has a cmd + k to search, cmd + r to refresh, etc
Desktop app: Youtube scroll on a full screen video
Chrome: youtube + tab to search | ebay + tab to search
Picks:
A weekly podcast about programming, development, and design.
Conversation — When Tech Meets Business
Iteration — A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
This episode uses Chapter 13 of Extreme programing as a jumping off point
Testing Early, Often, and Automated
Here is the dilemma in software development: defects are expensive, but eliminating defects is also expensive.
Planning: Managing Scope
This episode jumps off Chapter 12 of Extreme programing by Kent Beck.
Planning is an exercise in listening, speaking, and aligning goals for a specific time period. It is valuable input for each team member. Without planning, we are individuals with haphazard connections and effectiveness. We are a team when we plan and work in harmony.
XP recommends planning at any timescale with these four steps.
1.) List the items of work that may need to be done.
2.) Estimate the items.
3.) Set a budget for the planning cycle.
4.) Agree on the work that needs to be done within the budget. As you negotiate, don't change the estimates or the budget.
This usually comes from the client, sometimes myself or the team.
So here is our high level break down. 1st we add a new bottom tab that says students seeking this tab replaces the settings gear tab. The settings tab will be moved to the top right corner of the app. When a student clicks that tab the design attached (below) would show. * Design shows a list of students who have performed searches, with a "Message" button on each.
Rules A student should show up on a tutors seeking list if......A student search is
Whiz Tutor — an app where you can find a book nearby tutors for in-person tutoring.
Pitch was — when students search for but don't book a tutor, let relevant tutors message those students. This would happen through a "Students Seeking" tab that shows up in the tutors Mobile app.
Hand off the pitch to a designer on the team to refine and recommend a scope.
Question the work
Define the work
Handoff the design
So recent and painful.
Welcome to Iteration: a weekly podcast about programming, development, and design through the lens of amazing books, chapter by chapter
corollary: noun, a proposition that follows from one already proved. e.g. "The huge increases in unemployment were the corollary of expenditure cuts.
TLDR: Walk before you run
The point of customer involvement is to reduce wasted effort by putting the people with the needs in direct contact with the people who can fill those needs.
(After you write tests and fix the bug...) Once the defect is resolved, figure out _why_ the defect was created and wasn't caught. Initiate the necessary changes to prevent this kind of defect in the future
Magic formula for success as an agency:
A variety of people must work together in interlinking ways to make a project more effective. They have to work together as a group for each to be successful.
TLDR: what should each of these roles do on an XP team?
Tester - find the happy path; find ways to break it
Interaction Designer - choose overall metaphors for the system; create personas and goals; help the team analyze and make sense of the world;
Product Managers - write stories; pick themes and stories in quarterly cycles; prioritizes; encourage communication between customers and programmers
Project Managers Facilitate communication, help identify priorities and consistent accountability.
Executives Courage, confidence and accountability
A weekly podcast about programming, development, and design through the lens of amazing books, chapter by chapter
John: Hi, I'm John and I'm joined by JP.
JP: Today we will be going through chapters 6, 7, and 8 for those following alone - which are all about Extreme Programming practices. These are the things that XP teams are doing on a daily basis. Kent Beck defines two categories for practices: Primary Practices and Corollary Practices. You must first master the primary practices before considering corollary ones. This episode focuses on primary practices.
Practices that do not serve a purpose or have values are empty. For example, pair programming for the sake of making your boss happy doesn't make much sense. However, pair programming to communicate, get feedback, simplify the system, catch errors, and bolster courage makes a lot of sense.
XP predicts that the more face time you have, the more humane and productive the project.
👨🏫 humanity
👨🏫 improvement
👨🏫 quality
Make your workspace about work. An interested observer should be able to walk into the team space and get a general idea of how the project is going in 15 seconds.
👨🏫 mutual benefit - doing stuff today that benefits me now and in the future
👨🏫 flow
Work only as many hours as you can be productive and only as many hours as you can sustain. Burning yourself out unproductively today and spoiling the next two days' work isn't good for you or for the team.
Taking care of yourself is the quickest way back to energized work.
I turn to long work hours as a way of grabbing control in a situation in which I am otherwise out of control
👨🏫 flow
👨🏫 humanity
👨🏫 improvement
👨🏫 mutual benefit
Hot tips:
➡️ stay the same amount of time but manage time better
➡️️️️️ block off 2 hours at a time in your calendar just for coding
➡️ turn off phone, email, and slack notifications
Plan using customer-visible functionality. As soon as the story is written, try to estimate the development effort necessary to implement it.
Write stories on index cards and put them on a frequently passed wall. Every attempt I've seen to computerize stories has failed to provide a fraction of the value of having real cards on a real wall.
👨🏫 flow
👨🏫 reflection
👨🏫 quality
REMEMBER! XP is a way to improve both your development process and your experience in it.
Change always starts at home. The only person you can actually change is yourself. [...] Dictating practices to a team destroys trust and creates resentment.
lead by example
🐶 Find a practice - List out Things that drain you, list out things that energize your work, adopt practices around these two things, preventing drain and supporting energizing!
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter
Hi, I'm John and I'm joined by JP.
Today we will be going through chapter 5 and continuing our discussion about the guiding principles of Extreme Programming.
Values are too abstract to directly guide behavior. (This is why we discuss things in the context of principles)
Other principles may guide your team, but these are the principles that guide XP:
Now obviously we aren't going to bore you with discussion on all 14 of these principles, so today we'll only talk about a handful of them.
Copy and paste alert
What do people need to be good developers? What are some basic human needs?
Interestingly, satisfying these requisites meets both business and human needs.
"Fractal Nature of geology" When nature finds a shape that works, she uses it wherever she can.
A crystal is a material whose constituents, such as atoms, molecules or ions, are arranged in a highly ordered microscopic structure — the same arrangment all the way to an atomic level. The same shape, makes up arrangments that make the same shape, that makes up arrangements that make the same shape.
All's to say - I've found that many things that prove useful at a small scale, work at larger scales
Concepts like
Software development teams where everyone is alike, while comfotable, are not effective. Teams need to bring together a variety of skills, attitudes, and perspectives to see problems and pitfalls, to think of multiple ways to solve problems, and to implement the solutions. Teams need diversity
The principle of diversity suggets that the programmers should work together on the problem and both opinions should be valued.
"Learn to see problems as opportunities for change."
To reach exellence, problems need to turn into opportunities for learning and improvment, not just survival.
Conciously choose to transform each problem into an opportunity. Good book on this the obsticle is the way
Example: .env
files for all of our projects got posted to a public repo. We migrated toward a better more secure system, credentials that would be harder to leak and are easier to rotate. We used the problem as an oppourtunity to improve our architecture.
Sacrificing quality is not effective as a means of control... Quality should not be a control variable.
This is really extreme.
Author makes the aurgument that when you skimp on quality you end up spending even more time or money. This rings true, I have often taken the wrong approach in projects of skipming on design, testing or refacting and it doesn't really help in the long run.
We'd all like to get more features out the door for less money, it's just not doable. Less is less.
If you're having trouble succeeding, fail. Don't know which of the three ways to implement a story? Try it all three ways.
When you don't know what to do, risking failure can be the shortest, surest road to success
Conclusion:
Season 7 Epsiode 2
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter
5 Essential Values in Extreme Programing
Extreme Programing By Kent Beck - Chapters 2,3 and 4
Chapter 2 - Learning to Drive
frequent, small corrections
don't wait to find out if you are going in the wrong direction
Chapter 3 - Values, Principles, and Practices
values are the roots of things we like and don't like in a situation.
Making values explicit is important because without values, practices quickly become rote (habitual repetition), activities performed for their own sake buck lacking any purpose or direction.
practices are evidence of values
Practices are clear. Everyone knows if I've attended the morning standup meetings. Whether I really valuecommunication is fuzzy. Whether I maintain practices that enhance communication is concrete.
principles bridge the gap between values and practices
START HERE
Chapter 4 - Values
Chapters 2 and 3 are small introductory sections, here is the TLDR:
Software, teams, and requirements change. We need to be able to adapt
to such change. The next 3 sections will be about values, practices,
and principles of Extreme Programming
Chapter 4 is about values
Everyone who touches software has a sense of what matters. One person might think what really matters is carefully thinking through all conceivable design decisions before implementing. Another might think what really matters is not having any restrictions on his own personal freedom.
What actually matters is not how any given person behaves as much as how the individuals behave as part of a team and as part of an organization.
Sometimes it's easy to bikeshed over things like code style. Arrow functions vs function declaration, inline functions vs methods, etc
XP embraces 5 values to guide development
JP: Retro feedback and postmortem feedback often includes communication - both good and bad
2. Simplicity
To make a system simple enough to gracefully solve only today's problems is hard work.
"What is the simplest thing that could possible work?"
JP: Emphasis on "today's problems" - how can we provide value to the customer without compromising on theirexperience and without overengineering a solution?
JS: Stakeholder communicatinon, actively work to include everyone in at the key touchpoints, initial concept, mokcup, prototype, final review.
JS: Have something to look at / talk about. Somebody make a mockup, somebody write some pseudocode
opinions about an idea, yours or your teammates
how the code looks when you implement the idea
whether the tests were easy to write
whether the tests run
how the idea works once it has been deployed
JP: Be agile! Look to build an MVP. Get analytics on things and make decisions from there. It's hard to invest in an idea entirely and then end up ditching the whole thing. Everyone feels burned.
JS: Again, think through key touchpoints, (99%, 50%, 1%)[https://medium.com/the-mission/how-to-scale-yourself-the-99-50-1-framework-7798518f36e1]
JP: Being able to speak up when you disagree with people's ideas and being able to listen and exercising patience.
JS: Being honest with yourslef and stakeholders about timelines, replytimes, scope.
JS: Having the courage to set boundries. - "I need this by tomorrow" - I'm sorry, I can't make that happen for you.
5. Respect
If members of a team don't care about each other and what they're doing, XP won't work. If members of a team don't care about a project, nothing can save it. Every person whose life is touched by software development has equal value as a human being. No one is intrinsically worth more than anyone else.
JP: It's much easier when everyone respects each other.
JS: Reconize there's rarely a "wrong" approach, avoid letting pesonal preference becoming the "right" way.
JS: Reconize positives, "what I like about this is... however" Try to keep things in a positive context.
6. Other
This list isn't exhaustive. The important thing is that your team should align on core values.
Other Values: safety, security, predictability, and quality-of-life <- I feel like these need an episode!
Chapter conclusion:
Values don't provide concrete advice about what to do in software development. Because of the distance between values and practices, we need a way to bridge the gap between them. Principles are the tool we need.
Picks
JP: Pair code review sessions
JS: the (99/50/1 framework)[https://medium.com/the-mission/how-to-scale-yourself-the-99-50-1-framework-7798518f36e1]
JS: Basecamp's new book - (Shape Up)[https://basecamp.com/shapeup]
Iteration — A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
By Kent Beck
"Extreme Programing is about social change. It's about letting go of habits and patterns that were adaptive in the past, but now in the way of us doing out best work. It's about giving up the defenses that protect us but interfere with our productivity. It may leave us feeing exposed.
It's about being open about what we are capable of doing and then doing it. And, allowing and expecting others to do the same...
...It's about the process of becoming more of our best selves and in the process our best as developers. And, it's about writing great code...
"Philosophy of software based on... communication, feedback, simplicity, courage and respect.
"XP is my attempt to reconcile humanity and productivity in my own practice of software development..."
"How would you do it if you had enough time? — Fussing about the constraints distracts you from your goals. Your clear self does the best work no matter what the constraints are"
Final Summary — What is XP?
Iteration Season 06E09 - Release July 22nd 2019
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Roundtable: Getting a Job in Tech
Between books - Discussion about career development in tech
Guest: John Rivera - Link?
John S to lead discussion -
Where do you work now? What do you do?
John S: Run an agency, we are a small team of remote developers, we do mobile apps and web apps.
John R: Just started working on Amazon photos mobile app for the prints feature team, I do cross-platform mobile development primarily using React Native. But I’ve also gotten to do my fair share of project management with ChefSteps, and am seeking to pursue that at Amazon
JP: Opendoor
Where did you start? Where were you before tech?
5mins each on origin story
John S: Dabbled in design + web for ever — I was working in the corporate world a job I didn’t love but I was successful. Stepped back and switched careers at November 2015 - switched career at 25
John R: I worked at uhaul and albertsons as a meat clerk. Started things off by saving up for a bootcamp. Did freelance.
JP: MySpace layouts in 9th grade, 13-14 years ago. Then web design until about 2015
What’s been a key practice or tool in moving your career forward?
John R: Networking, Diving deep, embracing things that aren’t in my domain
John S: Consistency, Keeping up with friendships (networking), Blogging, pushing outside comfort zone.
How do you balance getting work done now vs ongoing learning?
John S: Use new tools and techniques in the day to day
John R:
JP: Being proactive with code review and looking to senior engineers
How do you get a good Job in tech?
John S: Network, publishing, making your work visible, random blog post from 2016
John R:
JP: I got my job from meetups
What would you have told yourself 3 years ago?
John S: Consistency, life is a marathon not a sprint. Keep stretching yourself outside comfort zone. Focus on less, go deeper on less things.
John R:
JP: Take breaks, you won’t forget how to code if you take a day off
CLOSE - no picks
John R - Where can people find you?
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Work Stuff
Summary of "Refactoring"
Picks:
Things mentioned
Craftwork design https://craftwork.design/
To do refactoring properly, I need a solid suite of tests to spot my inevitable mistakes.
If you want to refactor, you have to write tests
Testing should be risk driven; remember, I'm trying to find bugs, now or in the future. Therefore I don't test accessor methods that just read and write a field. They are so simple that I'm not likely to find a bug there.
My focus is to test areas that I'm most worried about going wrong.
Whenever I have a collection of something, ... I like to see what happens when it's empty
When you get a bug report, start by writing a unit test that exposes the bug
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
var organization = { name: "JP Sio", country: "USA" };
becomes ⬇️
class Organization {
constructor(data) {
this._name = data.name;
this._country = data.country;
}
get name() {
return this._name;
}
set name(arg) {
this._name = arg;
}
get country() {
return this._country;
}
set country(arg) {
this._country = arg;
}
}
class Organization
doesn't need to know / care which is stored and which is calculatedclass Person {
get courses() {
return this._courses;
}
set courses(aList) {
this._courses = aList;
}
}
becomes ⬇️
class Person {
get courses() {
return this._courses.slice();
}
addCourse(aCourse) {
/*...*/
}
}
slice()
is key here, does not modify the original array - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sliceorders.filter(0 => "high" === o.priority || "rush" === o.priority)
becomes ⬇️
orders.filter(o => o.priority.higherThan(new Priority("normal")));
- programmers are often hesitant to create their own types and rely only on primitives. i.e. representing a phone number as a string instead of as it's own type
A telephone number may be represented as a string for a while, but later it will need special behavior for formatting, extracting the area code, and the like
Sometimes it's better to not try to split things apart, sometimes it just complicates things.
// before refactor:
function getItemPrice(item) {
if (itemOnSale(item) == true) {
return item.price - 5
} else {
return item.price
}
};
function itemOnSale(product) {
if (product.onSale == true) {
return true;
} else {
return false;
}
};
let original = getItemPrice(sweatshirt);
// after refactor:
function newGetItemPrice(item) {
if (item.onSale == true) {
return item.price - 5
} else {
return item.price
}
};
The theme of this chapter: just because you know how to refactor, doesn't mean you know when. This chapter talks about the when.
One thing we won't try to give you is precise criteria for when a refactoring is overdue. In our experience, no set of metrics rivals informed human intuition. What we will do is give you indications that there is trouble that can be solved by a refactoring.
editor choice
S06E04 - Iteration
A weekly podcast about development and design through the lens of amazing books, chapter-by-chapter
Refactors Before -
Picks:
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Why should we refactor?
Getting buy in for refactors:
When to refactor:
When to not refactor:
Legacy Code
Refactoring Tools for future episodes?
Picks
In this episode we dive deep into some specific refactors from Refactoring 's Chapter 1. We talk about renaming things, extracting functions, functions, replacing a temp with query and some other hot tips and tricks you can put into your code today.
This episode walks through specific code examples from Chapter 1 of Martin Fowler's Refactoring...
Change Function Declaration
Extract Function
Replace temp w/ query
Instead of:
accounts = get_accounts(user)
transactions = get_transactions(accounts)
we can just do:
transactions = get_transactions(get_accounts(user))
Replace conditional with polymorphism
Notification.deliver!
example
Welcome to iteration. A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Refactoring
Improving the Design of Existing Code
by Martin Fowler (with Kent Beck)
Introduction
Refactoring process:
Considerations + Thoughts
My Pick:
S06E01 - DO IT LIVE!
This week is a more casual episode where we talk about recent struggles findings and some of our favorite parts of our most recent book. Practical Object-Oriented Programming in Ruby
We'll be back episode covering a new book - Refactoring by Martin Fowler
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
CH2 - Designing Classes with a single responsibility
Chapter 7 - Favorite Takeaways/Examples From POODR
My Team Came up with:
include Listable
include Lister
Any user type can act as a “Lister” and add things to the list
Any object can be “Listable” or “added to a list”
Recent Lessons - Always have a staging environment
Picks:
https://thispersondoesnotexist.com/
Iteration S05E09
Testing… Testing… 123
Publishing February 18th - Hope everyone had a good Valentine’s Day weekend!
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Introduction
Reasons to test:
Knowing What to test:
Knowing When to Test
Knowing How to test:
Tests are indispensable. Well-designed applications are highly abstract and under constant pressure to evolve; without tests these applications can neither be understood nor safely changed. The best tests are loosely coupled to the underlying code and test everything once and in the proper place. They add value without increasing costs.
Next Episode - Recap of Practical Object-Oriented Design and New book announcement!
Picks:
NOUN PROJECT - https://thenounproject.com/
**Super Smash Bros Ultimate **
Combining Objects with Composition
Metz, Sandi. Practical Object-Oriented Design in Ruby
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
“Combining the qualities of two existing subclasses, something that inheritance cannot readily accommodate.”
We talked about inheritance, then modules, now this builds on top of the idea of modules and pushes it further.
Composing a bicycle of parts...
Bicycle > has A parts
Parts has subclasses of - RoadBikeParts and MountainBikeParts
Making the Parts Object More Like an Array - This part was freaky
Parts Factory
Different Configs within the parts factory > an array of all the keys and attributes - road_config - mountain_config
Using all this to make a recumbent bike:
Once this is all set up you have this incredibly powerful interface of a bicycle composed of parts:
Bicycle.new(
size: 'L',
parts: PartsFactory.build(recumbent_config))
Composition VS Aggregation
A Meal is composed of an appetizer - An appetizer does not survive outside of the meal. When the meal is gone by definition the appetizer is gone. A meal is composed of an appetizer.
A band is an aggregate of musicians - when the band breaks up the musicians don’t die.
“Composition” encompasses both aggregation and composition -
“This distinction between composition and aggregation may have a little practical effect on your code.”
Deciding Between Inheritance and Composition
“Think of it this way: For the cost of arranging objects in a hierarchy, you get message delegation for free.”
When in doubt use Composition over inheritance
“The general rule is that faced with a problem that composition can solve, you should be biased towards doing so. If you cannot explicitly defend inheritance as a better solution, use composition.”
John’s Pick: Book: "It Doesn’t Have To Be Crazy At Work" -> David Heinemeier Hansen and Jason Fried
JP: Kahn Academy - digging into math again
Next Week: Final Chapter - Designing Cost-Effective Tests
Metz, Sandi. Practical Object-Oriented Design in Ruby
Chapter 7. Sharing Role Behavior with Modules
Welcome to iteration
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Last episode we talked about inheritance which was kind of an extension of duck typing… but sometimes we need to combine the qualities of two existing subclasses, something that inheritance cannot readily accommodate.
Many object-oriented languages provide a way to define a named group of methods that are independent of class and can be mixed in to any object. In Ruby, these mix-ins are called modules.
Discovering the Schedulable Duck Type
The Schedule expects its target to behave like something that understands lead_days, that is, like something that is “schedulable.” You have discovered a duck type.
This specific example illustrates the general idea that objects should manage themselves; they should contain their own behavior.
Mountain Bike? Mechanic?
Now, in the code above, the dependency on Schedule has been removed from Bicycle and moved into the Schedulable module, isolating it even further.
Like Using Inheritance
COMES BACK TO AUTOMATIC MESSAGE DELEGATION
Loggable Example
When Bicycle includes Schedulable, all of the methods defined in the module become part of Bicycle’s response set.
When a single class includes several different modules, the modules are placed in the method lookup path in reverse order of module inclusion. Thus, the methods of the last included module are encountered first in the lookup path.
When a single class includes several different modules, the modules are placed in the method lookup path in reverse order of module inclusion. Thus, the methods of the last included module are encountered first in the lookup path.
Picks:
John: Type to Siri - Accessibility > Siri > Type to Siri
JP: Scrimba - https://scrimba.com/playlist/pKwrCg
Acquiring Behavior Through Inheritance
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Sani Metz - Object-Oriented Design in Ruby
“Inheritance is, at its core, a mechanism for automatic message delegation. It defines a forwarding path for not-understood messages.”
Where to Use Inheritance
Objects that share a common parent -
The objects that you are modeling must truly have a generalization-specialization relationship.
Bicycle Touring Company - FastFeet
Bikes - Mountain and Road Bikes
Bikes have an overall size, a handlebar tape color, a tire size, and a chain type.
Create a new empty Bicycle Class
Let RoadBike > Bicycle
And MountainBike > Bicycle
When in doubt put less code in the parent, it’s easier to promote code later when you need a shared code.
“The general rule for refactoring into a new inheritance hierarchy is to arrange code so that you can promote abstractions rather than demote concretions.”
A superclass may have many subclasses, but each subclass is permitted only one superclass.
This family tree image is, however, a bit misleading. In many parts of the biological world, it’s common for descendants to have two ancestors.
It’s really useful to rails a NotImplementedError
in the parent class in the methods that are required from their children, for example, default tire_size -
“Creating code that fails with reasonable error messages takes minor effort in the present but provides value forever.”
Initialize > Post Initialize to append any or overrode attributes from the parent initialize method.
Initialize + post_initialize
Closes with a mic drop - Initializing a new RecumbentBike is so DRY and painless!
“Inheritance solves the problem of related types that share a great deal of common behavior but differ across some dimension.”
“The best way to create an abstract superclass is by pushing code up from concrete subclasses.”
“When your problem is one of needing numerous specializations of a stable, common abstraction, inheritance can be an extremely low-cost solution.”
PICKS
Practical Object-Oriented Design in Ruby
A weekly podcast about development and design through the lens of amazing books, chapter-by-chapter.
Duck types are public interfaces that are not tied to any specific class.
Objects that are defined by their behavior than by their class name.
if an object quacks like a duck and walks like a duck, then its class is immaterial, it’s a duck.
In a way, the “+” operator is a “duck type” - because it responds differently to a different type of objects.
Preparer
TripCoordinator, Mechanic, Driver can all be a preparer - they all respond to the prepare method in their own ways.
At a higher level, what are these all doing? They are preparing something - we can trust within this shared interface.
Within mechanic - we only call prepare_trip
vs gas_up
or full_water_tank
-
Instead of switching on type
You
Talk through this Object:
Notification Object?
https://github.com/withbetterco/wellstart/blob/master/app/models/notification.rb#L156
It has this insane method checking to see if the user’s notification settings match the notification that’s trying to send
We are wanting to extend the notification object, for another type - Push Notifications
Object (message, comment, like)
User
NotificationSettings
Notifier
Notification Policy
“The ability to tolerate ambiguity about the class of an object is the hallmark of a confident designer.”
Recognizing a duck:
“You can replace the following with ducks: • Case statements that switch on class • kind_of? and is_a? • responds_to?”
Polymorphic Objects
Went from a ParticipantNote, and ProgramNote, and ApplicantNote, to one single Note object through a Notable Module. They all have “ has _many: notes, as:: notable” instead of each having “program_notes”, applicant_notes, etc.
“you are missing an object, one whose public interface you have not yet discovered.”
Dot files - .zshrc - Custom prompt - with my git status -
Slippers from JP - Quadie
At an object-oriented level, applications are made up of classes but defined by messages
Imagine a restaurant kitchen. Customers order food off a menu. The menu is a kind of public interface. Within the kitchen, messages get passed and the way a meal is prepared (implementation details) are private to the customer.
Public Interfaces
Private Interfaces
The public interface is a contract that articulates the responsibilities of your class
Use case
The distinction between a message that asks for what a sender wants and a message that tells the receiver how to behave may seem subtle but the consequences are significant
trip
and mechanic
mechanic
HOW to prepare the bike.mechanic
WHAT to do and leave the implementation details up to the mechanic.The best possible situation is for an object to be completely independent of its context. An object that could collaborate with others without knowing who they are or what they do could be reused in unanticipated and novel ways
Recall the use case: A customer, in order to choose a trip, would like to see a list of available trips of appropriate difficulty, on a specific date, where rental bicycles are available
Customer
, Trip
, and Bicycle
TripFinder
class that is responsible for finding suitable trips
Methods in the public interface should:
public
, protected
, and private
JP’s: HackingWithSwift
John’s Pick: MacStadium.com -
To collaborate, an object must know something about others. Knowing creates a dependency. If not managed carefully, these dependencies will strangle your application
An object has a dependency when it knows:
Gear
expects a class named Wheel
to existself
.
Gear
expects a Wheel
instance to respond to diameter
Gear
knows that Wheel.new
requires a rim
and a tire
Gear
knows the first argument to Wheel.new
should be rim
and the second should be tire
see 1_inject_dependencies.rb
Wheel
class changes, the gear_inches
method must also changegear_inches
is explicitly saying that it is only willing to calculate gear inches for instances of Wheel
Gear
will only collaborate with any other kind of object even if that object has a diameter and uses gears!It's is not the class of the object that's important, it's the message you plan to send to it.
Gear
needs access to an object that can respond to diameter
- a duck typeWheel
instance outside of the classsee 2_isolate_dependencies.rb
Isolate Instance Creation
Wheel.new
from gear_inches
and into Gear
's initialize
methodWheel
into its own wheel
methodIsolate Vulnerable External Messages
gear_inches
depends on Gear
responding to wheel
and wheel
responding to diameter
diameter
method to hold wheel.diameter
, we remove the dependency within gear_inches
see 3_remove_arg_orer_dependencies.rb
Use Hashes for Initialization Arguments
initialize
method must be passed in the correct order. we can pass an object instead to remove this dependencyExplicitly Define Defaults
fetch
method to set defaults when using hashes in our initialize
methodfetch
expects the key you're fetching to be in the hash and supplies several options for handling missing keysfetch
will only set the default if the key is not found in the hashGear
depending on Wheel
or diameter
- but the code could have easily been written so that Wheel
depends on Gear
or ratio
Depend on things that change less often
John’s pick - Pick Krisp -https://krisp.ai
The foundation of an object-oriented system is the message, but the most visible organizational structure is the class
Questions to ask yourself:
A class should do the smallest possible useful thing; that is, it should have a single responsibility
Small Gears
Large Gears
harder to pedal, fast
sends you flying down those steep hills
one pedal rotation with your foot might cause the tires to rotate multiple times
Let's start with a small script and then extrapolate classes out of it:
chainring = 52
cog = 11
ratio = chainring / cog.to_f
puts 'Large Gear:'\
"\n#{chainring}-tooth chainring"\
"\n#{cog}-tooth cog"\
"\n#{ratio.round(2)} rotations"
chainring = 30
cog = 27
ratio = chainring / cog.to_f
puts "\nSmall Gear:"\
"\n#{chainring}-tooth chainring"\
"\n#{cog}-tooth cog"\
"\n#{ratio.round(2)} rotations"
Since we're talking about gears, it only makes sense that we start by creating a Gear
class based on the behavior above
see 1_gear.rb
Our Gear
class has three methods: chainring
, cog
, and ratio
Gear
is a subclass of Object
and thus inherits many other methods besides the three that we defined
What I'm trying to say is that the complete set of behavior / the total set of messages to which it can respond is fairly large
This is great and all - but what if we want to extend the functionality by taking into account the effect of the difference in wheels
Consider this formula
gear inches = wheel diameter × gear ratio
(where)
wheel diameter = rim diameter + (2 × tire diameter)
see 2_gear.rb
Gear.new(52, 11)
no longer works because we added 2 more arguments to our initialize
methodGear
class - perhaps it is doing too muchgear_inches
, which is fine - but calculating the tire
size seems a little weirdGear
class, there's something off about having rim
and tire
in there.Gear
is transparent and reasonable - this doesn't mean that we have great design. All it means is that we have no dependenciesGear
lies about its responsibilities as it has multiple responsibilities in that it has to do "wheel" calculations in our gear_inches
messageHere are some techniques that help you write code that embraces change
Hide Instance Variables
Always wrap instance variables in accessor methods instead of directly referring to variables, like the ratio
method does.
We can do this by using an attr_reader
def ratio
@chainring / @cog.to_f
end
def ratio
chainring / cog.to_f
end
If your instance variable is referred to multiple times and it suddenly needs to change, you're in for a world of hurt.
Your method that wraps your instance variable becomes the single source of truth
One drawback is that because you can wrap any instance variables in methods, its possible to obfuscate the distinction between data and objects
But the point is that you should be hiding data from yourself.
Hiding data from yourself protects code from unexpected changes
Hide Data Structures
see 3_obscuring_references.rb
Struct
class to wrap a structuresee 4_revealing_references.rb
diameters
method now has no knowledge of the internal structure of the arraydiameters
just know that it has to respond to rim
and tire
and nothing about the data structurewheelify
methodExtra Extra Responsibilities from Methods
def diameters
wheels.collect { |wheel| wheel.rim + (wheel.tire * 2) }
end
this method clearly has two responsibilities
we can separate these into two methods that each have their own responsibility
def diameters
wheels.collect { |wheel| diameter(wheel) }
end
def diameter(wheel)
wheel.rim + (wheel.tire * 2)
end
separating iteration from the action that's being performed on each element is a common case of multiple responsibilities
Wheel
class from our Gear
classsee 5_gear_and_wheel.rb
A weekly podcast about development and design through the lens of amazing books, chapter-by-chapter.
Pivot a bit: Less agnostic, more useful to just lean into the technologies we use every day for a while.
We’ll do our best to keep the information generally useful to all software developers.
Moving forward this is a Web Development Podcast covering Ruby on Rails, Javascript and React.
New book:
Practical Object-Oriented Design in Ruby by Sandi Metz
Also known as POODR
About the Author:
Sandi Metz: She is one of the foremost thought leaders in clean code.
If you want some amazing programming talks just look up Sandi Metz on YouTube.
About the book:
“The Complete Guide to Writing Maintainable, Manageable, Pleasing, and Powerful Object-Oriented Applications”
About Object-Oriented Design:
Object-oriented applications are made up of objects and the messages that pass between them. Messages will turn out to be the more important of the two, but in this brief introduction (and in the first few chapters of the book) the concepts will get equal weight.
“In a world of objects, new arrangements of behavior emerge naturally. You don’t have to explicitly write code for the spouse_steps_on_cat procedure, all you need is a spouse object that takes steps and a cat object that does not like being stepped on. Put these two objects into a room together and unanticipated combinations of behavior will appear.”
“Unfortunately, something will change. It always does. The customers didn’t know what they wanted, they didn’t say what they meant…. Even applications that are perfect in every way… change is ubiquitous and omnipresent”
WHY IS CHANGE SO HARD!?
Dependencies stand in the way of change
Object Oriented Design is about Managing Dependencies
“In the absence of design, unmanaged dependencies wreak havoc because objects know too much about one another.”
“Part of the difficulty of design is that every problem has two components. You must not only write code for the feature you plan to deliver today, you must also create code that is amenable to being changed later.”
Design Principles
Design Patterns
Service Objects, Factory, Adapter, Decorator - This book doesn’t cover these.
Big Up Front Design Pitfalls
Design takes time
Next Chapter - we really get our hands dirty
Sandi Metz Links:
https://www.youtube.com/watch?v=npOGOmkxuio&t=1841s
https://www.youtube.com/watch?v=29MAL8pJImQ
https://www.youtube.com/watch?v=8bZh5LMaSmE&t=1s
Pick:
JP: https://testingjavascript.com/
John: SOLID Design Patterns in Javascript
https://www.youtube.com/watch?v=GtZtQ2VFweA&feature=share
- - - - -
New Book: Practical Object-Oriented Design
Examples of when to not "fail fast":
Sometimes you just need a way to proceed through steps and have the system tell you what parts succeeded and what parts failed
Sideband data
When communication failures without resorting to exceptions, we need a sideband: a secondary channel of communication for reporting meta-information about the status and disposition of a process.
Multiple return values
hehe, this reminds me of stuff I do in javascript
ruby supports multiple return values in the form of array splatting. in JS, you could do this with destructuring
def foo
result = 42
success = true
[result, success]
end
result, success = foo
puts "#{success ? 'succeeded' : 'failed'}; result #{result}"
Or you can use an open struct
def foo
OpenStruct.new(:result => 42, :status => :success)
end
Output parameters
Caller-supplied fallback strategy
if we're not sure we want to terminate the execution of a long process by raising an exception, we can inject a failure policy into the process
def make_user_accounts(host, failure_policy=method(:raise))
# ...
rescue => error
failure_policy.call(error)
end
def provision_host(host, failure_policy)
make_user_accounts(host, failure_policy)
end
policy = lambda { |e| puts e.message }
provision_host("192.168.1.123", policy)
JP:
John:
Failure flags and benign values
Sometimes responding with a nil
is good enough, i.e.
def save
# some failing code
rescue
nil
end
Related to this is the concept of "benign values"
The system might replace the erroneous value with a phony value that it knows to have a benign effect on the rest of the system
When the system's success doesn't depend on the outcome of the method in question, using a benign value may be the right choice. Benign values are also helpful in making the code more testable.
Example:
begin
response = HTTP.get_response(url)
JSON.parse(response.body)
rescue Net::HTTPError
{ 'stock_quote' => '' }
end
'ing, we can use
warn`Warning as errors
Check out this hack:
module Kernel
def warn(message)
raise message
end
end
warn 'uh oh'
Remote failure reporting
Circuit breaker pattern
Ending the program
exit
ends the whole programexit
in the Whiz Tutor codebase?John: User Onboard - https://www.useronboard.com/ by https://twitter.com/samuelhulick
JP: singlediv.com - https://twitter.com/samuelhulick
In this short season, we are going through EXceptional Ruby by Advi Grimm
Let's talk about some definitions first:
"Failures cause exceptions which are due to errors"
raise
or fail
methods🗣 Discussion: When do you find yourself using raise
?
🗣 Discussion: When do you find yourself using rescue
?
rescue
clause should be a short sequence of simple instructions designed to bring the object back to a stable state and to either retry the operation or terminate with a failuresyntax
Starts with the rescue
keyword, followed by one or more classes or modules to match, then a hash rocket and the variable name to which the matching exception will be assigned
Subsequent lines of code up to an end
keyword will be executed if the rescue
is matched
rescue IOError => e
puts "Error while writing to file: #{e.message}"
end
Moar Code
begin
raise RuntimeError, 'specific error'
rescue StandardError => error
puts "Generic error handler: #{error.inspect}"
rescue RuntimeError => error
puts "runtime error handler: #{error.inspect}"
end
🗣 Discussion: Have you ever used retry
?
tries = 0
begin
tries += 1
puts "trying #{tries}"
raise
rescue
retry if tries < 3
puts 'I give up'
end
Picks:
JP: Overcast https://overcast.fm/
John: Apple Refurbished
Welcome to Iteration: A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter
Ask yourself:
there are no silver bullets
Picks:
https://www.notion.so/ - How meta - we use Notion to manage this podcast.
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
John: How / Why do they grow? Needs change:
John: All the different use cases for a user
John:
"When you need to implement password recovery, and do not have a clear, single place to put the logic, it will still find its way into your code. It will spread itself across existing classes, usually making those classes harder to read and use.”
Example problem: Want to send a welcome email when a user is created via a public form but not when an admin creates a user via a backend interface
Core models should only have the absolute minimum to exist:
Core models should NOT have these things: (these things belong in multiple, interaction-specific form models)
virtual attributes that don't map 1:1 with db
callbacks to fire for a particular screen or use case (i.e. form signup)
we want the perks of AR models with AR. solution: inheritance
class User::AsSignUp < User
validates :password, presence: true, confirmation: true
after_create :send_welcome_email
private
def send_welcome_email; end
end
John: Note the "AsSignup" pattern - "AsFacebookAuth"
def self.something
class Invoice < ActiveRecord::Base
has_many :items
end
class Item < ActiveRecord::Base
belongs_to:invoice
end
Why not just:
class Invoice::Item < ActiveRecord::Base
belongs_to:invoice
end
and move the file to: app/models/invoice/item.rb
The recommendations are a lot like BEM - A front-end development methodology - learn more at: http://getbem.com/
Abstracts (Sizing, Boarders, Spacing)Base (Grid, Colors, images, Typography)Components (Buttons, Cards, Alerts)Page Specific CSS
Picks:
Growing Rails Applications in Practice: Part 1/3: New Rules For Rails
Welcome to Iteration: A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter
An Inconvenient Secret: Large applications are large
This book is about scaling your codebase. The amount of pain you feel should be logarithmic, not exponential.
This is not about revolutionary design patterns or magic gems that make all your problems go away. Instead, we will show you how to use discipline, consistency, and organization to make your application grow more gently.
Beautiful Controllers
Should functionality go into the model or the controller?!
"Less business logic in our controllers, the better"
The authors argue for a standard controller design for every single user interaction. that is to say, it should only handle HTTP requests
EVERYTHING is CRUD
example of a stripped-down controller where Note controller never talks to the model directly.
"Every controller action reads or changes a single model. even if an update involves multiple models, the job of finding and changing the involved records should be pushed to an orchestrating model"
controllers should contain the minimum amount of glue to translate between the request, your model, and the response
Relearning Active Record
Data integrity with callbacks -> later in the book, we'll talk about how to not use so many callbacks
bad:
class Invite < ActiveRecord::Base
def accept! (user)
accepted = true
Membership.create!(user: user)
end
end
invite.update(accepted: true) # => circumventing the accept! method
better:
after_save :create_membership_on_accept
private
def create_membership_on_accept
if accepted && accepted_changed?
Membership.create!(user: user)
end
end
User interactions without a database
Not all user interactions need an active record model.
Example: sign in form that uses sessions. when the form is submitted, you don't end up inserting a row in a table in your db
start taking your controllers from hell -> putting that logic in your model (models from hell?)
you know things are a pain when you have to use form_tag and can't use form_for
one thing to note is that the example sends notifications (i.e. SMS, email) in their model and not their controller
Welcome to Iteration - A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
In this more casual episode, we recap some of our favorite tips from the Pragmatic Programmer in the context of our recent projects and lessons. We talk though caring about your craft, not leaving any broken windows and more.
Picks:
John - http://www.hemingwayapp.com/
JP - better touch tool
John: Welcome to Iteration: A weekly podcast about programming, development, and
design through the lens of amazing books, chapter-by-chapter.
JP: This is part 2 of Chapter 8 - THE FINAL CHAPTER!
Identify and test significant program states. Just testing lines of code isn't enough
JP: Even if you test every single line of code - that's not what matters. What matters is how many different permutations of your app's state you have covered. drops mic
John: Coverage tools are nice - but they only give you a window into the state passed into it. If you can extract state out into separate objects or methods to be able to test them decoupled from time.
Once a human tester finds a bug, it should be the last time a human tester finds that bug. Automatic tests should check for it from then on.
JP: We don't have time to find a bug more than once... "We have to spend our time writing new code - and new bugs"
John: Step one of debugging - write a test that's failing. I broke this pattern this weekend. :(
Write docs as you would write code: honor the DRY principle, use metadata, MVC, auto-generation and so on
JP: don't dread writing docs. it's part of your application. I think this tip is phrased in such a way to appeal to engineers. think of documentation writing as writing code, not writing literature
John: I like this in theory - I'm having trouble getting tooling in place for this that makes sense. I really want to dynamically generate, external API docs, internal docs and user guides totally automatically. Super struggling to get anything moving in rails.
Documentation created separately from code is less likely to be correct and up to date
JP: sometimes you need documentation. obviously, name your variables well, but sometimes explain what a function does or why it does it. at OL we'll sometimes write include the GitHub issue number for a weird quirk or to explain why a test is testing for certain functionality. treat docs like code. part of the code, not separate from it
John: I feel like this is a bit outdated. If written well modern languages really can be self-documenting. Basecamp really doesn't "do" code comments or internal docs - Per DHH - If there is a comment explaining a method or model I break it up further until it doesn't need explaining. I worship in the church of Henninger-Hansen.
Come to understand your users' expectations, then deliver just that little bit more.
JP: "Never lose sight of the business problems your application is intended to solve".
John: One of my favorite parts of the job is delivering features users get super jazzed about.
Craftspeople of an earlier age were proud to sign their work. You should be, too
"Anonymity, especially on large projects, can provide a breeding ground for sloppiness, mistakes, sloth, and bad code. [...] We want to see a pride of ownership. Your signature should come to be recognized as an indicator of quality. A really professional job. Written by a real programmer. A Pragmatic Programmer"
JP: lol, git blame
John: Take pride in what you do.
Picks
JP: https://github.com/sindresorhus/refined-github
John: LG 22MD4KA-B UltraFine 4K Display 21.5" UHD 4096x2304 4xUSB-C
Next week: Pragmatic Programmer in Practice - Book recap in the context of our real-life development work.
John: Welcome to Iteration: A weekly podcast about programming, development, and
design through the lens of amazing books, chapter-by-chapter.
JP: This is part 1 of Chapter 8
John: This chapter is all about "Pragmatic Projects" - Teams, Automation, Testing, Documentation Code quality and more.
Don't separate designers from coders, testers from data modelers. Build teams the way you would build code.
JP: It's a mistake to think that the activities of a project - analysis, design, coding, and testing - can happen in isolation. i.e. Offers V2 at OL. Leaders of a team: needs at least 1 technical and 1 administrative personnel. Always think of the business goals
John: It's nice to have lots of full stack devs - They can focus more on a "Module" than a specific tech or "side" of the project.
At the dawn of the age of automobiles, the instructions for starting a Model-T Ford were more than two pages long. With modern cars, you just turn the key—the starting procedure is automatic and foolproof.
John: We are developers! Why would we do ANY tedious work? Example: Github's API pulls in PR's and notes.
A shell script or batch file will execute the same instructions, in the same order, time after time
JP: "We may have to build the starter and fuel injector from scratch, but once it's done, we can just turn the key from then on" i.e. deploys
Let the computer do the repetitious, the mundane—it will do a better job of it than we would.
Tests that run with every build are much more effective than test plans that sit on the shelf.
JP: In the Smalltalk world, they say, "Code a little, test a little" -> Get those small wins and make incremental changes
John: Write tests to help guide design.
'Nuff said
JP: Keeping your feature branch green!
John: ALL the tests - unit, integration, performance, staging, usability, QA
Introduce bugs on purpose in a separate copy of the source to verify that testing will catch them.
JP: After you have written a test to find a particular bug, cause the bug on purpose to make sure the test complains
John: Code coverage analysis tools are very helpful
Picks
John: Welcome to Iteration: A weekly podcast about programming, development, and
design through the lens of amazing books, chapter-by-chapter.
JP: Welcome to PART 2 of Chapter 7: "Before The Project"
You've been building experience all your life. Don't ignore
nagging doubts.
JP: Follow your instincts when starting a project - but don't
procrastinate - you can do this by prototyping. Proof of concepts are nice
when you tackle the "hard" thing first. Prototype to discover
John: Prototype, prototype!
"as the prototype progresses you may have one of those moments of revelation when you suddenly realize that some basic premise was wrong."
Don't fall into the specification spiral - at some point you need to start
coding.
JP: "Program specification is the process of taking a requirement and reducing
it down to the point where a programmer's skill can take over." -
John:
"natural language is really not up to the job."
more than 1 bullet point alert
Don't blindly adopt any technique without putting it into the context of your
development practices and capabilities
This shows how dated the book is. examples of formal methods: CASE tools,
waterfall development, "the spiral model", to today's UML diagrams.
If this were written today, we'd talk about lean methodology, agile development,
SCRUM
You should work constantly to refine and improve your process
Beware of vendor hype, industry dogma, and the aura of the price tag. Judge
tools on their merits.
John:
Try not to think about how much a tool cost when you look at its output.
JP:
If you're an Apple fan boy/girl, you might be interested in what Steve Jobs had
to say about Object-Oriented Programming. This is an excerpt from a 1994 Rolling
Stone interview where Steve (not a programmer) explains OOP in simple terms.
Jeff Goodell: Would you explain, in simple terms, exactly what object-oriented
software is?
Steve Jobs: Objects are like people. They’re living, breathing things that have
knowledge inside them about how to do things and have memory inside them so they
can remember things. And rather than interacting with them at a very low level,
you interact with them at a very high level of abstraction, like we’re doing
right here.
Here’s an example: If I’m your laundry object, you can give me your dirty
clothes and send me a message that says, “Can you get my clothes laundered,
please.” I happen to know where the best laundry place in San Francisco is. And
I speak English, and I have dollars in my pockets. So I go out and hail a
taxicab and tell the driver to take me to this place in San Francisco. I go get
your clothes laundered, I jump back in the cab, I get back here. I give you your
clean clothes and say, “Here are your clean clothes.”
You have no idea how I did that. You have no knowledge of the laundry place.
Maybe you speak French, and you can’t even hail a taxi. You can’t pay for one,
you don’t have dollars in your pocket. Yet, I knew how to do all of that. And
you didn’t have to know any of it. All that complexity was hidden inside of me,
and we were able to interact at a very high level of abstraction. That’s what
objects are. They encapsulate complexity, and the interfaces to that complexity
are high level.
John: Time Timer - https://www.timetimer.com/ - Pomodoro - Physical Device
John: Welcome to Iteration: A weekly podcast about programming, development, and
design through the lens of amazing books, chapter-by-chapter.
JP: Welcome to PART 1 of Chapter 7: "Before The Project."
Starting a project can be a daunting task. There are a lot of unknowns and you
might not know when you should start. We're going to talk about some of the
things that will guide you when starting a project from scratch. Our focus will
be gathering and understanding requirements
For me, this is great because though I work at OL, I might be taking on a
freelance client soon!
John:
"Perfection is achieved, not when there is nothing left to add, but when there is nothing left to take away...."
Requirements rarely lie on the surface. They're buried deep beneath the layers
of assumptions, misconceptions, and politics
JP: You can't just "gather" requirements as if they exist. You must do RESEARCH.
Remember that you're solving business problems
It's the best way to gain insight into how the system will really be used
JP: OBSERVE users for a week - this is much different than "thinking" like a
user. I think that if you do the latter, you end up with preconceived notions
based on your own assumptions.
John:
"It's important to discover the underlying reason why users do a particular thing, rather than just the way they currently do it."
John:
"...the simplest statement that accurately reflects the business need is best."
Invest in the abstraction, not the implementation. Abstractions can survive
the barrage of changes from different implementations and new technologies
Requirements are not architecture. Requirements are not design, nor are they
the user interface. Requirements are need
JP: Don't sweat implementation details. Requirements should be abstract
Create and maintain a single source of all the specific terms and vocabulary
for a project
JP: Create a literal glossary so that you and stakeholders can have a
UBIQUITOUS LANGUAGE #domaindrivendesign
- i.e. "client" and "customer"
might be the same - they might be different.
Also - you want this to live in a document that's shared. Don't know how serious
that is but this is what the author's recommend for serious projects
John:
Gordius, the King of Phrygia, once tied a knot that no one could untie. It was said that he who solved the riddle of the Gordian Knot would rule all of Asia. So along comes Alexander the Great, who chops the knot to bits with his sword. Just a little different interpretation of the requirements, that's all... and he did end up ruling most of Asia.
When faced with an impossible problem, identify the real constraints. Ask
yourself: "Does it have to be done this way? Does it have to be done at all?"
JP: Find the constraints of the box so that you can solve the problem at hand.
You have to think of every possible avenue so that you don't dismiss potential
solutions. I really like this:
Consider the Trojan horse - a novel solution to an intractable problem. How do
you get troops into a walled city without being discovered? You can be that
"through the front door" was initially dismissed as suicide.
Too many quotes alert
Many times a reinterpretation of the requirements can make a whole set of
problems go away [...]. All you need are the real constraints, the misleading
constraints, and the wisdom to know the difference.
JP: Swift - The Big Nerd Ranch Guide. Plenty of reasons why I want to learn
Swift.
John: Welcome to Iteration: A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
JP: This is part 2 of chapter 6, "While you are coding". Last week we talked about pragmatic practices while you are coding.
Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code when it needs it. Fix the root of the problem
Time pressure is often used as an excuse for not refactoring. But his excuse just doesn't hold up: fail to refactor now, and there'll be far greater time investment to fix the problem down the road - when there are more dependencies to reckon with. Will there be more time available then? Not in our experience
Advice:
Keep track of the things that need to be refactored. If you cna't refactor something immediately, make sure that it gets placed on the schedule. Make sure that users of the affected code know that it is scheduled to be refactored and how it might affect them.
Martin Fowler's tips for refactoring
1.) don't try to refactor and add functionality at the same time
2.) make sure you have good tests in place before you begin refactoring
3.) take short, deliberate steps
What's your tolerance for pain?
Start thinking about testing before you write a line of code
John: If your tests are hard to write - the design of your system is probably inelegant. It's a "design smell" if you are thinking - how the hell am I going to test this?
Test ruthlessly. Don't make your users find bugs for you.
HOT QUOTE ALERT
Testing is more cultural than technical: we can instill this testing culture in a project regardless of the language being used.
John: Related: Re-create bugs in tests when debugging. every. time.
Wizards can generate reams of code. Make sure you understand all of it before you incorporate it into your project
We are not against wizards [...] But if you do use a wizard, and you don't understand all the code that it produces, you won't be in control of your own application. You won't be able to maintain it, and you'll be struggling when it comes time to debug
PICKS
JP: https://www.howtographql.com/
John: Jesus Castello - Ruby Guides on YouTube
John: Welcome to Iteration: A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
JP: Chapter 6 "While you are coding" Summary / Introduction - In this section, we will be discussing the things a programmer thinks about during the process of coding.
The section kicks off by talking about how coding is not a mechanical process. Adjustments must be made while we code. It's largely driving a car. Our brain goes into auto-pilot - however, an attentive driver is always assessing the current situation. Is someone about to cross the street? Etc.
Rely only on reliable things. Beware of accidental complexity, and don't confuse a happy coincidence with a purposeful plan
JP: really funny metaphor about a solider coming to a false conclusion in a minefield. "As developers, we also work in minefields."
You can't know why something is broken if you didn't know why it worked in the first place
John: It's easy to assume that X causes Y, but as we've said - don't assume it, prove it.
John: Be deliberate.
Get a feel for how long things are likely to take before you write code
JP: Basically, big O stuff: constant, logarithmic, linear, exponential. Use a greedy approach when you can. Try to think about how you can do something in a single pass. But always remember the context. Maybe your data isn't so large that an exponential algorithm is just fine for the sake of readability.
"Pragmatic programmers try to cover both the theoretical and practical bases. After all this estimating, the only timing that counts is the speed of your code, running in the prod env. with real data."
John: If I have a super slow method or view it’s usually because I need a new object or attribute.
Mathematical analysis of algorithms doesn't tell you everything. Try timing your code in its target environment
JP: "Be wary of premature optimization. It's always a good idea to make sure an alg really is a bottleneck before investing your precious time trying to improve it"
John: In general: Tests pass - I ship. I'd rather just throw more Dyno's at my methods than too much time optimizing.
PICKS
JP: browserstack.com
John: Postman - specifcally SET UP ENVIROMENTS
John: Greedy Algorithms
A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
The view is an interpretation of the model. It doesn't need to be graphical. The controller is more of a coordination mechanism, and doesn't have to be related to any sort of input device.
JP: Use blackboards to coordinate disparate facts and agents, while maintaining independence and isolation among participants
John: The blackboard style of programming removes the need for so many interfaces, making for a more elegant and consistent system.
John: "Feed" concept
Seriously... just look how cool this is.
defmodule MyList do
def flatten([ [sub_head | sub_tail] | tail]) do
flatten(sub_head) ++ flatten(sub_tail) ++ flatten(tail)
end
def flatten([ head | tail]) do
flatten(head) ++ flatten(tail)
end
def flatten([]), do: []
def flatten(head), do: [head]
end
IO.inspect MyList.flatten [ 1, [ 2, 3, [ 4 ] ], 5, [ [ [ [ 6 ] ] ] ] ]
# [1, 2, 3, 4, 5, 6]
John: Welcome to Iteration: A weekly podcast about programming, development, and design through the lens of amazing books, chapter-by-chapter.
Quick update: Sketch Color Spaces
Today we'll be going through Chapter 5, "Bend or Break" - where we talk about writing flexible code. This is especially important for software engineers in a profession where things are constantly changing. (insert joke about JavaScript frameworks). We will largely focus on different ways we can decouple our code!
Life doesn't stand still. Neither can the code that we write. In order to keep up with today's near-frantic pace of change, we need to make every effort to write code that's as loose—as flexible—as possible.
Organize code into modules and limit interaction between them. If one module gets compromised and has to be replaced, the other modules should be able to carry on.
Avoid coupling by writing shy code and applying the law of Demeter
What is shy?
selection.getRecorder().getLocation().getTimeZone()
Implement technology choices for an application as configuration options, not through integration or engineering
Program for the general case, and put the specifics outside the compiled code base
valid_send_days
Exploit the concurrency in your user's workflow
This example was really good so I'm copying it from the book:
making a pina colada
1 open blender
2 open pina colada mix
3 put mix in blender
4 measure 1/2 cup white rum
5 pour in rum
6 add 2 cups of ice
7 close blender
8 liquefy for 2 mins
9 open blender
10 get glasses
11 get pink umbrellas
12 serve pina coladas
Think about how imperative this is. First do this... then do this...
BUT, think about what you can do concurrently: 1, 2, 4, 10, 11. These can happen all at the same time and up front. Next, 3, 5, and 6 can happen concurrently afterwards. These would be big optimizations
“Pragmatic Programmers code in defenses against their own mistakes.”
John: To me this means testing and never assuming the user is wrong.
https://github.com/egonSchiele/contracts.ruby
"You can think of contracts as assert
on steroids"
This says that double expects a number and returns a number. Here's the full code:
require 'contracts'
class Example
include Contracts::Core
include Contracts::Builtin
Contract Num => Num
def double(x)
x * 2
end
end
puts Example.new.double("oops")
be strict in what you will accept before you begin, and promise as little as possible in return. Remember, if your contract indicates that you'll accept anything and promise the world in return, then you've got a lot of code to write!
What is a "correct" program?
“What is a correct program? One that does no more and no less than it claims to do. Documenting and verifying that claim is the heart of Design by Contract”
“It's much easier to find and diagnose the problem by crashing early, at the site of the problem.”
John: In ruby using rescue to aggressively just pushes the problem up. Not crashing but not working properly.
When your code discovers that something that was something to be impossible just happened, your program is no longer viable
A dead program normally does a lot less damage than a crippled one
"This application will never be used abroad, so why internationalize it?"
Let's not practice this kind of self-deception, particularly when coding
John: Write tests prove it won’t be used in a certain way.
try...catch
- ask yourself: "will this code still run if I remove all of the exception handlers". if the answer is, "no" then maybe exceptions are being used in nonexceptional circumstancesJohn: Error and an exception are two different things. Very loosely: one is based on incorrect inputs the other is an error in a process.
Programs that use exceptions as part of their normal processing suffer from all the readability and maintainability problems of classic spaghetti code. These programs break encapsulation routines and their callers are more tighlting coupled via exception handling
John: Garbage collection. We are lucky as most major frameworks do garbage collection for us.
John: I currently have this problem with action-cable web-socket connections. I am opening them and not managing the closing of these connections well. So it’s leading to performance issues.
Email sending: make sure it delivered. Handle the exception, finish what you started!
Stubs/doubles vs mocks
Stub is simple fake object. It just makes sure test runs smoothly.
Mock is smarter stub. You verify Your test passes through it.
Good stack exchange link on this
JP: "what does your program think is going on": DON'T BLAME EXTERNAL FACTORS FIRST. It's probably your code haha!
John: why, when faced with a "surprising" failure, you must realize that one or more of your assumptions is wrong.
JP: "routine" code isn't infallible! did you test all of the edge cases?
I really like the debugging checklist so here it is:
John: Duplicate the problem in tests.
examples of text manipulation:
JP: Funny enough, Hunt and Thomas like using Ruby (and Perl) to quickly hack short scripts
John: I want to push more into this - Just barely experimenting with self-creating API docs. Even just things like in ruby: writing a rake task to pull out all your custom objects and methods to start docs and get a clear picture has been helpful for me.
passive vs active code generators
passive = run once to produce a result
active = run every time you need a result. results are then thrown away
JP: meta programming? code gen doesnt have to be meta
John: Refactoring methods to "Find common resources" based on "Model" name - Reducess code significantly.
Every craftsman starts his or her journey with a basic set of good quality tools
Discussion: What are your tools?
Tools become conduits from the craftsman's brain to the finished product - they have become extensions of his or her hands
Always be on the lookout for better ways of doing things
JP: plain text doesn't become obsolete - as opposed to binary. this seems obvious. this is mostly about readability
JP: you can do everything in the shell that you do using the GUI: launch apps, browsers; search files; touch
, mkdir
, rm -rf
. basically i need to get better at this. touch newfile.rb
is faster than right click > new file > newfile.rb > carriage return
JP: fuck IDE's, VIM all the way, baby!!! I no longer rely on auto complete and it's amazing. The editor is an extension to your hand
JP: the front end devs at my job don't check their files into git and it blows my mind.
JP: "it doesn't really matter whether the bug is your fault or someone else's. it is still your problem". suck it up!
JP: don't waste energy denying that a bug is possible. clearly, it is. just breathe
Picks
JP: I love doing this during "exploration" - careful not to use prototypes in prod 👀
John: prototype vs tracer bullet - Expectations: Remind them that you can build a great prototype of a new car out of balsa wood and duct tape, but you wouldn't try to drive it in rush-hour traffic! - Localhost with ngrok
JP: Remember to focus on domain problems and not petty implementation details
John: Let your code be english! - Let it reflect the way your team talks. execute_email_delivery_protical
vs send_email
JP: Be deliberate and keep track... wording is key (i.e. specificity)
John: Reality - scope is a Moving target - Tracer code and testing helps make sure estimates are well thought out. Charge to estimate / mockup.
JP: Keep an open line of communication about expectations for scheduling
John: What to say when you are asked for an estimate "I'll get back to you" - Scope can be revised. Not just timeline.
Overview = combine ideas and processes
This chapter is truly about a "pragmatic" approach to development
Duplicated code arises differently:
we call these the "four i's"
"shortcuts make for long delays"
number 4 is a result of large teams - not having a --- dare I say --- a ubiquitous language
you need good communication to quell number 4
READ DOCS
Tip: Lean on code and programmatically generated things to prevent repeating yourself.
TWO OR MORE THINGS are orthogonal if changes in one do not affect any of the others
i.e. database code will be orthogonal to the UI. you can change the interface without affecting the database
driving stick shift is not orthogonal
helicopter controls are not orthogonal
bottom line: non-orthogonal systems are hard to maintain
You get two major benefits if you write orthogonal systems: increased productivity and reduced risk.
ways orthogonality can be applied to your work
if i dramatically change the requirements behind a particular function, how many modules are affected?
Toolkits and Libraries
Testing
An orthogonally designed and implemented system is easier to test. Because the interactions between the system's components are formalized and limited, more of the system testing can be performed at the individual module level. This is good news, because module level (or unit) testing is considerably easier to specify and perform than integration testing.
Reversability
Nothing is more dangerous than an idea if it's the only one you have.
Writing more orthogonal code allows you to more easily reverse changess or eb and flow with the needs of the project.
Bottom line: orthognality is about reduction of interdependency among system components
instead of carving decisions in stone, think of them mroe as being written in the sand at the beach. A big wave can come along and wipe them out at any time.
when firing a machine gun in the dark, you either:
Tracer ammunition (tracers) are bullets or cannon caliber projectiles that are built with a small pyrotechnic charge in their base. Ignited by the burning powder, the pyrotechnic composition burns very brightly, making the projectile visible to the naked eye. This enables the shooter to follow the projectile trajectory to make aiming corrections.
tracer code is not disposable. you write it for keeps. it contains all the error checking, structuring, documentation, and self-checking that any piece of production code has. it simply is not fully functional
Welcome to Iteration: a weekly podcast about programing, development and design through the lens of amazing books, chapter-by-chapter
by Andy Hunt and Dave Thomas
This book will help you become a better programmer
this book was written in freaking 1999! I was 7.
programming is a craft
"as a programmer, you are part listener, part advisor, part interpreter, and part dictator. you try to capture elusive requirements and find a way of expressing them so that a mere machine can do them justice. you try to document your work so that others can understand it, and you try to engineer your work so that others can build on it. What's more, you try to do all this against the relentless ticking of the project clock. you work small miracle every day"
"you shouldn't be welded to any particular technology, but have a broad enough background and experience base to allow you to choose good solutions in particular situations"
What makes a pragmatic programmer
Tips
"We who cut mere stones must always be envisioning cathedrals."
"great lawns need small amounts of daily care, and so do great programmers."
"1% better every day. 365% bettere every year"
Challenge
hmmmmm.... really gets you thinking
Software entropy - aka Broken window theory - aka software rot
This is a great metaphor:
One broken window, left unrepaired for any substantial length of time, instills in the inhabitants of the building a sense of abandonment - ... so another window gets broken. People start littering. graffiti appears.
"The three soldiers returning home from war were hungry. When they saw the village ahead their spirits lifted—they were sure the villagers would give them a meal. But when they got there, they found the doors locked and the windows closed. After many years of war, the villagers were short of food, and hoarded what they had. Undeterred, the soldiers boiled a pot of water and carefully placed three stones into it. The amazed villagers came out to watch. "This is stone soup," the soldiers explained.
"Is that all you put in it?" asked the villagers. "Absolutely—although some say it tastes even better with a few carrots...." A villager ran off, returning in no time with a basket of carrots from his hoard. A couple of minutes later, the villagers again asked "Is that it?" "Well," said the soldiers, "a couple of potatoes give it body." Off ran another villager."
(don't be the frog who gets boiled gradually)
There will always be tradeoffs. When to ship?
Great software today is often preferable to perfect software tomorrow. If you give your users something to play with early, their feedback will often lead you to a better eventual solution.
Challenges
GOALS - I LOVE this section.
It doesn't matter whether you ever use any of these technologies on a project, or even whether you put them on your resume. The process of learning will expand your thinking, opening you to new possibilities and new ways of doing things.
Don't get swayed by media hype. I'm looking at you create-react-app!
create-react-app
is the best configuration free react setup. someone challenged me and said it's just the best marketedHaving the best ideas, the finest code, or the most pragmatic thinking is ultimately sterile unless you can communicate with other people. A good idea is an orphan without effective communication
these are great soft skills!