<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ivy Puckett</title>
    <description>The latest articles on DEV Community by Ivy Puckett (@ivypuckett).</description>
    <link>https://dev.to/ivypuckett</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F464635%2Fa525942a-a7aa-4298-be40-7849a3299b26.jpg</url>
      <title>DEV Community: Ivy Puckett</title>
      <link>https://dev.to/ivypuckett</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ivypuckett"/>
    <language>en</language>
    <item>
      <title>A long list of weird things I've used in production</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Wed, 18 Mar 2026 05:07:06 +0000</pubDate>
      <link>https://dev.to/ivypuckett/a-long-list-of-weird-things-ive-used-in-production-36n8</link>
      <guid>https://dev.to/ivypuckett/a-long-list-of-weird-things-ive-used-in-production-36n8</guid>
      <description>&lt;p&gt;I've been paid to utilize 80 different software tools in my 8 yrs as an engineer. I've gone deep on some (Go, Regex, SQL Server) and light on others (jq, Ruby). All of them have been interesting.&lt;/p&gt;

&lt;p&gt;I learn two lessons from this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Spend time on fundamentals. No matter where I find myself, I'm grateful I read "Software Architecture: The hard parts." I'm less grateful I read that book on C#.&lt;/li&gt;
&lt;li&gt;Evaluate tradeoffs, not familiarity. Most tools do the same kinds of things. You can write the same app in JS and Rust. Pick the tools that fit your needs, not the ones you've used before.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The categories are illustrative vs comprehensive. I would not say HTML is a programming language for instance.&lt;/p&gt;

&lt;p&gt;I've provided links to a couple niche tools I've found to be very helpful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runtimes

&lt;ul&gt;
&lt;li&gt;Azure Functions&lt;/li&gt;
&lt;li&gt;Lambdas&lt;/li&gt;
&lt;li&gt;EC2 &amp;amp; ECS&lt;/li&gt;
&lt;li&gt;Azure App Service&lt;/li&gt;
&lt;li&gt;Kubernetes&lt;/li&gt;
&lt;li&gt;KEDA&lt;/li&gt;
&lt;li&gt;WordPress&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;CI/CD

&lt;ul&gt;
&lt;li&gt;Azure Devops&lt;/li&gt;
&lt;li&gt;GitHub Actions&lt;/li&gt;
&lt;li&gt;Jenkins&lt;/li&gt;
&lt;li&gt;Terraform&lt;/li&gt;
&lt;li&gt;Cloudformation&lt;/li&gt;
&lt;li&gt;CDK&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Make&lt;/li&gt;
&lt;li&gt;&lt;a href="https://taskfile.dev/" rel="noopener noreferrer"&gt;Taskfile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IAM&lt;/li&gt;
&lt;li&gt;SSM&lt;/li&gt;
&lt;li&gt;SecretsManager&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Async messaging

&lt;ul&gt;
&lt;li&gt;Azure Service Bus&lt;/li&gt;
&lt;li&gt;Azure Event Grid&lt;/li&gt;
&lt;li&gt;SQS&lt;/li&gt;
&lt;li&gt;EventBridge&lt;/li&gt;
&lt;li&gt;RiverQueue&lt;/li&gt;
&lt;li&gt;Temporal&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Reverse proxies / gateways

&lt;ul&gt;
&lt;li&gt;Azure API Manager&lt;/li&gt;
&lt;li&gt;Tyk&lt;/li&gt;
&lt;li&gt;NGINX&lt;/li&gt;
&lt;li&gt;API Gateway&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Low-code

&lt;ul&gt;
&lt;li&gt;Microsoft PowerAutomate and PowerApps&lt;/li&gt;
&lt;li&gt;Microsoft SharePoint&lt;/li&gt;
&lt;li&gt;Windmill&lt;/li&gt;
&lt;li&gt;Braze&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;API Documentation

&lt;ul&gt;
&lt;li&gt;Bruno&lt;/li&gt;
&lt;li&gt;Postman&lt;/li&gt;
&lt;li&gt;&lt;a href="https://httpie.io/" rel="noopener noreferrer"&gt;Httpie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenAPI&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Load testing

&lt;ul&gt;
&lt;li&gt;K6&lt;/li&gt;
&lt;li&gt;Vegeta&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Editors

&lt;ul&gt;
&lt;li&gt;DataGrip&lt;/li&gt;
&lt;li&gt;VisualStudio&lt;/li&gt;
&lt;li&gt;VisualStudioCode&lt;/li&gt;
&lt;li&gt;Neovim&lt;/li&gt;
&lt;li&gt;&lt;a href="https://helix-editor.com/" rel="noopener noreferrer"&gt;Helix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IDEA&lt;/li&gt;
&lt;li&gt;Cursor&lt;/li&gt;
&lt;li&gt;Copilot&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Languages

&lt;ul&gt;
&lt;li&gt;SQL&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/kusto/query/?view=microsoft-fabric" rel="noopener noreferrer"&gt;KQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;XML (included because I have some war stories haha)&lt;/li&gt;
&lt;li&gt;PHP&lt;/li&gt;
&lt;li&gt;Regex (included because I think I'm more practiced than ~95% of devs)&lt;/li&gt;
&lt;li&gt;Protobufs (yes I've written these by hand)&lt;/li&gt;
&lt;li&gt;C#&lt;/li&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;JS&lt;/li&gt;
&lt;li&gt;Angular&lt;/li&gt;
&lt;li&gt;Ruby&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Rust&lt;/li&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Go&lt;/li&gt;
&lt;li&gt;Cucumber&lt;/li&gt;
&lt;li&gt;WPF / .NET Framework / .NET Core&lt;/li&gt;
&lt;li&gt;SOAP (now that was hellish)&lt;/li&gt;
&lt;li&gt;ThreeJS (I was paid to make a procedurally generated 3D galaxy renderer. That was cool)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Database-like

&lt;ul&gt;
&lt;li&gt;Athena&lt;/li&gt;
&lt;li&gt;SQL Server&lt;/li&gt;
&lt;li&gt;Oracle&lt;/li&gt;
&lt;li&gt;Postgres (best SQL db imo)&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;&lt;a href="https://steampipe.io/" rel="noopener noreferrer"&gt;Steampipe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Azure Blob Storage&lt;/li&gt;
&lt;li&gt;Azure SQL&lt;/li&gt;
&lt;li&gt;DDB&lt;/li&gt;
&lt;li&gt;S3&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pressly/goose" rel="noopener noreferrer"&gt;Goose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;EntityFramework&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;What tools have you used? I'd love to hear about them.&lt;/p&gt;




&lt;p&gt;Photo Credit: &lt;a href="https://unsplash.com/photos/an-intricate-antique-mechanical-device-on-a-wooden-base-sJsFEnp_bfk" rel="noopener noreferrer"&gt;The New York Public Library&lt;/a&gt;&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>7 Dumb things I'd do if I started a software company</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Fri, 21 Nov 2025 04:08:45 +0000</pubDate>
      <link>https://dev.to/ivypuckett/7-dumb-things-id-do-if-i-started-a-software-company-4khi</link>
      <guid>https://dev.to/ivypuckett/7-dumb-things-id-do-if-i-started-a-software-company-4khi</guid>
      <description>&lt;p&gt;Life is short, be proud of your work.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. I'd contribute to small companies
&lt;/h2&gt;

&lt;p&gt;AWS is probably the right choice because of it's 5 9s of availability on its core services. I've been on the other side and I trust that when something goes wrong, someone is aware and actively working to fix it before I even knew about it.&lt;/p&gt;

&lt;p&gt;...Also, I want to support a diverse cloud market so instead of making the right choice, I'd probably go with startups like fly.io, tigris, clerk, and lemonsqueezy... not that I've thought about this or anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Not use SQL
&lt;/h2&gt;

&lt;p&gt;SQL makes modeling a small domain easier, but wow does it cause problems. I remember being at a company where engineers had to plan to wake up at midnight to upgrade various dbs to meet quarterly objectives. I don't want to ever have to wake up to upgrade a db.&lt;/p&gt;

&lt;p&gt;At another company, all we did was debug indexing all day. Our schema was so awful that a single user could lock the whole 16k/month db for 20 minutes. And it wasn't an edge case, this is just something that happened about once a week when someone decided to update their filters.&lt;/p&gt;

&lt;p&gt;It's well known that AWS avoids using SQL internally. I was exposed to the magic of this and I don't know why I'd ever go back. It was so much easier to predict performance because there weren't any noisey neighbors or weird query plans.&lt;/p&gt;

&lt;p&gt;But, I admit, I don't have a good columnar store replacement in mind, so I might use Neon. They manage the upgrades and I can trust myself never to add a join keyword to my queries... Probably 😉.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Only deliver software over the internet
&lt;/h2&gt;

&lt;p&gt;Delivering updates to native applications is painful. I've had to do it for both desktop and mobile and I don't want to deal with it any more. When a customer uses my product, they will always get the freshest version, no exceptions. This means a web interface and possibly a PWA if it's really necessary.&lt;/p&gt;

&lt;p&gt;Unless I make a game.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Make the UI render without CSS
&lt;/h2&gt;

&lt;p&gt;It makes accessibility easier and cuts down on the amount of bytes sent over the wire. Then after everything is in the right place, I might style the UI so it looks at all presentable.&lt;/p&gt;

&lt;p&gt;How would I render a graph? No idea 🤷‍♀️&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Have a fully static website and an API on day one
&lt;/h2&gt;

&lt;p&gt;I worked in a dotnet framework app where the controllers rendered HTML. It caused a lot of security issues because there was often no meaningful distinction between what the client "was" and what the server "was." In a vacuum I'd expect it to be the opposite, but I learned then that separating the frontend makes things easier in the long run.&lt;/p&gt;

&lt;p&gt;It's a stupid decision because even if it's more maintainable, it's more to maintain. Just should just use Ruby on Rails or something.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Use a monorepo
&lt;/h2&gt;

&lt;p&gt;Monorepos make it easy to couple things that shouldn't be coupled, but as a solo dev, why would I want to make multiple commits to get out one feature?&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Just use Taskfiles for cicd
&lt;/h2&gt;

&lt;p&gt;CI/CD doesn't have the same return on investment for companies with less than 2 software teams. I've configured pipelines and stuff as a solo dev, but they always end up requiring too much maintenance. I've learned the hard way that I don't have time, so making the deploy repeatable is much more important to me than making it automatic.&lt;/p&gt;

&lt;p&gt;Then there's the fact that makefiles are awful. There's not even enough of a standard syntax to be able to make a good autoformater (or there wasn't when I looked).&lt;/p&gt;

&lt;p&gt;I switched to taskfiles and everything about repeatable actions got better.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>How to make your online life private</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Mon, 29 Sep 2025 04:01:41 +0000</pubDate>
      <link>https://dev.to/ivypuckett/how-to-make-your-online-life-private-3jep</link>
      <guid>https://dev.to/ivypuckett/how-to-make-your-online-life-private-3jep</guid>
      <description>&lt;p&gt;Here's some simple switches I've made to make sure my online life stays between me and the people I talk to.&lt;/p&gt;

&lt;p&gt;All of these options are free. No affiliate links, but please support these companies who are making the world a better place. &lt;/p&gt;

&lt;h3&gt;
  
  
  SMS -&amp;gt; Signal
&lt;/h3&gt;

&lt;p&gt;Signal is awesome because the company which owns it cannot read any of the messages on its own platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://signal.org/" rel="noopener noreferrer"&gt;https://signal.org/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Gmail -&amp;gt; Proton Mail
&lt;/h3&gt;

&lt;p&gt;Same as signal, Proton cannot read any emails they provide.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://proton.me/mail" rel="noopener noreferrer"&gt;https://proton.me/mail&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ChatGPT -&amp;gt; Lumo
&lt;/h3&gt;

&lt;p&gt;The free tier doesn't give you quite as much, but I haven't had any complaints. Lumo is provided by Proton and has similar security in place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lumo.proton.me/" rel="noopener noreferrer"&gt;https://lumo.proton.me/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Gboard -&amp;gt; Futo Keyboard
&lt;/h3&gt;

&lt;p&gt;I hadn't thought about it, but it's kinda creepy that my phone's keyboard used to make network requests. Futo is entirely offline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://keyboard.futo.org/" rel="noopener noreferrer"&gt;https://keyboard.futo.org/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Windows -&amp;gt; Linux
&lt;/h3&gt;

&lt;p&gt;There are so many good distros. I switch often.&lt;/p&gt;

&lt;p&gt;Distro personality test: &lt;a href="https://distrochooser.de/" rel="noopener noreferrer"&gt;https://distrochooser.de/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Chrome -&amp;gt; Brave
&lt;/h3&gt;

&lt;p&gt;Centered on privacy and built on chromium, I like it better than Chrome.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://brave.com/" rel="noopener noreferrer"&gt;https://brave.com/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Finally
&lt;/h3&gt;

&lt;p&gt;If you know of anything else that can be done, please let me know.&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>privacy</category>
    </item>
    <item>
      <title>AI represents nothing new</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Sat, 20 Sep 2025 03:11:20 +0000</pubDate>
      <link>https://dev.to/ivypuckett/ai-represents-nothing-new-2lb0</link>
      <guid>https://dev.to/ivypuckett/ai-represents-nothing-new-2lb0</guid>
      <description>&lt;p&gt;My dad was a software engineer for 50 years. He once told me, "every ten years the software industry fundamentally shifts. Some people adapt and start making more money, but there's always jobs available for those that don't want to adapt." &lt;/p&gt;

&lt;p&gt;In his career, he saw this many times. It's happened to me as well. When I entered the software industry, my company was one of the last to migrate from a data center to the cloud. My role quickly shifted from throwing things over the wall to ops to taking care of ops myself. We still had ops people in our company, but fewer than we would have 10 years prior.&lt;/p&gt;

&lt;p&gt;The devops movement, which I see as a collapse of the roles of "dev" and "ops," is mirrored in the more subtle collapse of "dev" and "qa." In my most recent two roles, there are no manual qa people. Instead, I am responsible for the quality of the work I produce and any bugs I release to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is happening to me now
&lt;/h2&gt;

&lt;p&gt;I scorned AI until an engineer I respect (hi Bri!) said that she adopted it and it made her more effective. I gave myself a week where I solely prompted Claude to write code for me. My results were disappointing.&lt;/p&gt;

&lt;p&gt;It felt a lot like the tale of John Henry, a railroad stake driver who challenged the machine. After a full day's labor, he beat the machine in driving stakes over the mountain. Exhausted, he collapsed on the ground and the machine kept going.&lt;/p&gt;

&lt;p&gt;I write better code than AI. It's more maintainable, better abstractions, better names, and more readable tests. Claude is better at staying engaged and coming back to solve the problem with fresh energy. I used to pride myself on that. Together, Claude and I make a good team because I have shifted from author to reviewer.&lt;/p&gt;

&lt;p&gt;I'm currently straddling two high priority initiatives. A week ago my meeting schedule was too full for me to get much done on either. I made progress on both initiatives by prompting an agent to do fine grained, specific tasks in the 5 minutes between meetings. By doing this, I was able to meet deadlines I thought I'd have to push back.&lt;/p&gt;

&lt;p&gt;I still write a lot of code. There are some problems it seems AI simply cannot figure out. But my role is different than it was two months ago and I'm more effective because I embrace that fact.&lt;/p&gt;

&lt;h2&gt;
  
  
  No, AI won't replace you
&lt;/h2&gt;

&lt;p&gt;Higher level languages didn't decrease the number of software jobs available. Neither did OOP, the cloud, CI/CD, or any other scary new concept we've seen over the years. AI won't decrease the number of jobs available either.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to adapt
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Set up a good agent into your current IDE. Claude is a solid choice.&lt;/li&gt;
&lt;li&gt;Give yourself a week where every line of code you output comes from a prompt.&lt;/li&gt;
&lt;li&gt;Learn from what works and what doesn't.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to not adapt
&lt;/h2&gt;

&lt;p&gt;It's hard to see the future, but there are a couple of things AI appears to be bad at where you could excel as a dev.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Become an expert in an ecosystem (cloud, programming language, etc.). While it has an approximate knowledge of everything, it is bad at esoteric issues.&lt;/li&gt;
&lt;li&gt;Work at a company which can't expose its data for regulatory reasons. Governments, health insurance agencies, etc. may have to rely on good developers that don't want to use AI. This happened with the Cloud and appears to be happening now.&lt;/li&gt;
&lt;li&gt;Just wait and refuse to adopt it. This shift has only been going on for a couple years. You have time to adopt it later if you need / want to.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Don't worry about your job. Decide whether you want to adapt and position yourself accordingly.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>career</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Introducing: A Go package to reduce err boilerplate</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Sun, 14 Sep 2025 01:22:34 +0000</pubDate>
      <link>https://dev.to/ivypuckett/introducing-a-go-package-to-reduce-err-boilerplate-3o6a</link>
      <guid>https://dev.to/ivypuckett/introducing-a-go-package-to-reduce-err-boilerplate-3o6a</guid>
      <description>&lt;p&gt;TL;DR look at it here: &lt;a href="https://pkg.go.dev/github.com/ivypuckett/to@v1.0.0" rel="noopener noreferrer"&gt;https://pkg.go.dev/github.com/ivypuckett/to@v1.0.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go is a wonderful language, but I keep writing the same three lines of code over and over again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once is fine but if I get unlucky, I may add 15 extra lines of code over the scope of a single method... Just to return errors. &lt;a href="https://www.nuget.org/packages/WinstonPuckett.ResultExtensions" rel="noopener noreferrer"&gt;Having already implemented this pattern in C#&lt;/a&gt;, I knew that it should be possible to eliminate this boilerplate in Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal
&lt;/h2&gt;

&lt;p&gt;Implement a &lt;strong&gt;forward pipe operator&lt;/strong&gt; / &lt;strong&gt;bind monad&lt;/strong&gt; which enables chaining multiple methods where the input of the next is the output of the last. Upon the first error returned, return that error and the zero value of the expected result. If no errors are returned, return the result of the last operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pain
&lt;/h2&gt;

&lt;p&gt;In C#, the forward piping is fairly easy. I created an extension method on the base object which allows any object to call &lt;code&gt;.Pipe(methodName)&lt;/code&gt;. That means someone can call &lt;code&gt;1.Pipe(Increment).Pipe(Increment)&lt;/code&gt; and receive 3.&lt;/p&gt;

&lt;p&gt;Go is not an object oriented language (thank goodness), but it still has methods. My first thought was to create a struct called Chain with a method &lt;code&gt;.Bind&lt;/code&gt; which takes in the next method and returns a new Chain object. It'd be a lot like a linked list. I found out that Go does not support generics on methods. There's no way (I've found) to create a struct with an unbound type.&lt;/p&gt;

&lt;p&gt;The next thought was to create a &lt;code&gt;Compose[T, U, V any](func(T)(U, error), fn2(U) (V, error)) func(T) (V, error)&lt;/code&gt; function. This kind of function would allow someone to recursively bind functions by calling &lt;code&gt;Bind(fn1, Bind(fn2, fn3))&lt;/code&gt;. The syntax was too cumbersome though and there's a small bit of overhead with the number of function calls.&lt;/p&gt;

&lt;p&gt;Using variable arguments and type assertions is also promising, but I didn't want to utilize reflection as there's overhead in that as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The semi-elegant solution
&lt;/h2&gt;

&lt;p&gt;Ultimately, the interface for this is &lt;code&gt;to.Bind3(input, fn1, fn2, fn3)&lt;/code&gt;. There is only one extra character and the only overhead is the function call itself. The package provides 1-32 parameter variants.&lt;/p&gt;

&lt;p&gt;I considered using &lt;code&gt;bind.Three&lt;/code&gt; as it fills a sentence better, but I thought better of it as it may break a programmer's flow easier if we have to think of how to spell a word instead of just typing the new number on a keyboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Before&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;SaveWithoutBind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;sanitized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;cased&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;correctCasing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sanitized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;queried&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getExtraInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cased&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queried&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// After&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;SaveWithBind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bind4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;sanitize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;correctCasing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;getExtraInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/ivypuckett/to@v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/ivypuckett/to" rel="noopener noreferrer"&gt;https://github.com/ivypuckett/to&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go Package: &lt;a href="https://pkg.go.dev/github.com/ivypuckett/to@v1.0.0" rel="noopener noreferrer"&gt;https://pkg.go.dev/github.com/ivypuckett/to@v1.0.0&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Image credit: &lt;a href="https://unsplash.com/photos/people-partying-with-confetti-ZODcBkEohk8" rel="noopener noreferrer"&gt;https://unsplash.com/photos/people-partying-with-confetti-ZODcBkEohk8&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>go</category>
      <category>functional</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How to view productivity</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Wed, 21 May 2025 13:56:33 +0000</pubDate>
      <link>https://dev.to/ivypuckett/how-to-view-productivity-1p9b</link>
      <guid>https://dev.to/ivypuckett/how-to-view-productivity-1p9b</guid>
      <description>&lt;p&gt;We maximize what we measure. Without clarity on purpose, we measure the things that make us feel good. These pleasures distract us from deriving joy from what we maximize. In short, we (I) tend to focus on the input more than impact.&lt;/p&gt;

&lt;p&gt;By understanding how to define and measure productivity for ourselves, we reset our focus.&lt;/p&gt;

&lt;p&gt;First we will define productivity, then we will understand how to use all sources of information, last we'll look at 6 lenses we can use to view our own productivity and how we can "clean the lense" to have a more clear picture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining productivity
&lt;/h2&gt;

&lt;p&gt;If we define productivity as "the ability to have impact," our metrics for whether we are productive are subject to the context in which we operate.&lt;/p&gt;

&lt;p&gt;Put another way, there is no consistent metric we can apply to understand whether we are productive.&lt;/p&gt;

&lt;p&gt;Furthermore, "productivity" is an attribute. Just like kindness, intelligence or attractiveness, we cannot measure productivity on our own.&lt;/p&gt;

&lt;p&gt;Likewise, exclusively allowing others to define our productivity will give us an inaccurate result. Much like looking in a foggy mirror.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;I once took on a large-scale, highly-visible project. I collaborated across every team in our org and delivered the first milestone before the deadline.&lt;/p&gt;

&lt;p&gt;After I delivered the first piece, the project was cancelled. We had many things in place which no longer served a purpose. Leadership saw the delivery as a win. I saw it as a failure.&lt;/p&gt;

&lt;p&gt;From that anecdote, should I say that I was productive because I delivered on time? Productive because leadership saw it as productive? Or should I say that I was unproductive because my time did not end in driving impact?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We must use all available signals to point us towards some sense of true productivity.&lt;/strong&gt; In this case, two of the three signals I can identify say I was productive. From these signals, I can look for lessons to take forward.&lt;/p&gt;

&lt;p&gt;It can be useful to group these signals into internal productivity (ones own view) and external productivity (others view). "Cleaning the lense" of internal productivity is about &lt;strong&gt;honestly measuring our impact against an idealized self.&lt;/strong&gt; For external productivity, it is about &lt;strong&gt;empowering those around us to speak to our productivity accurately.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both are vital to success.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internal Productivity: Incremental delivery
&lt;/h2&gt;

&lt;p&gt;To understand what we've done and how much we've done, we need to mark it as done.&lt;/p&gt;

&lt;p&gt;Said another way, until something is released, it does not speak to our productivity.&lt;/p&gt;

&lt;p&gt;Release more often! Break down your work into smaller pieces! When I started doing this, I noticed that I became much more relaxed as a developer. Because I could see how much I'd done, &lt;strong&gt;I became more satisfied with how much I was doing.&lt;/strong&gt; I am also able to push myself to get more done because I tackle a smaller scope at any given time.&lt;/p&gt;

&lt;p&gt;Work items can also become too fine grained. The rest of this section is dedicated to understanding what is too large and too small.&lt;/p&gt;

&lt;p&gt;A change is too small when it cannot be reviewed without reviewing another change. A change is too large when a comment could block part of the release, but other parts could go out.&lt;/p&gt;

&lt;p&gt;I worked with Cory, a good engineer who advocated for 75/75 PRs: 75 lines of code and 75 lines of tests in one pull request. For me, 150/150 is about right. If you're over 300/300, you can probably break things down more.&lt;/p&gt;

&lt;p&gt;Kent Beck also gave us one of the best tools for refining this skill in &lt;a href="https://www.oreilly.com/library/view/test-driven-development/0321146530/" rel="noopener noreferrer"&gt;Test Driven Development: By Example&lt;/a&gt;. Write a list of things you'll do in the next hour and a list of things you'll do in the next month.&lt;/p&gt;

&lt;p&gt;By writing the list of tasks you'll do in the next hour, you're breaking your work into smaller-than-hour-sized-chunks. If deploying one task is not a large enough scope, you can group tasks together into a deployment unit. &lt;/p&gt;

&lt;p&gt;This technique is also the easiest way to know your timeline, which we'll talk about soon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internal Productivity: Unblock Yourself
&lt;/h2&gt;

&lt;p&gt;At face value, "unblock yourself" is a truism. In practice, when I see someone stuck at a junior-level of productivity it's usually because they don't know when to ask for help or they don't know how to unblock themselves.&lt;/p&gt;

&lt;p&gt;Software is a collaborative activity. The only stupid questions are those asked insincerely (yep, there's a story there). The idea of "unblock yourself" is not at odds with asking for help.&lt;/p&gt;

&lt;p&gt;When you feel blocked, &lt;strong&gt;put in two hours of concerted effort.&lt;/strong&gt; During the two hour window, continually come back to the question, "ok, but how do I move forward?" If you are tempted to stop pressing forward, imagine that everyone else is on vacation (yep, there's a story there too). If that doesn't help, type out the question you'd want to ask in specific detail and imagine what the person would ask you to try first.&lt;/p&gt;

&lt;p&gt;At the end of the two hour window, reach out to someone. If you want to go the extra mile, continue to work on the problem after you've reached out and race to solve the problem before the person responds.&lt;/p&gt;

&lt;p&gt;There's no secret here. It's effort. Regardless of outcome, stretching yourself like this strengthens the muscle that leads to productivity.&lt;/p&gt;

&lt;p&gt;By attempting to unblock yourself, you're implicitly asking the question, "how would my idealized self solve this problem?" Year over year, you will see a trend of being able to solve larger problems without being blocked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internal Productivity: Foreknowledge and experience
&lt;/h2&gt;

&lt;p&gt;This lense speaks to how quickly and accurately you can respond to a given situation. By understanding how large the boundaries of your knowledge are, you can more clearly understand how far you have to go to respond well. &lt;/p&gt;

&lt;p&gt;Measure how often you can identify gaps and how well you can expand your borders of knowledge to grow beyond the gap. Every time you find something new and relevant to learn, celebrate.&lt;/p&gt;

&lt;p&gt;One day I was brought onto a project. We were integrating with a new downstream system that didn't have an established RPS limit. We wanted to know for sure the system could handle our load.&lt;/p&gt;

&lt;p&gt;The week prior I took the time to learn &lt;a href="https://k6.io/" rel="noopener noreferrer"&gt;k6&lt;/a&gt;. As it turned out, I had the clearest vision for how we could move forward load testing this downstream system. &lt;strong&gt;Because I spent time to learn something, I was able to propose a solution.&lt;/strong&gt; I didn't know I'd be on the project. I didn't know the project would need load testing.&lt;/p&gt;

&lt;p&gt;How did I know a load testing tool was the right thing to learn? I listened to the wind (most people call this prayer). That answer probably isn't satisfying though, so here are more concrete steps you can take:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Listen to what others are interested in and ways they've solved problems.&lt;/li&gt;
&lt;li&gt;Look around for the holes in how your company does things. Instead of learning a specific technology, evaluate several.&lt;/li&gt;
&lt;li&gt;Aim to spend a certain percent of your time learning things. Google calls this 20% time, several people in my community call this Fun Fridays.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Especially the last point is important. If you feel consistently overwhelmed by everything in front of you, slow down. This not only allows you to continue learning, but often gives room to gain perspective. It's a lot like driving, if you only look 5 feet in front of you, everything requires a quick reaction. If you gaze down the road, you'll be able to take your time to react in a more measured manner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't aim for always being "right" about what to learn next.&lt;/strong&gt; Focus on expanding the boundaries of your knowledge and skill.&lt;/p&gt;

&lt;p&gt;For the experience part of foreknowledge and experience, find developers who are better than you and get on projects with them. There's nothing quite as helpful as observing and adopting how others approach problems. If you can't find anybody more senior, find someone more junior. Junior engineers don't have the years of bias you do and there's a lot one can learn from fresh eyes.&lt;/p&gt;

&lt;h2&gt;
  
  
  External Productivity: Align with Impact
&lt;/h2&gt;

&lt;p&gt;I know a number of developers who don't care about the business side of business; they just want to write code, architect solid systems, and sleep at night without alarms going off. We need people like this on our teams and in our lives.&lt;/p&gt;

&lt;p&gt;One common expression I hear from this archetype is that the business doesn't see how productive they are. This is true - the more technical a deliverable, the less likely a business will be able to evaluate its importance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You must bridge the gap.&lt;/strong&gt; Define the exact impact of any piece of work you propose. Impact must be related to &lt;strong&gt;customer experience, money, or a measured reduction in operational overhead&lt;/strong&gt;. Unless you find something else the business cares about, &lt;strong&gt;ruthlessly de-prioritize anything that doesn't fit into this list.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you've gone through this exercise a number of times, you may notice the things that "business people" propose also align with this list almost all of the time. Speaking in terms of impact unifies the two "halves" of the company.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: extensibility is intentionally left off the list. If you want to change something for extensibility, include the effort as part of the effort for a business feature. In general, this is a good way to take care of tech debt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  External Productivity: Measure the Unknown
&lt;/h2&gt;

&lt;p&gt;When I was younger, I once estimated that a piece of work would take me 2 months. 6 months later I delivered it. In addition to failing to deliver incrementally, there were unanticipated, external factors preventing me from moving quickly.&lt;/p&gt;

&lt;p&gt;Developing skill in estimating, and especially measuring the unknown, is essential to having others reflect back your productivity accurately. Promise to deliver only what you &lt;strong&gt;know&lt;/strong&gt; you can deliver and expose the unknowns that make timelines risky. When you find out your timeline is wrong, expose it as early as possible.&lt;/p&gt;

&lt;p&gt;If you're a younger developer being asked for timelines, look for older developers and ask for their opinions. Be aware that, according to &lt;a href="https://a.co/d/bmZ4zeJ" rel="noopener noreferrer"&gt;The Mythical Man Month&lt;/a&gt;, coding is 1/6 of the time it takes to get something to production.&lt;/p&gt;

&lt;p&gt;There are a number of circumstances which cause unknowns to creep into the schedule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When something is unknown because you haven't broken down the work, break down the work.&lt;/li&gt;
&lt;li&gt;When it's because the logic is not define yet, the services are unfamiliar or, there's new (to you) algorithms / technologies, estimate with that in mind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Estimate unknowns first in terms of scale. Will it take hours, days, weeks, months, or years? Then give an "expected" and "if everything goes wrong" estimate.&lt;/p&gt;

&lt;p&gt;When you dive into the project and the unknown becomes known, expose early when something will take longer than expected. This develops trust.&lt;/p&gt;

&lt;p&gt;By measuring the unknown, we eliminate a common reason it's hard for others to help us evaluate our productivity. Measuring the unknown brings others in to the conversation about how long something will actually take instead of having a binary yes/no for if a deadline will be met. This allows other developers to speak to us for how we are managing our time.&lt;/p&gt;

&lt;h2&gt;
  
  
  External Productivity: Know your timeline
&lt;/h2&gt;

&lt;p&gt;Know your past. It allows others to reflect back a more accurate representation of your productivity during a performance review.&lt;/p&gt;

&lt;p&gt;Know your present. It allows you to accurately reflect back to others what you're currently working on and prioritize new initiatives against current ones.&lt;/p&gt;

&lt;p&gt;Know your future. It allows you to not slow down when you finish a project and cast vision to others when it's time to move on from your current initiatives.&lt;/p&gt;

&lt;p&gt;Again, as Kent would say, the easiest way to do all three of these is to keep two lists. One list of things you'll do in the next hour and another of things you'll do in the next month. Ticketing systems like Jira most often don't encompass what we do. Take note of things like the conversations you need to schedule and one-off tasks which so often encroach upon our time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;There's no easy answers. Productivity is ephemeral. Stay present, stay curious, put in the work. Seek to use all sources for a sense of true productivity.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>learning</category>
    </item>
    <item>
      <title>How to write a great one-pager</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Sat, 12 Oct 2024 23:01:43 +0000</pubDate>
      <link>https://dev.to/ivypuckett/how-to-write-a-great-one-pager-1edj</link>
      <guid>https://dev.to/ivypuckett/how-to-write-a-great-one-pager-1edj</guid>
      <description>&lt;p&gt;One-pagers are the fastest mechanism the software industry uses to gain alignment. A one-pager is a document which outlines a problem's context and exposes potential solutions to solve the problem. After a one-pager is made available, it is often presented in a review process to drive toward a decision.&lt;/p&gt;

&lt;p&gt;This one-pager outlines the non-obvious rules for writing one-pagers.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Assume your audience is 2-3x less informed than you believe.
&lt;/h2&gt;

&lt;p&gt;In doing so, you will surface basic assumptions the group makes. This allows the group to question assumptions before asserting a direction for the review. Many one-pagers are shared beyond the scope the author intended. By writing for a less-informed audience, you help non-technical roles understand &lt;strong&gt;why&lt;/strong&gt; the work needs to be done and &lt;strong&gt;what&lt;/strong&gt; areas of the system are impacted.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Adopt egoless writing.
&lt;/h2&gt;

&lt;p&gt;Gerald Weinberg in, &lt;em&gt;The Psychology of Computer Programming&lt;/em&gt;, recounts a story where a technical leader wrote twenty lines of code. When another engineer reviewed the code, she found eleven major errors. Instead of the leader defending their choices, they laughed and shared the news with everyone in the office, praising the reviewer for finding so many mistakes.&lt;/p&gt;

&lt;p&gt;This is an example of egoless programming. The author celebrated the mistakes pointed out in the code they wrote. When we write one-pagers, we aim to do the same. &lt;strong&gt;Every criticism is not a criticism of the author, but of the physical words on the page.&lt;/strong&gt; Every comment should be treated as an opportunity for celebration.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The author owns the document.
&lt;/h2&gt;

&lt;p&gt;A principle I picked up from Amazon: the one who is responsible for writing the document has the authority to determine what the document says. Reviewers find places the document needs to change, but do not decide &lt;strong&gt;how&lt;/strong&gt; to resolve comments. This is most effective when practiced alongside egoless writing.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Suggest two alternatives to a course of action.
&lt;/h2&gt;

&lt;p&gt;When only one option is present, reviewers tend to wonder whether the author explored other options and request more research. With two options, reviewers tend to “pick sides” instead of exploring tradeoffs. Three or more options communicates that enough research has been done and it helps reviewers not become attached to any of the options.&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Mark the first option as recommended. Tell why that option is recommended. Include graphs, risks, and tradeoffs.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. If someone suggests a nitpick, find a way to accept it.
&lt;/h2&gt;

&lt;p&gt;Anything besides content should be resolved as quickly as possible so as to not detract from the review. Unless it changes the meaning, accept whatever suggestions people have and move on. If it does change the meaning and you can't accept it at face value, message the reviewer and suggest a third way to phrase things. &lt;strong&gt;If one person thought the original phrasing was confusing, there are more who haven’t spoken up.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Include graphs.
&lt;/h2&gt;

&lt;p&gt;If you don’t include graphs and there’s an opportunity to, someone will request it. Make the graphs beforehand so that you can focus on the content during reviews.&lt;/p&gt;

&lt;p&gt;Some people understand the information better after looking at graphs. Consider “graph making” an exercise in accessibility if nothing else.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. One-pagers are as short as reasonable.
&lt;/h2&gt;

&lt;p&gt;Few one-pagers are actually only one page. However, strive to make them as short as you can. An easy way to do this is to eliminate all tangents beyond the scope of the overview. If you follow the format below, all information should guide reviewers toward making a decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Follow a format
&lt;/h2&gt;

&lt;p&gt;Format changes per subject, but following this pattern as much as reasonable leads to higher quality reviews. There are a few "tedious" sections (overview, graphs, what the system looks like today), but including these eliminates questions unrelated to the topic.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Overview: One-to-two paragraphs about the area we’re working in, the problem, the services involved, and any other documents or links that are relevant to the discussion.&lt;/li&gt;
&lt;li&gt;Current user flow: This may be a section with multiple subheadings depending on the scope of the change. Talk about how data flows through your system. Bring graphs.&lt;/li&gt;
&lt;li&gt;Answer questions preemptively: Things like, “what happens if we do nothing?”, “how long do we have to act?”, “is there any off-the-shelf software we could use?”, “what have we tried in the past?”. Make each heading a sentence with the question being answered. That way curious minds can navigate using the document outline.&lt;/li&gt;
&lt;li&gt;Proposed changes: as mentioned previously, bring at least three alternatives and mark your recommended path in the heading. Try to use one graph per alternative.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/U6U311CWAJ" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ko-fi.com%2Fcdn%2Fkofi1.png%3Fv%3D3" alt="Buy Me a Coffee at ko-fi.com" width="580" height="146"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Special thank you to LTK for allowing me to publish this. I originally wrote it as internal documentation and asked whether it would be ok to also publish it here.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;This came out of a mentoring session I had with Diana Larsen. In 2020 I asked her how to help my teammates fight for “the right thing” instead of their own perspectives. Her advice was to find a third alternative even if it was a weaker suggestion. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>tutorial</category>
      <category>documentation</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I got a job at AWS</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Tue, 27 Aug 2024 05:01:11 +0000</pubDate>
      <link>https://dev.to/ivypuckett/how-i-got-a-job-at-aws-5hm3</link>
      <guid>https://dev.to/ivypuckett/how-i-got-a-job-at-aws-5hm3</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I had been working at my first software job for 3.5 years and in that time I moved from junior to mid. It was obvious that if I were to keep growing my skills, I would need to move companies.&lt;/p&gt;

&lt;p&gt;First thing, I changed my status on LinkedIn to "Open to Work." About three months later, an AWS recruiter reached out to me. Working at AWS was my dream job. She said I could interview for a couple of different teams and we decided I would interview with API Gateway.&lt;/p&gt;

&lt;p&gt;I had two months to prepare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Study coding challenges
&lt;/h2&gt;

&lt;p&gt;I read two books and would only recommend &lt;a href="https://www.crackingthecodinginterview.com/" rel="noopener noreferrer"&gt;Cracking the Coding Interview&lt;/a&gt;. This is common advice, but it prepares you well for coding challenges. I read through it, doing at least one problem per chapter and then reviewed as many additional questions per chapter as I had time for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Go to Amazon's interviewing workshop (if available)
&lt;/h2&gt;

&lt;p&gt;AWS provides a number of resources for candidates. They want people to succeed, If I had not attended the hour workshop offered to me by my recruiter, I wouldn't have gotten the job. Most of the advice in this article just echoes their recommendations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Find two stories for each LP
&lt;/h2&gt;

&lt;p&gt;Amazon holds tightly to the &lt;a href="https://www.amazon.jobs/content/en/our-workplace/leadership-principles" rel="noopener noreferrer"&gt;Leadership Principles&lt;/a&gt;. These are a set of short phrases used to guide decision making.&lt;/p&gt;

&lt;p&gt;Choose two stories per Leadership Principle. Each story should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow the &lt;a href="https://www.amazon.jobs/en/landing_pages/in-person-interview" rel="noopener noreferrer"&gt;STAR&lt;/a&gt; technique.&lt;/li&gt;
&lt;li&gt;Be short (3-5 minutes max) to explain.&lt;/li&gt;
&lt;li&gt;Be tied to a professional experience. If you're fresh out of college, tie it to a collegiate experience or side project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Write enough of the story down that you'll be able to look at your notes in the interview and remember the story.&lt;/p&gt;

&lt;p&gt;This took me around 10 hours. At the time, there were 12 Leadership Principles, which meant 24 stories. I tried my best and came up with around 20 stories with 4 overlapping between principles.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: During the interview, I pivoted which stories I told according to the questions asked. Don't be rigid in the interview, but find as many stories as you can and be ready to share any of them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 3: Find useful design patterns and be able to apply them.
&lt;/h2&gt;

&lt;p&gt;The book "Design Patterns" by Erich Gamma is a great resource for this. Don't memorize the entire book (unless you'd like to). Instead, pick 4 diverse patterns that you could see helping you solve problems.&lt;/p&gt;

&lt;p&gt;I picked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Abstract Factory&lt;/li&gt;
&lt;li&gt;Builder&lt;/li&gt;
&lt;li&gt;Singleton&lt;/li&gt;
&lt;li&gt;Decorator&lt;/li&gt;
&lt;li&gt;Proxy&lt;/li&gt;
&lt;li&gt;Observer&lt;/li&gt;
&lt;li&gt;Iterator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I only used one of these as part of the software design portion of the interview. However, I referenced more in passing as the interviews progressed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Look into trees
&lt;/h2&gt;

&lt;p&gt;This is in Cracking the Coding Interview. Please look into it. Even if it's just BFS/DFS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Know O(n) notation
&lt;/h2&gt;

&lt;p&gt;Some people already do but just in case, it's really important. Not just for interviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Have at least 4 thoughtful questions to ask
&lt;/h2&gt;

&lt;p&gt;Asking questions that show you know what you would like out of a job and want to work with the company can be very helpful. Ask software specific things you care about. One example I like is: "What is your oncall schedule like?" or "What does releasing software look like on your team?"&lt;/p&gt;

&lt;p&gt;Figure out what you care about in a job and write down these questions beforehand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Essential Step: Take too many notes
&lt;/h2&gt;

&lt;p&gt;The picture for this post above is my setup for my interview. This was something that was mentioned in the class - that notes are allowed. &lt;strong&gt;Always be up front about your notes.&lt;/strong&gt; If you're going to reference them and you happen to be remote, mention casually, "hey, do you mind if I reference my notes on this?" Or "let me just scan my notes real quick for a story that matches that." &lt;/p&gt;

&lt;p&gt;To be honest, I memorized everything except for the 20 LP stories. But those 20 stories were incredibly useful to have written down and I'm glad I took the time to write more down because it stuck in my brain better.&lt;/p&gt;

&lt;h2&gt;
  
  
  The interview format
&lt;/h2&gt;

&lt;p&gt;This may have changed since I interviewed, but here are the rounds I had to get though:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Phone screening with a recruiter&lt;/li&gt;
&lt;li&gt;Two short, at-home leetcode style tests&lt;/li&gt;
&lt;li&gt;Connection with the recruiter for interview timing and training opportunities &lt;/li&gt;
&lt;li&gt;4, hour long in-person interviews: system design, software design (patterns), 2 coding exercises. In each, I was asked a behavioral question&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Useful Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cracking the Coding Interview: &lt;a href="https://www.crackingthecodinginterview.com/" rel="noopener noreferrer"&gt;https://www.crackingthecodinginterview.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Bit Twiddling Hacks: &lt;a href="https://graphics.stanford.edu/%7Eseander/bithacks.html" rel="noopener noreferrer"&gt;https://graphics.stanford.edu/~seander/bithacks.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Grokking Algorithms (a very beginner friendly book I learned about recently): &lt;a href="https://www.amazon.com/Grokking-Algorithms-illustrated-programmers-curious/dp/1617292230" rel="noopener noreferrer"&gt;https://www.amazon.com/Grokking-Algorithms-illustrated-programmers-curious/dp/1617292230&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Design Patterns: &lt;a href="https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612" rel="noopener noreferrer"&gt;https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;STAR Interview Technique: &lt;a href="https://www.amazon.jobs/en/landing_pages/in-person-interview" rel="noopener noreferrer"&gt;https://www.amazon.jobs/en/landing_pages/in-person-interview&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Leadership Principles: &lt;a href="https://www.amazon.jobs/content/en/our-workplace/leadership-principles" rel="noopener noreferrer"&gt;https://www.amazon.jobs/content/en/our-workplace/leadership-principles&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How long did this take?
&lt;/h2&gt;

&lt;p&gt;I didn't have any leetcode experience before I started preparing. My first job didn't contain a coding challenge. I had read the Design Patterns book, but I didn't have a list memorized. This was my first time applying for a FAANG roll.&lt;/p&gt;

&lt;p&gt;This was my dream job, so I spent multiple hours most nights studying for it. My guess is that I spent 100 hours preparing for the interviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  How much of this is luck?
&lt;/h2&gt;

&lt;p&gt;There's always luck involved with interviewing. In my current role at LTK, I was rejected the first time and accepted the second.&lt;/p&gt;

&lt;h2&gt;
  
  
  What would you have done differently?
&lt;/h2&gt;

&lt;p&gt;I didn't handle the offer stage very well. They ended up offering me 30k more than I asked for because I didn't trust the research I had done on what Amazon typically pays. If I had believed things, I may have been able to negotiate for 10k more in my salary.&lt;/p&gt;

&lt;p&gt;When you join, you get to choose which OS you use. I wish I would have asked what OS the people on my team use. There is also an unlisted third option of getting a Linux laptop. I switched to that after 8 months and had a wonderful experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened after you got the job?
&lt;/h2&gt;

&lt;p&gt;I joined AWS working on API Gateway for 1.5 years. In that time, I was put on an S-Team project where I led various parts of the initiative to great success. I'm being intentionally vague as I'm not sure how much of that I can share.&lt;/p&gt;

&lt;p&gt;Then, AWS required everyone to come back to the office. I was asked to choose a location or (by default) move to Colorado. They did it in the best way possible - giving me a year to decide. I'm very grateful for the time frame.&lt;/p&gt;

&lt;p&gt;I decided to move on, but working at AWS was one of my favorite professional experiences. The people I worked with were some of the most practiced engineers I've met and when my son grows up enough to where me being at home is not as impactful, I would consider rejoining.&lt;/p&gt;




&lt;p&gt;If you want to be an encouraging voice and/or read these posts before they're public, buy me a coffee and let's start a conversation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/U6U311CWAJ" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ko-fi.com%2Fcdn%2Fkofi1.png%3Fv%3D3" alt="Buy Me a Coffee at ko-fi.com" width="580" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>aws</category>
      <category>learning</category>
    </item>
    <item>
      <title>How to lose weight as a software engineer</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Sat, 20 Jul 2024 18:59:13 +0000</pubDate>
      <link>https://dev.to/ivypuckett/how-to-lose-weight-as-a-software-engineer-2mc9</link>
      <guid>https://dev.to/ivypuckett/how-to-lose-weight-as-a-software-engineer-2mc9</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Find out where you are. Take a small step towards your goal. Adjust your understanding based on what you learned. Repeat.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dave Thomas &lt;a href="https://youtu.be/a-BOSpxYJ9M?si=ki5xZnTx_uHwrZeB&amp;amp;t=1434" rel="noopener noreferrer"&gt;Agile is Dead, Long Live Agility 2015&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Short background
&lt;/h2&gt;

&lt;p&gt;When I was 8, I attended a pool party in my backyard. I had just stepped outside when a small girl looked up at me, ran to her mother, and whispered loudly, &lt;strong&gt;"mommy, why doesn't he have to wear a bra?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In March 2018, I realized I had gained 60 pounds in 4 years. Given the trajectory, I was about to have serious health concerns. I had tried diets and calorie counting apps, even through childhood, and nothing stuck for more than 7 months. &lt;strong&gt;I needed something different.&lt;/strong&gt; I was too disagreeable to hand myself over to a program for an extended period. Really, I needed the wisdom that software engineering provides.&lt;/p&gt;

&lt;p&gt;I have successfully lost 60 pounds over a period of 3 years. Then I joined AWS and had a baby. Now I've lost 20 of the 40 I'd gained back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Principles
&lt;/h2&gt;

&lt;p&gt;When I realized I needed something different, I started to rethink how we do weight loss in America. Most of the marketing centers around adrenaline-induced motivation: do more, keep pushing, just do it. What if these didn't work for me because they don't work?&lt;/p&gt;

&lt;p&gt;Instead, I started with a basic premise: approach weight loss as a scientist, not an athlete. Then, run safe experiments on your own body; don't rely on what works for someone else.&lt;/p&gt;

&lt;p&gt;Here are the basic principles I've come to align with. By following these, I see sustainable outcomes which have guided me through the past 5 years.&lt;/p&gt;

&lt;h3&gt;
  
  
  0. Do the least amount of work to achieve your goal.
&lt;/h3&gt;

&lt;p&gt;The muscles one uses for passing a test are unsustainable long term. Until 2018, I made the mistake of "trying too hard." I threw myself into weight loss and burned out quickly.&lt;/p&gt;

&lt;p&gt;If you want to succeed, &lt;strong&gt;do simple things that use little willpower.&lt;/strong&gt; I've found that weighing myself once a day and asking, "how did I get here?" then altering one behavior for a day is the least amount of work I can do to achieve a consistent result.&lt;/p&gt;

&lt;p&gt;This turns weight loss into a &lt;a href="https://feedvisor.com/resources/amazon-trends/amazon-flywheel-explained/" rel="noopener noreferrer"&gt;flywheel&lt;/a&gt;. Smaller consistent changes lead to big results. &lt;/p&gt;

&lt;h3&gt;
  
  
  1. Expect to lose weight at the rate you gain it.
&lt;/h3&gt;

&lt;p&gt;Don't sprint. Don't overwork yourself. This is an epic. &lt;/p&gt;

&lt;p&gt;I've heard a (probably false) statistic that Americans gain one pound a year. If you lose one pound a year, you're twice as far ahead as most people in America.&lt;/p&gt;

&lt;p&gt;If you set reasonable expectations of yourself (3 pounds a month was right for me when I started), you tend to &lt;strong&gt;make more sustainable choices.&lt;/strong&gt; It's more about asking the question, "what does it look like to live comfortably as someone who's 10 pounds lighter than I am?" than "how do I lose weight?"&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Measure somehow, consistently. Make your tools your friends.
&lt;/h3&gt;

&lt;p&gt;If measuring weight directly sounds like punishment, don't do it. But find a consistent measurement that fluctuates within a fine-grained time window and correlates to the outcome desired.&lt;/p&gt;

&lt;p&gt;When you find a measurement, treat it as &lt;strong&gt;a friend who tells you the truth&lt;/strong&gt;, not a competitor. This will encourage engagement with measurement regardless of how the past cycle went.&lt;/p&gt;

&lt;p&gt;Don't use calorie counting. This measures the input vs the output. What you're trying to measure is how your body responds over time, not your behavior around food.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Run experiments at fine-grained increments.
&lt;/h3&gt;

&lt;p&gt;Shorter than a day if you can. For me, a day is just right. The more data collected, the more you find out how actions impact your outcomes.&lt;/p&gt;

&lt;p&gt;This is just &lt;a href="https://athenian.com/blog/what-is-cycle-time" rel="noopener noreferrer"&gt;utilizing short cycle times&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Choose when to gain weight.
&lt;/h3&gt;

&lt;p&gt;When I attend a holiday meal, I gain weight. Don't fight battles unless you're going to win. When you are presented with options, choose consciously whether or not to gain weight. It's &lt;strong&gt;not a "cheat day."&lt;/strong&gt; It's a day where you've chosen your outcomes.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Celebrate small things
&lt;/h3&gt;

&lt;p&gt;If you move in a positive direction, say, "yay!" out loud. It helps :)&lt;/p&gt;

&lt;p&gt;Hopefully you do this in business too. Celebration is advantageous for so many things.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Change your environment more than you change your behavior
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Over-utilizing willpower leads to burn out.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of "trying not to grab the ice cream from the freezer," engage with something else that will fill the craving and stop buying ice cream. Maybe it's finding a group of friends to play a table top role-playing game with.&lt;/p&gt;

&lt;p&gt;If you tend to eat at places with heavy foods during work, find a restaurant with good food that serves smaller portion sizes. If you tend to go with coworkers, maybe order a hot chocolate instead of a hamburger and then eat at your desk (that's an example from my life).&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Set reasonable targets in public
&lt;/h3&gt;

&lt;p&gt;It's much easier to lose weight if you're public about where you're at and what you're aiming for. Find a friend group which is happy to have updates on a cadence (maybe join a health challenge) and be open about where you're at.&lt;/p&gt;

&lt;p&gt;This is the equivalent of "working in public." However, I don't know where I learned that software principle from and can't find examples. The basic idea is to surface progress early and often, which creates alignment between engineers and stakeholders.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Find a reason
&lt;/h3&gt;

&lt;p&gt;For me, there were several. As I've mentioned, there were health implications. There were also several other reasons. Feel free to draw from these and find your own. Your feet take their own steps when you are aligned well.&lt;/p&gt;

&lt;p&gt;Here are mine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Health concerns&lt;/li&gt;
&lt;li&gt;Mental health (depression mostly)&lt;/li&gt;
&lt;li&gt;An idealized self image&lt;/li&gt;
&lt;li&gt;Wanting to interact with future children fully&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My experiments as examples
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What happens if I use 2% instead of whole milk? I lost 1 pound that day.&lt;/li&gt;
&lt;li&gt;What happens if I order a salad at this restaurant instead of a burger? I gained 1 pound instead of 3.&lt;/li&gt;
&lt;li&gt;What happens if I go for a run today? Nothing changed.&lt;/li&gt;
&lt;li&gt;What happens if I have some whiskey? Nothing changed.&lt;/li&gt;
&lt;li&gt;What happens if I shift my food intake earlier? I lost weight. This is one of the most impactful changes I made.&lt;/li&gt;
&lt;li&gt;What happens if I cut out caffeine? I gained 2 pounds over two weeks, then I started to lose weight again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By running these experiments, we start to see what sorts of actions lead to what consequences. Running experiments more than once is also valuable to help isolate and correlate behaviors and outcomes. Once an action is found correlative with a desired outcome, we can utilize those experiments in my everyday life to achieve our goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary and how to get started.
&lt;/h2&gt;

&lt;p&gt;Handing your body to someone else to take care of doesn't work. We all need to &lt;strong&gt;find what works for us&lt;/strong&gt;. This post really just outlines what we've learned in software: &lt;strong&gt;run short experiments and gather data.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Get started:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose a measurement tool and cadence for measurement today. Using a scale is effective.&lt;/li&gt;
&lt;li&gt;Run an experiment.&lt;/li&gt;
&lt;li&gt;Measure and record the results.&lt;/li&gt;
&lt;li&gt;Go to step 2.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;I've talked about this to a couple of people and there are some common questions I get:&lt;/p&gt;

&lt;h3&gt;
  
  
  "What if I was female assigned at birth?"
&lt;/h3&gt;

&lt;p&gt;If your measurement tool is there to give you information, not to punish you, there's no reason to measure less frequently. Including data about your cycle is valuable information. We're looking for long term progress and fine-grained data collection.&lt;/p&gt;

&lt;h3&gt;
  
  
  "What if I need to make a change now?"
&lt;/h3&gt;

&lt;p&gt;If your weight has crossed over into having immediate health implications, don't try to move slowly. Move at an unsustainable pace to get to where you need to be, then come back here.&lt;/p&gt;

&lt;p&gt;Please follow advice from medical doctors over anything stated here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ko-fi.com/U6U311CWAJ" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstorage.ko-fi.com%2Fcdn%2Fkofi4.png%3Fv%3D3" alt="Buy Me a Coffee at ko-fi.com" width="580" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>discuss</category>
      <category>community</category>
    </item>
    <item>
      <title>New project, who dis?</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Wed, 15 May 2024 13:41:52 +0000</pubDate>
      <link>https://dev.to/ivypuckett/new-project-who-dis-36po</link>
      <guid>https://dev.to/ivypuckett/new-project-who-dis-36po</guid>
      <description>&lt;p&gt;There is now a blank public repo for the "fully-featured, infinitely scalable IaaS with predictable pricing." It's pretty minimal, but it's good to slow down and think about how things are laid out. The further I get into this project, the more I question whether a fork-able repository or a CLI that generates boilerplate is the right approach. Either way, it will be valuable to prove that all of these dependencies work together.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/winstonpuckett/sunflower" rel="noopener noreferrer"&gt;https://github.com/winstonpuckett/sunflower&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fru4yqh5fwqshqb6x01kd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fru4yqh5fwqshqb6x01kd.png" alt="Current repository structure" width="392" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've also narrowed what the experience should feel like. A user who has never heard of Sunflower should be able to complete "hello, world" within 5 minutes. This might be hard given the prerequisites (like, "have a Kubernetes cluster already").&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Making a free, fully-featured, infinitely scalable IaaS with predictable pricing</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Mon, 13 May 2024 12:12:30 +0000</pubDate>
      <link>https://dev.to/ivypuckett/making-a-free-fully-featured-infinitely-scalable-iaas-with-predictable-pricing-1ip2</link>
      <guid>https://dev.to/ivypuckett/making-a-free-fully-featured-infinitely-scalable-iaas-with-predictable-pricing-1ip2</guid>
      <description>&lt;p&gt;Pretty loud words, but it's what we need right now. Free tiers and usage-based billing make it difficult to visualize how cost will scale over time (search "cloud cost horror stories"). Creating a fully functional architecture based on a cloud provider takes a lot of learning or a lot of resources.&lt;/p&gt;

&lt;p&gt;Solutions like &lt;a href="https://pocketbase.io/" rel="noopener noreferrer"&gt;pocketbase&lt;/a&gt; and &lt;a href="https://coolify.io/" rel="noopener noreferrer"&gt;coolify&lt;/a&gt; come close to solving these problems. However, I wouldn't choose either as I fear architecture lock-in as much as vendor lock-in. Especially in the case of pocketbase, I may be forced to rewrite my application if it were to scale overnight.&lt;/p&gt;

&lt;p&gt;Likewise, Kubernetes comes close. It's free, extensible, "infinitely" scalable, and, when cloud hosted, is billed with consistent costs. The only drawback is that you start from scratch. Even if one reduces the needs of the application to the bare essentials, the number of choices and the amount of mental overhead exceeds what a developer should take on.&lt;/p&gt;

&lt;p&gt;If Kubernetes had a template or even a list of reasonable defaults to bootstrap a new project, a developer could use this as a baseline, dive into learning Kubernetes at a more reasonable pace, and expand / replace the components without being strongly bound to a particular cloud or scaling strategy.&lt;/p&gt;

&lt;h1&gt;
  
  
  What should we do about it?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;If people show interest&lt;/strong&gt;, I'd like to pull together tools from across our industry to provide this IaaS to jumpstart independent developers with "best practices by default."&lt;/p&gt;

&lt;p&gt;The solution will have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auth&lt;/li&gt;
&lt;li&gt;NoSQL, SQL, and Key/Value database support&lt;/li&gt;
&lt;li&gt;Reverse Proxy &amp;amp; Load Balancing&lt;/li&gt;
&lt;li&gt;Static Sites&lt;/li&gt;
&lt;li&gt;Backend Services&lt;/li&gt;
&lt;li&gt;Frontend Analytics&lt;/li&gt;
&lt;li&gt;Backend Metrics&lt;/li&gt;
&lt;li&gt;Serverless functions (if requested)&lt;/li&gt;
&lt;li&gt;Paging/Alerting&lt;/li&gt;
&lt;li&gt;External Configuration&lt;/li&gt;
&lt;li&gt;Source Control&lt;/li&gt;
&lt;li&gt;Container Registry&lt;/li&gt;
&lt;li&gt;Helm Chart Repo&lt;/li&gt;
&lt;li&gt;CI/CD Pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This might seem like a lot, and it is, but solutions for everything above already exist. We just need to pull it all together.&lt;/p&gt;

&lt;h1&gt;
  
  
  How would we do it?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21r9g1uroxlozxeh3iqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F21r9g1uroxlozxeh3iqi.png" alt="Architecture Diagram" width="800" height="689"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To ensure the platform is cloud agnostic and easily deployable, we start with Kubernetes. Every piece of infrastructure in the platform will be hosted on top of this.&lt;/p&gt;

&lt;p&gt;There are a couple of key technologies which satisfy our needs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NGINX works for static site deployment and ingress and reverse proxy &lt;/li&gt;
&lt;li&gt;Gitea provides all CI/CD needs from source control to pipelines&lt;/li&gt;
&lt;li&gt;Postgres, and Vallkey satisfy most of our database requirements.&lt;/li&gt;
&lt;li&gt;Prometheus satisfies our observability needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a full list of planned integrations, see the diagram above. &lt;/p&gt;

&lt;h1&gt;
  
  
  Unknowns
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;What auth solution will be best?&lt;/li&gt;
&lt;li&gt;How does this get packaged for both ease and extensibility? &lt;/li&gt;
&lt;li&gt;Should serverless functions be included? How much work would that be?&lt;/li&gt;
&lt;li&gt;Most projects need to accept a form of payment. What can we do to help people bootstrap that aspect?&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Milestones
&lt;/h1&gt;

&lt;p&gt;At every step, everything needs to be scripted and reproducible. Some sort of IaC is required even if it's just a Makefile. Listen and adapt the project to feedback received.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Measure interest by publishing a post and seeing if people respond positively. If they do, move to the next step.&lt;/li&gt;
&lt;li&gt;Create a fork-able repository with a single-command deploy script. Running this installs or deletes the platform.&lt;/li&gt;
&lt;li&gt;Add Gitea and documentation.&lt;/li&gt;
&lt;li&gt;Add auth, a service which connects to it, and documentation.&lt;/li&gt;
&lt;li&gt;Add databases, a service which connects to them, and documentation.&lt;/li&gt;
&lt;li&gt;Add NGINX, a static site, analytics, and documentation.&lt;/li&gt;
&lt;li&gt;Add NGINX as a reverse proxy, a site it exposes, metrics, and documentation.&lt;/li&gt;
&lt;li&gt;Add an alert for the metrics, and documentation.&lt;/li&gt;
&lt;li&gt;Refactor all IaC to be uniform.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  How could one get involved?
&lt;/h1&gt;

&lt;p&gt;Leave a reaction on this post to help me gauge interest. If you want to get involved further, leave a comment with suggestions, ideas, requests, or offers to help.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;P.S. This is not in competion with AWS. I wouldn't want to take on hosting any of this.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>learning</category>
      <category>cloud</category>
    </item>
    <item>
      <title>OpenMP Notes</title>
      <dc:creator>Ivy Puckett</dc:creator>
      <pubDate>Sun, 24 Sep 2023 22:27:03 +0000</pubDate>
      <link>https://dev.to/ivypuckett/openmp-notes-1cfa</link>
      <guid>https://dev.to/ivypuckett/openmp-notes-1cfa</guid>
      <description>&lt;h2&gt;
  
  
  What is this document?
&lt;/h2&gt;

&lt;p&gt;I recently went through Tim Mattson's &lt;a href="https://youtube.com/playlist?list=PLLX-Q6B8xqZ8n8bwjGdzBJ25X2utwnoEG&amp;amp;si=VlCiP_gIHKOfBHQC" rel="noopener noreferrer"&gt;Introduction to OpenMP&lt;/a&gt;, a  27-video course which outlines all of the major constructs and underlying principles in OpenMP. It's a wonderful course with lots of helpful information and I recommend you take it yourself. Here are my condensed notes on the course.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why OpenMP?
&lt;/h2&gt;

&lt;p&gt;Parallelism is important because of power usage - Moore's law continues to hold, but the power to runs chip with twice as many capacitors grows almost quadratically with the number of capacitors used.&lt;/p&gt;

&lt;p&gt;Instead, by running just two cores in parallel, we find a 40% reduction in the power used for a given input of work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/cMWGeJyrc9w?si=XYPQzEBkBwGHgg7_" rel="noopener noreferrer"&gt;https://youtu.be/cMWGeJyrc9w?si=XYPQzEBkBwGHgg7_&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Concurrency is async (could be happening at the same time). Parallel is when you map so that it &lt;strong&gt;is&lt;/strong&gt; done at the same time.&lt;/p&gt;

&lt;p&gt;OpenMP assumes shared address space hardware.&lt;/p&gt;

&lt;p&gt;Example of pragmas OpenMP uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#pragma omp construct clauses
&lt;/span&gt;
&lt;span class="c1"&gt;// simplest&lt;/span&gt;
&lt;span class="cp"&gt;#pragma omp parallel
&lt;/span&gt;
&lt;span class="c1"&gt;// You can combine statements like&lt;/span&gt;
&lt;span class="cp"&gt;#pragma omp parallel for
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;// Instead of&lt;/span&gt;
&lt;span class="cp"&gt;#pragma omp parallel
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cp"&gt;#pragma omp for
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Blocks must not exit in the middle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared memory machines
&lt;/h2&gt;

&lt;h3&gt;
  
  
  SMP Symmetric MultiProcessor
&lt;/h3&gt;

&lt;p&gt;Operating system treats each thread the same with same amount of time devoted to each thread.&lt;/p&gt;

&lt;p&gt;No special blocks of memory - all memory &lt;em&gt;should&lt;/em&gt; be equally performant and accessible &lt;/p&gt;

&lt;h3&gt;
  
  
  NUMA Non-Uniform Memory Architecture
&lt;/h3&gt;

&lt;p&gt;Understands and takes advantage of the fact that access time to certain memory is faster if it's physically closer to the processor .&lt;/p&gt;

&lt;p&gt;Nothing is truly an SMP these days, but we pretend it is... at least for CPUs. I'm curious about SMPs vs NUMAs in the world of GPUs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Random good info
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Race conditions and synchronization are the most common errors in parallel programming.&lt;/li&gt;
&lt;li&gt;Fundamental model behind OpenMP is the Fork-Join model&lt;/li&gt;
&lt;li&gt;A collection of threads is called a Team.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;#pragma omp parallel&lt;/code&gt; is what forks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;omp_set_num_threads(4)&lt;/code&gt; tells OMP how many threads to use if it's unspecified in the pragma.&lt;/li&gt;
&lt;li&gt;Data allocated outside the parallel block will go on the heap and be visible to all threads. Data allocated inside the block will be allocated to the stack and be visible only to the thread. They use "private" canonically. &lt;/li&gt;
&lt;li&gt;A generated function is called a thunk.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Question, OpenMP uses &lt;code&gt;pthreads&lt;/code&gt; under the hood when it compiles down.  Would an NVIDIA GPU also do that or does it compile to a CUDA-specific implementation?&lt;/p&gt;
&lt;h2&gt;
  
  
  SPMD - Single Program, Multiple Data
&lt;/h2&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each thread runs identical code against different data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cyclic distribution of loop iterations: increment the loop number by the number of threads .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To eliminate race conditions, we can promote a scalar like &lt;code&gt;sum&lt;/code&gt; to an array.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Because we may get a different number of threads than we request, you may need to have any thread (id 0 most likely) check the thread count we got.&lt;/p&gt;
&lt;h2&gt;
  
  
  False sharing:
&lt;/h2&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If independent data happens to sit on the same cache line, each update will cause cache lines to "slosh back and forth" between threads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Promoting a scalar to an array and using a round-robin strategy is one example where we create false sharing and poor scalability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;One way to avoid false sharing is by padding the array so that separate threads will be guaranteed to show up in separate cache lines. To do this, make the sum array multidimensional and use the first value &lt;code&gt;[i][0]&lt;/code&gt; for the actual value&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Synchronization solves false sharing without us having to know the underlying cache sizes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Synchronization
&lt;/h2&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Barrier Synchronization is "each thread should wait until all threads arrive"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mutual exclusion: "only one thread can access x resource"&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Constructs:&lt;br&gt;
Note that pragmas are always applicable to the thing directly below. So use blocks if you want to effect multiple things.&lt;/p&gt;
&lt;h3&gt;
  
  
  Critical
&lt;/h3&gt;

&lt;p&gt;Only one resource may access at a time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#pragma omp parallel
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;omp_get_thread_num&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="cp"&gt;#pragma omp critical
&lt;/span&gt;    &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Atomic
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#pragma omp atomic

#pragma omp atomic read|write|update|capture
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"If the low-level, high performance constructs for mutual exclusion exist on this hardware, use them. Otherwise act like this is a critical section."&lt;/p&gt;

&lt;p&gt;Is there any benefit to critical sections in this case? Perhaps critical sections allow for function calls, where atomic only refers to a scalar set operation? Yes - video just said this is just available for simple binary operations to update values. &lt;/p&gt;

&lt;h3&gt;
  
  
  Barrier
&lt;/h3&gt;

&lt;p&gt;Wait until all threads process to this point before moving on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#pragma omp parallel
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;omp_get_thread_num&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="cp"&gt;#pragma omp barrier
&lt;/span&gt;    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Flush
&lt;/h3&gt;

&lt;p&gt;Compilers are really good at optimizing where reads and writes occur. The order that you place operations in may not be the same order things happen if they are deemed to have equivalent results. This holds true for OpenMP. If you need to make reads and writes consistent, you need to use a Flush.&lt;/p&gt;

&lt;p&gt;Creates a synchronization point that says, "you are guaranteed to have a consistent view of memory with the flush set." The flush set is the list of variables inside parenthesis passed to the flush pragma. When you leave off the flush set, everything must be consistent.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All reads and writes before the flush must resolve to memory before and reads or writes to memory after the flush set.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Flushes with overlapping flush sets may not be reordered with respect to each other.&lt;/p&gt;

&lt;p&gt;For all intents and purposes, flush is equivalent to a fence in compiler terminology.&lt;/p&gt;

&lt;p&gt;Flushes are hard to get right, so OpenMP provides implicit flushes at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;entering/exiting parallel regions&lt;/li&gt;
&lt;li&gt;implicit/explicit barriers&lt;/li&gt;
&lt;li&gt;entry/exit to critical sections&lt;/li&gt;
&lt;li&gt;set/unset of a lock&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flush makes variables available to other threads. &lt;/p&gt;

&lt;p&gt;If you spin lock on a variable, you also need to put a flush in the body of the loop. That forces the compiler to read the value every time not from a cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#pragma omp flush
&lt;/span&gt;
&lt;span class="cp"&gt;#pragma omp flush(variableOne, variableTwo)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Master
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;#pragma omp master&lt;/code&gt; schedules the next block on the main thread. For most use cases of master, you usually want a barrier on the next statement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Work sharing
&lt;/h2&gt;

&lt;p&gt;Note: there is an implicit barrier at the end of any work sharing construct. &lt;code&gt;nowait&lt;/code&gt; skips the barrier. There's no way to turn off the barrier at the end of a parallel region.&lt;/p&gt;

&lt;p&gt;Constructs&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loop

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;#pragma omp for&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;#pragma omp for schedule&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;tells compiler how to split up loops between threads&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;... schedule(static, optional chunk size)&lt;/code&gt;: figure out how to break these loops into blocks at compile time &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;... schedule(dynamic, optional chunk size)&lt;/code&gt;: create a task queue and pull from it until there's no more work. This is better when you have radically different work from one thread to the next. If you leave off chunk size, it will do one at a time.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;... schedule(guided, optional chunk size)&lt;/code&gt;: start with a large chunk size and get smaller as you go along. This was popular after a paper said this was optimal, but these days we know that the other two are usually better.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;... schedule(runtime)&lt;/code&gt;: take the schedule and chunk size from the OMP_SCHEDULE environment variable or runtime library. This is useful when you aren't sure what schedule you want to use, so you compile the program once and try a bunch of them out. &lt;code&gt;omp_set_schedule()&lt;/code&gt; is how you set the schedule.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;... schedule(auto)&lt;/code&gt;: a new schedule which leaves the decision up to the compiler. How is this different from leaving off the schedule parameter? I'm guessing leaving it off means that you accept a default vs do compiler magic.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Reduction

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;#pragma omp parallel reduction (operator: variables)&lt;/code&gt; | &lt;code&gt;#pragma omp parallel for reduction(operator: variables)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;common task: Find the compute intensive loops, make it so that you can run them independently, insert omp for&lt;/li&gt;
&lt;li&gt;"Loop carry dependencies" Are variables which are dependent on the loops&lt;/li&gt;
&lt;li&gt;accumulating across a data structure is called a reduction.&lt;/li&gt;
&lt;li&gt;when we use the reduction operator, omp creates a local copy of the list of variables and initializes them to the identity of the operator (+=0, *=1)&lt;/li&gt;
&lt;li&gt;when the parallelizations are done, reduction construct combines everything into a single variable for you. Then combines that with the global copy to give you a final answer.&lt;/li&gt;
&lt;li&gt;One interesting thing is that you can do reductions over binary operations like &amp;amp;. Question, does that short circuit?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Section/Sections

&lt;ul&gt;
&lt;li&gt;schedule different portions of a sequence on different threads&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sections&lt;/code&gt; for the outer block, &lt;code&gt;section&lt;/code&gt; for each inner statement&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Single

&lt;ul&gt;
&lt;li&gt;"only the first three to hit this will execute it."&lt;/li&gt;
&lt;li&gt;note that there's still an implicit barrier because this is a work sharing construct.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;... omp single&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Task

&lt;ul&gt;
&lt;li&gt;Consists of data environment, code to execute, "Internal Control Variables" or ICV.

&lt;ul&gt;
&lt;li&gt;In OpenMP there are certain features of the environment that constructs control (like number of threads). These are ICVs.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;#pragma omp task&lt;/code&gt; , &lt;code&gt;#pragma omp taskwait&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;It looks like taskwait is what creates the implicit barrier in this case. The current thread will keep executing after it has spawned a task with the task construct.&lt;/li&gt;

&lt;li&gt;when you use recursion, look at whether you need to set anything as shared, firstprivate etc. It's so common in tasks that we default private to firstprivate.&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Lock

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;omp_init_lock()&lt;/code&gt; , &lt;code&gt;omp_set_lock()&lt;/code&gt; for acquire, &lt;code&gt;omp_unset_lock()&lt;/code&gt; for release. &lt;code&gt;omp_destroy_lock()&lt;/code&gt; to release the lock's memory. &lt;code&gt;omp_test_lock()&lt;/code&gt; to find out if the lock is available, but not wait for it to be available.&lt;/li&gt;
&lt;li&gt;Useful when you have lots of bins where you have a low chance of trying to update two things at the same time.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Runtime Library Routines
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;omp_get_num_threads()&lt;/code&gt; get the current number of threads omp works with.

&lt;ul&gt;
&lt;li&gt;outside a parallel region, this returns 1.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;omp_set_num_threads()&lt;/code&gt; set the current number of threads omp works with.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;omp_get_thread_num()&lt;/code&gt; get the current thread id.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;omp_get_max_threads()&lt;/code&gt; get the max number of threads we could use for this system.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;omp_in_parallel()&lt;/code&gt; is this running in parallel?&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;omp_set_dynamic()&lt;/code&gt;  set dynamic mode (whether omp gets smart about how many threads you get for a given parallel region)&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;omp_get_dynamic()&lt;/code&gt; is this running in dynamic mode?&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;omp_num_procs()&lt;/code&gt; how many processors are there on this system?&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment Variables
&lt;/h2&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;OMP_NUM_THREADS&lt;/code&gt; the number of threads we request, given this is an integer literal. In a production system, we almost always want to do this rather than have the code be responsible.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;OMP_STACKSIZE&lt;/code&gt; ask for extra stack size in cases where you allocate large variables to the stack. This prevents stack overflow.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;code&gt;OMP_WAIT_POLICY ACTIVE | PASSIVE&lt;/code&gt; if ACTIVE, spin the thread until you get the lock (spin lock). If PASSIVE, suspend the thread until there's available resources. Waking suspended threads costs a lot, so use PASSIVE when you expect to have long wait times and don't want the thread eating resources.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;OMP_PROC_BIND TRUE | FALSE&lt;/code&gt; if enabled, once you bind a thread to a processor, leave it there. This helps as no processor actually has uniform memory access, so we can optimize for the regions of memory closer to the processor. The disadvantage is that if something else eats up that processor (antivirus scan for example), you don't remap onto a processor which is available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Environment
&lt;/h2&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Heap is shared, stack is local to a thread.&lt;/p&gt;

&lt;p&gt;Variables can be shared, private, or firstprivate/lastprivate. First and last means "the xth time you set this, it will remain that."&lt;/p&gt;

&lt;p&gt;&lt;code&gt;... for private(tmp)&lt;/code&gt; is an example of a declaration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;firstprivate(variable)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lastprivate(variable)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can declare something as both first and last private. I have questions about what that would do.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thread private
&lt;/h3&gt;

&lt;p&gt;What if we want a global variable that's private to each thread?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#pragma omp threadprivate(counter)
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;incrementCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cp"&gt;#pragma omp parallel for copyin(counter)
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't a real use case btw, I just wanted an example. For this, we should be using atomic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging
&lt;/h2&gt;

&lt;p&gt;You need to use a parallel debugger. Visual Studio has one.&lt;/p&gt;

&lt;p&gt;Default &lt;code&gt;none&lt;/code&gt; for your data environment can help you debug, because it forces you to declare the type of everything. &lt;/p&gt;

&lt;p&gt;Remember, the compiler skips pragmas it doesn't recognize are skipped.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Model of OpenMP
&lt;/h2&gt;

&lt;p&gt;There is shared memory and each thread gets a cache. How do you guarantee whether you're getting the most up to date value?&lt;/p&gt;

&lt;p&gt;The order you put loads and stores may be quite different than what gets executed.&lt;/p&gt;

&lt;p&gt;The memory model gives you precise controls over reads (r), writes (w), and synchronization (s) operations.&lt;/p&gt;

&lt;p&gt;Sequential consistency is when r's, w's, s's are in the order you put them in. All threads will see them in this order, and execute as such. This creates a lot of constraints on optimizations.&lt;/p&gt;

&lt;p&gt;Relaxed consistency means that you can move, as long as you don't change the output. For instance, you can't change ordering around synchronization operations. You as the programmer have to use these synchronization operations to order what needs to be consistent.&lt;/p&gt;

&lt;p&gt;For more on this, see the Flush construct above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/4Hlc2KoRcFI?si=I9GJ-giVbfZLvJxq" rel="noopener noreferrer"&gt;Practical Approach to OpenMP for NVIDIA GPUs by Guray Ozen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Good quote from this course: "Computing is free, all you do is pay for data movement and the computing costs you nothing."&lt;/li&gt;
&lt;li&gt;The recapitulation video in this series focussed on the design patterns from the course. It was really good: &lt;a href="https://youtu.be/sNmGXNBzofM?si=qzR1cNPh1C02qLM1" rel="noopener noreferrer"&gt;https://youtu.be/sNmGXNBzofM?si=qzR1cNPh1C02qLM1&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cpp</category>
      <category>learning</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
