<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Dan's thoughts]]></title><description><![CDATA[The action or process of thinking]]></description><link>https://jdan.dev/</link><image><url>https://jdan.dev/favicon.png</url><title>Dan&apos;s thoughts</title><link>https://jdan.dev/</link></image><generator>Ghost 5.79</generator><lastBuildDate>Fri, 23 Feb 2024 03:39:49 GMT</lastBuildDate><atom:link href="https://jdan.dev/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Handcrafted media is coming]]></title><description><![CDATA[<p>I&apos;m sitting at an airport, sipping a cappuccino, waiting for my flight to board. I&apos;m mostly in my head, thinking about various bits and bobs, house renovation, project at work, stuff like that, when my eyes rest on two huge TVs playing the same three ads</p>]]></description><link>https://jdan.dev/handcrafted-media-is-right-around-the-corner/</link><guid isPermaLink="false">65d3684faac173000152794b</guid><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Mon, 19 Feb 2024 14:45:44 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1485846234645-a62644f84728?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDN8fEFpJTIwbW92aWV8ZW58MHx8fHwxNzA4MzUzODc2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1485846234645-a62644f84728?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDN8fEFpJTIwbW92aWV8ZW58MHx8fHwxNzA4MzUzODc2fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Handcrafted media is coming"><p>I&apos;m sitting at an airport, sipping a cappuccino, waiting for my flight to board. I&apos;m mostly in my head, thinking about various bits and bobs, house renovation, project at work, stuff like that, when my eyes rest on two huge TVs playing the same three ads back to back, each lasting roughly 10 seconds.</p><p>One is for a Samsung phone. The other is for a Samsung TV. The third is for an electric car made by Opel.</p><p>The first two though, is what caught my interest (the car too, but for reasons other than what got me typing these words).</p><p>You see, both the phone and the TV are advertised with &quot;Galaxy AI&quot;, and &quot;Artificial Intelligence&quot;, respectively.</p><p>And that got me thinking.</p><p>We&apos;re about to hit the era where &quot;Handcrafted Media&quot; is a thing. Not in the literal sense, of course, because you can&apos;t make any sort of media <em>without automated tools</em>:</p><blockquote>A handicraft, sometimes more precisely expressed as artisanal handicraft or handmade, is any of a wide variety of types of work where useful and decorative objects are made completely by one&apos;s hand or by using only simple, non-automated related tools like scissors, carving implements, or hooks.</blockquote><p><a href="https://en.wikipedia.org/wiki/Handicraft?ref=jdan.dev">https://en.wikipedia.org/wiki/Handicraft</a></p><p>Rather handcrafted in the sense that <em>without AI</em>. Both in the sense that <em>made without AI</em> and <em>consumed without AI</em>.</p><p>Now, I&#x2019;m not an expert at making movies, or tv shows. I know that a lot of people are involved, and they use a lot of tools, both physical and digital. I&#x2019;m sure that those tools are already being enhanced with &#x201C;the power of AI&#x201D;, whatever that means.</p><p>What I&#x2019;m somewhat of an expert at is consuming media <em>(aren&#x2019;t we all)</em>.</p><p>TVs already do a lot to modify images for &quot;the viewer&apos;s pleasure&quot;, like <a href="https://en.wikipedia.org/wiki/Motion_interpolation?ref=jdan.dev">frame interpolation</a>, or colour correction, or even audio tuning.</p><p>As &quot;AI&quot; is getting its foothold in TVs as well, I&apos;m sure that these will <a href="https://en.wikipedia.org/wiki/Up_to_eleven?ref=jdan.dev">go up to 11</a>. With tools like <a href="https://openai.com/sora?ref=jdan.dev">OpenAI Sora</a>, you can already generate life-like videos. Sure, they don&apos;t hold up to scrutiny, but we miss a lot of stuff already when watching movies anyway. Not to mention that Sora came out roughly 14 months after ChatGPT, so I&apos;m sure that in the coming years it will get<em> much better</em>.</p><p>And that worries me.</p><p>Imagine this: you&apos;re watching a movie on Netflix, and get an ad break. It&apos;s just the thing that you were looking at on Amazon a day before. Because soon it will be possible to have personalized ads for every human being on the planet.</p><p>Or worse - the ad <em>gets embedded</em> into the movie! Just For You! There&apos;s already a much simpler version of this for football, where the boards next to the fields can have <a href="https://www.mylondon.news/whats-on/whats-on-news/secret-behind-football-stadiums-advertising-20995972?ref=jdan.dev">different ads depending on the channel and the country that is broadcasting the match</a>.</p><p>Now take that, and insert <em>your browser history</em>.</p><p>You&#x2019;re watching The Fast and the Furius 17,5, and on the billboard in one of the scenes you see an ad for toothpaste, in your own language, for a store chain that has a store near you.</p><p>But then you rewatch it and it&#x2019;s government propaganda.</p><p>On one hand, this is worrying. But on the other, this is <em>extremely worrying</em>. Unless you&apos;re in advertisement, in which case, <em>yay</em>!</p><p>I believe people will fight this, but corporations gonna corporate, and money will most probably win at the end of the day.</p><p>Still, concessions will probably be made. &#x201C;Handcrafted&#x201D; movies will be made. Features that allow users to opt out of personalised ad breaks and/or &#x201C;AI enhancements&#x201D;. I think it&#x2019;s likely that movies themselves will have metadata to instruct your device whether certain modifications are &#x201C;preferred to be disabled&#x201D;.</p><p>I imagine a future that is terrible, and hope that I&#x2019;m wrong.</p>]]></content:encoded></item><item><title><![CDATA[Never Split The Difference]]></title><description><![CDATA[Have you ever thought "Man I wish I could negotiate"? Have I got a book recommendation for you!]]></description><link>https://jdan.dev/never-split-the-difference/</link><guid isPermaLink="false">65bbef1f4cdec80001ac3129</guid><category><![CDATA[review]]></category><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Thu, 01 Feb 2024 19:42:04 GMT</pubDate><media:content url="https://jdan.dev/content/images/2024/02/nstd-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://jdan.dev/content/images/2024/02/nstd-1.jpg" alt="Never Split The Difference"><p>Never Split The Difference by Chris Voss is one of those books that you wish you had read sooner. It is full of eye-opening insights that probably could&apos;ve saved me a <em>lot of money</em> in the past had I read it sooner.</p><p>You see, I&apos;ve never been a good negotiator - whether we&apos;re talking about haggling for a price, or just trying to push through something at work to do it my way instead of colleagues&apos; solutions.</p><p>For example, I always believed that when a price is set, it&apos;s not going to move. To me, in the context of the price of an object, buying a car is no different than buying cheese from a grocery store. Both have a price tag, and it&apos;s surreal to think that I&apos;d be able to get it for less than that - outside of a discount that the seller provides, but that&apos;s still a price that they have set, and not one that I have negotiated for.</p><p>This book believes otherwise. One of the biggest takeaways for me is the insight that <em>negotiation happens whether we acknowledge or want to take part in it or not</em>.</p><blockquote>The first step to achieving a mastery of daily negotiation is to get over your aversion to negotiating. You don&#x2019;t need to like it; you just need to understand that&#x2019;s how the world works. [<em>page 18]</em></blockquote><p>And that <em>hurts</em>, because I was mostly ignorant of this. What&apos;s worse, I was cognisant of my ignorance, and was fine with that.</p><p>This book is a great slap in the face in that regard. It talks about how to negotiate, which I understand feels like a daunting topic, but I feel that it managed to convey both a mentality, and a lot of techniques that one can use to become better at it (or, in my case, <em>start doing it</em>).</p><p>I won&apos;t outline every single idea this book tries to teach us, but the ones I found particularly interesting / useful are:</p><h2 id="start-with-listening">Start with listening</h2><p>I know that this sounds like a no-brainer, and it is, but many times when we are negotiating (or arguing about something), we use the time the other person is speaking as time to compile what we are going to say back to them.</p><p>Chris Voss says: don&apos;t. Listen to the other person, actively. Doing so not only makes them feel like they are heard, but also gives you more information about where they are coming from, which you can use to inform how you approach the negotiation.</p><h2 id="decision-making-is-governed-by-emotion">Decision making is governed by emotion</h2><p>I&apos;m sure this is also one of those &quot;<em>well <strong>DUH</strong></em>&quot; sentences, but when I think about trying to convince someone of something, I always use <em>logic</em>.</p><p>And that rarely works.</p><p>Instead, emotions always take a huge part in decisions. Logic may get you to the door, but only emotion can get you through it.</p><h2 id="calibrated-questions-are-amazing">Calibrated questions are amazing</h2><p>A calibrated question is one that specifically makes the other person try to think of a solution to your problem.</p><blockquote>Use &#x201C;How&#x201D; questions to shape the negotiating environment. You do this by using &#x201C;How can I do that?&#x201D; as a gentle version of &#x201C;No.&#x201D; [Page 186]</blockquote><p>Questions like these are good for saying &quot;no&quot; without actually saying no. They are also good at getting more information out of the other party.</p><p>Questions like &quot;How am I supposed to do that?&quot;, or &quot;What about this do you think does not work?&quot;, or &quot;Why would we choose your competitors over you?&quot;.</p><p>It&apos;s important that these are not yes/no questions. I&apos;ve been trying to switch my yes/no questions to calibrated ones, and <em>it&apos;s hard</em>. But at times when I managed to use some, the outcome was much better (not only from the actual outcome of the negotiation, but also the process, and how people felt afterwards).</p><h2 id="negotiation-requires-preparation">Negotiation requires preparation</h2><p>The other ground-shattering idea (for me, which is <em>kinda sad</em>) was that, quote:</p><blockquote>When the pressure is on, you don&#x2019;t rise to the occasion; you fall to your highest level of preparation.</blockquote><p>Such an important message that even the book itself has it on two separate pages: 211 and 251.</p><p>When going into a negotiation, it&apos;s important to be prepared. It could (and should) be preceded by hours or days of research on the topic at hand. Because when you negotiate, and you have to take a punch (for example, an extremely low-ball offer), you need to be prepared to &quot;fight back&quot;, or just walk away, knowing that it&apos;s such a bad deal that, well:</p><blockquote>No deal is better than a bad deal. [page 115]</blockquote><h2 id="closing-notes">Closing notes</h2><p>There are so many other interesting and useful bits in this book, it&apos;s hard to summarise them. From psychological factors like how people like others who are similar to them, to how much the anchoring effect can play in a negotiation (putting aside the replication crisis), to things like how uncovering unknown unknowns can massively alter your position in a negotiation, and the list goes on.</p><p>I feel it&apos;s also important to emphasise that this book is not about &quot;how to take advantage of the other person&quot;, but rather, &quot;if you don&apos;t engage in a negotiation, <em>you may be taken advantage of without you knowing</em>&quot;.</p><p>With all that gleaming words, I must admit that there were parts of the book that I did not much care for. It&apos;s written in such a way that the author&apos;s past (being a law enforcement official, an FBI negotiator, and a teacher / professor) is interleaved with his teaching, giving examples of the different topics being discussed. While it&apos;s amazing what he has done, I felt that some of these were not at all applicable to the situations I usually find myself in.</p><p>There were also the stories of what Voss&apos; pupils have done, in a typical self-help book fashion, &quot;when they did what I taught, they achieved great success&quot;. These garnered many eye-rollings.</p><p>This is a personal preference, and your mileage may vary.</p><p>All in all, amazing book, I highly recommend it.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jdan.dev/content/images/2024/02/Negotiation-Phoebe-Buffay.jpg" class="kg-image" alt="Never Split The Difference" loading="lazy" width="1200" height="1200" srcset="https://jdan.dev/content/images/size/w600/2024/02/Negotiation-Phoebe-Buffay.jpg 600w, https://jdan.dev/content/images/size/w1000/2024/02/Negotiation-Phoebe-Buffay.jpg 1000w, https://jdan.dev/content/images/2024/02/Negotiation-Phoebe-Buffay.jpg 1200w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Some techniques work better than others - for reference </span><a href="https://youtu.be/HEJJWl7B5Po?t=88&amp;ref=jdan.dev"><span style="white-space: pre-wrap;">https://youtu.be/HEJJWl7B5Po?t=88</span></a></figcaption></figure>]]></content:encoded></item><item><title><![CDATA[Make Time - a book review]]></title><description><![CDATA[<p>I bought &quot;Make Time&quot; 4 months ago, mostly because I felt that I never have time to do what I really want to do.</p><p>Since then I have picked it up and consequently forgot about having read some of it twice already, in a way proving my own</p>]]></description><link>https://jdan.dev/make-time-a-book-review/</link><guid isPermaLink="false">6599c0d76ab8f600016fb8ed</guid><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Sat, 06 Jan 2024 21:21:59 GMT</pubDate><media:content url="https://jdan.dev/content/images/2024/01/make-time-1-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://jdan.dev/content/images/2024/01/make-time-1-1.jpg" alt="Make Time - a book review"><p>I bought &quot;Make Time&quot; 4 months ago, mostly because I felt that I never have time to do what I really want to do.</p><p>Since then I have picked it up and consequently forgot about having read some of it twice already, in a way proving my own point that I indeed have no time (or that&apos;s what I thought, at least).</p><p>With this on my mind I have picked the book up a third time, and have managed to finish it surprisingly quickly. It was a conscious read - the &quot;what can I learn from this&quot; type. In fact, my first highlight was from page 3:</p><blockquote>Whatever you want time for, we think Make Time can help you get it</blockquote><p>And to it I have added my only note (the other 48 highlights didn&apos;t get any):</p><blockquote>I wonder if the book delivers on this</blockquote><p>The premise of the book is that we all have the same amount of time, every day, and the secret lies in how we choose to spend the time that we have.</p><p>The authors introduce the concept of Infinity Pools and Busy Bandwagons, which usually take up most of our times. And, speaking from personal experience, they really do.</p><p><em>Infinity Pools</em> are sources of infinite time-wasting-capabilities. Be it Youtube, Facebook, Twitter, Netflix, Reddit, or anything that&apos;s a &quot;refresh for more content&quot; type. There&apos;s just no end to how much time you can spend on these sites, apps, and TV channels</p><p><em>Busy Bandwagons</em>, on the other hand are things that, well, keep you busy. Emails, Slack, never ending Todo lists. Be more productive, do more in less, and the like.</p><p>The problem with both of these is that there&apos;s no end to them. Regardless of how many emails we answer, we always get more. There&apos;s also an infinite supply of content everywhere we look. In a sense, they take up as much time from our lives as we give them.</p><p>This book provides a framework-esque system, and many many tips and ideas on how to help you become better at getting away from the infinity pools and the busy bandwagons, and instead focus on what you actually want to do in your free time. In addition, it also provides some ideas on how to stay in the zone and resist the urge of procrastination.</p><p>In the book&apos;s actual words (from page 19):</p><blockquote>Make Time Is Just Four Steps, Repeated Every Day</blockquote><div class="kg-card kg-header-card kg-v2 kg-width-full kg-content-wide " style="background-color: #000000;" data-background-color="#000000">
            
            <div class="kg-header-card-content">
                
                <div class="kg-header-card-text kg-align-center">
                    <h2 id="these-brains-were-meant-for-steppin" class="kg-header-card-heading" style="color: #FFFFFF;" data-text-color="#FFFFFF"><span style="white-space: pre-wrap;">These brains were meant for steppin&apos;</span></h2>
                    <p id="highlight-laser-energize-and-reflect" class="kg-header-card-subheading" style="color: #FFFFFF;" data-text-color="#FFFFFF"><span style="white-space: pre-wrap;">Highlight, Laser, Energize, and Reflect</span></p>
                    
                </div>
            </div>
        </div><p>The book argues that instead of spending time on endless content and being busy for the sake of being busy, you should instead choose a <strong>Highlight</strong> each day, and aim to do that instead. This could be anything you want to do - a hobby, or spending time with the family, researching paint colours for a renovation, anything.</p><p>Then, when it comes time to actually spend time on the highlight, <em><strong>Laser</strong> Focus</em> on it. Turn off any distractions, close the door to others, immerse yourself in your highlight, create barriers for procrastination, the list goes on.</p><p>You&apos;ll eventually get tired, which is why you need to <strong><em>Energize</em></strong>. There&#x2019;s a couple of ideas on how to stay on top of your game both mentally and physically - including tips on exercising, eating, consuming caffeine and sugary stuff, and also about some steps you could do to get better at sleeping.</p><p>Lastly, <strong><em>Reflect</em></strong> on the day, what went well, what could&apos;ve gone better.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://jdan.dev/content/images/2024/01/8E819DA7-94A5-4391-B6FB-00D6C887A085_1_102.jpg" class="kg-image" alt="Make Time - a book review" loading="lazy" width="1600" height="1203" srcset="https://jdan.dev/content/images/size/w600/2024/01/8E819DA7-94A5-4391-B6FB-00D6C887A085_1_102.jpg 600w, https://jdan.dev/content/images/size/w1000/2024/01/8E819DA7-94A5-4391-B6FB-00D6C887A085_1_102.jpg 1000w, https://jdan.dev/content/images/2024/01/8E819DA7-94A5-4391-B6FB-00D6C887A085_1_102.jpg 1600w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">New adventures await!</span></figcaption></figure><p>The book contains a bunch of tips for the above 4 - things you can try to do. It acknowledges that some are easier said than done, and that not every tactic works for everyone, but they are all worth a try at least.</p><p>It closes out with reiterating that it&apos;s all just 3 (+1) steps</p><blockquote><strong>The Highlight hypothesis</strong> If you set a single intention at the start of each day, we predict you&#x2019;ll be more satisfied, joyful, and effective.<br><br><strong>The Laser hypothesis</strong> If you create barriers around the Busy Bandwagon and the Infinity Pools, we predict you&#x2019;ll focus your attention like a laser beam.<br><br><strong>The Energize hypothesis</strong> If you live a little more like a prehistoric human, we predict you&#x2019;ll enhance your mental and physical energy.</blockquote><p>Where the <em>Reflect</em> part is about you taking notes about what worked and what didn&#x2019;t.</p><h2 id="should-i-read-it">Should I read it?</h2><p>If you&#x2019;ve ever looked back at your previous hour and regretted your choice of entertainment, thought that &#x201C;Geez, I could&#x2019;ve spent that better&#x201D;, then yes. You should.</p><p>It gave me some perspective and understanding about what I&#x2019;m doing and when I&#x2019;m doing it. For example, putting the teachings of the book into practice, I&#x2019;ve read most of the book while commuting to work and back.</p><p>I have also cut back on the infinity pool usage by not going to Youtube / Podcasts / Instagram when I&#x2019;m bored. Of course I still use them for relaxing and as learning opportunities, but not so much for &#x201C;just pass the time please thanks&#x201D;</p><p>Many of the 87 tips and tricks won&#x2019;t work for most of us, but if at least some of them work, I call it a success.</p><p>And I do call it a success.</p><p>See for yourself:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://maketime.blog/?ref=jdan.dev"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Make Time</div><div class="kg-bookmark-description">Make Time is a friendly approach to finding focus and energy in your daily life. It&#x2019;s not about crushing your to-do list, optimizing every hour, or maximizing personal productivity. It&#x2019;s about creating time for what matters by rethinking the defaults of constant busyness and distraction.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://maketime.blog/wp-content/uploads/2020/04/cropped-Make-Time-square-yellow-black-270x270.png" alt="Make Time - a book review"><span class="kg-bookmark-author">Make Time</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://maketime.blog/wp-content/uploads/2019/03/crop-0-0-1000-1344-0-Jake-Cover-3D-new.jpg" alt="Make Time - a book review"></div></a></figure><p>Until next time &#x1F44B;</p>]]></content:encoded></item><item><title><![CDATA[A book in review: Checklist Manifesto by Atul Gawande]]></title><description><![CDATA[Some thoughts on "The Checklist Manifesto" by Atul Gawande, mainly the key takeaways, but also why you should read it.]]></description><link>https://jdan.dev/a-book-in-review-checklist-manifesto-by-atul-gawande/</link><guid isPermaLink="false">65806b0c2f35c700012aab09</guid><category><![CDATA[review]]></category><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Mon, 18 Dec 2023 16:11:55 GMT</pubDate><media:content url="https://jdan.dev/content/images/2023/12/checklist-manifesto-2-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://jdan.dev/content/images/2023/12/checklist-manifesto-2-1.jpg" alt="A book in review: Checklist Manifesto by Atul Gawande"><p>A while ago I read <a href="https://atulgawande.com/book/the-checklist-manifesto/?ref=jdan.dev">The Checklist Manifesto by Atul Gawande</a>. The book was entertaining to read, it conveyed the usefulness (and life-saving potentials) of checklists in a story-driven way, with some much appreciated data sprinkled in to support its message.</p><p>The message of the book is that checklists are good. In fact, checklists can save lives, provided their application is in situations where lives may be at stake.</p><p>One of the examples given in the book, where checklists have been used, is US Airways Flight 1549 encountering a bird strike shortly after take off, resulting in an emergency landing in the Hudson river.</p><p>The movie Sully is a dramatized retelling of the story. The below video shows what the crew did from after the bird strike until the captain decides that they will have to land in the river (spoilers, I guess)</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/-6HYMpmxdaA?start=82&amp;feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen title="Sully scene &quot;Can we get serious now?&quot; Tom Hanks scene part 3"></iframe></figure><p>The main thing to note here (for the purposes of this post, at least) is the captain telling the co-pilot to get the QRH - or Quick Reference Handbook.</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">QRH includes various checklists for dealing with abnormal and emergency situations, based on the equipment and furnishings on the airplane. The aircraft manufacturer-designated checklists are always included in a QRH, and often the airline company or operator will include its own procedures. - <a href="https://en.wikipedia.org/wiki/Quick_Reference_Handbook?ref=jdan.dev">Wikipedia</a></div></div><p>It&#x2019;s a bunch of checklists. Basically, each of them answer one question: &#x201C;What do we need to do when X happens&#x201D;. The copilot then goes through the book, performing each step - be it confirming some of the things (e.g.: reading on an instrument, position of a throttle), or doing the steps (e.g.: toggling systems, turning on the <a href="https://en.wikipedia.org/wiki/Auxiliary_power_unit?ref=jdan.dev">APU</a>).</p><p>The premise of the book is that the same kind of checklists could be introduced elsewhere, primarily in surgical care, to reduce surgical errors that lead to repeat surgeries, infections, or even death.</p><div class="kg-card kg-header-card kg-v2 kg-width-regular " style="background-color: #F0F0F0;" data-background-color="#F0F0F0">
            
            <div class="kg-header-card-content">
                
                <div class="kg-header-card-text ">
                    <h2 id="checklists-provide-protection-against-failures" class="kg-header-card-heading" style="color: #000000;" data-text-color="#000000"><span style="white-space: pre-wrap;">Checklists provide protection against failures</span></h2>
                    
                    
                </div>
            </div>
        </div><p>The main purposes of checklists are that they can be used as a tool to assist in preventing failures. To quote the book itself:</p><blockquote>They supply a set of checks to ensure the stupid but critical stuff is not overlooked</blockquote><p>To understand where they can be useful, and how, the book also introduces different kinds of problems: Simple, Complicated, and Complex.</p><p><strong>Simple problems</strong> are basically sets of steps. They are like a recipe. You may not yet have all the required skills to solve the problems, but once you do, there&#x2019;s a high likelihood that next time you encounter such problems, you&#x2019;ll succeed in solving them.</p><p><strong>Complicated problems</strong> are basically sets of <strong><em>simple problems</em></strong>. Like building a car, or flying a rocket to the moon. You can divide the complicated problem into many smaller, simpler problems, and when you complete each and every one of them, you also complete the complicated problem. It&#x2019;s important to note that, on a high level, complicated problems are also like recipes, just that there&#x2019;s a couple orders of magnitude more steps than for simple problems. And once you learn how to solve a problem, you can repeat and perfect the process (like sending the 2nd, 3rd, etc rocket to the moon).</p><p><strong>Complex problems</strong> on the other hand can&#x2019;t be reduced into a recipe. Raising a child being the example used by the book. Every child is unique - raising one child does not guarantee that raising the next child will go smoother or easier.</p><p>These three pretty much encompass everything that life may throw at us. And when it does, we need to be prepared. Checklists are tools that can help us deal with them, if we (or others) took the time to compile them.</p><div class="kg-card kg-header-card kg-v2 kg-width-regular " data-background-color="#F0F0F0">
            
            <picture><img class="kg-header-card-image" src="https://jdan.dev/content/images/2023/12/oh-no-5ab91493df486-1-1-1.png" srcset="https://jdan.dev/content/images/size/w600/2023/12/oh-no-5ab91493df486-1-1-1.png 600w, https://jdan.dev/content/images/2023/12/oh-no-5ab91493df486-1-1-1.png 960w" loading="lazy" alt="A book in review: Checklist Manifesto by Atul Gawande"></picture>
        
            <div class="kg-header-card-content">
                
                <div class="kg-header-card-text ">
                    <h2 id="so-something-went-wrong" class="kg-header-card-heading" style="color: #FFFFFF;" data-text-color="#FFFFFF"><span style="white-space: pre-wrap;">So something went wrong..</span></h2>
                    
                    
                </div>
            </div>
        </div><p>When doing a task, and something ultimately goes wrong, you may ultimately reach for a checklist. That&#x2019;s fair enough for simple and complicated problems - you have steps you can follow, but what about complex problems? Where there&#x2019;s no recipe, and every situation is unique?</p><p>The book brings up two examples of such cases:</p><ol><li>Building construction, where something unexpected comes up while building out one of the floors</li><li>A hurricane hits and people are left without food, water, and shelter</li></ol><p>In both cases, the book argues that centralizing the control and decision making does not work, and instead both should be pushed to the people on the field with the expertise.</p><p>People, being the ultimate problem solvers, will have to apply their expertise, and work together to come to a solution that befits the problem. More so because in such cases, the complexity of the problem tends to exceed the capabilities / expertise of a single human to solve it.</p><h2 id="building-a-checklist">Building a checklist</h2><p>The book explores two types of checklists:</p><ul><li><strong>DO-CONFIRM</strong>: Perform jobs from memory, and use the checklist to confirm that the right things were done the right way</li><li><strong>READ-DO</strong>: Carry out the task as they check them off, like a recipe.</li></ul><p>Both have their time and place, and when creating one, it&#x2019;s important to choose the right type.</p><p>Other important aspects are to make sure that the checklist is of appropriate size, contains clear, concise, and unambiguous language, and has a clear cut point when it should be applied.</p><p>The appropriate size is necessary because humans are lazy, and, given a checklist with too many items, some will inevitable be skipped either by accident or on purpose. Given a checklist with too few items will lead to people not even bothering to pick it up when needed.</p><p>As for the language, it is important as each checklist must be clearly understood by each parties to mean the same thing, otherwise it could create more problems than it tries to solve. This may entail profession-specific jargon used to some extent to aid the users.</p><p>The cut-point must also be clearly defined, so that people know exactly when to reach for the checklist.</p><p>Lastly, checklists must be tested in the real world. As <a href="https://en.wikipedia.org/wiki/Helmuth_von_Moltke_the_Elder?ref=jdan.dev">Helmuth von Moltke the Elder</a> stated in 1871 (translated):</p><blockquote>No plan of operations extends with certainty beyond the first encounter with the enemy&apos;s main strength</blockquote><p>Although he was talking about war, the same applies to trying out any of our plans in the real world.</p><h2 id="summary">Summary</h2><p>Overall, I loved the teachings of the book - it&#x2019;s something I believe we could all learn from. Although I didn&#x2019;t quite like the <em>presentation</em> of the book, as it sometimes felt like we were taking the scenic route to get to the point, it was still a book that I enjoyed reading, and would recommend to basically everyone.</p><h2 id="but-wait-there%E2%80%99s-more">But wait, there&#x2019;s more!</h2><p>Having read the book, and ruminated over it for a couple of months (most of which I spent never even thinking about it, actually), I decided to write a review-ish of it (hint: you&#x2019;re reading it). On one hand, it&#x2019;s because my <a href="https://javorszky.co.uk/2023/11/16/book-review-the-checklist-manifesto-by-atul-gawande/?ref=jdan.dev">brother did the same</a>, but on the other, I wanted to also start applying what the book teaches, and what better way to do than&#x2026; to create a checklist.</p><p>And so I did. About writing. Which I am arguably horrible at. Now, I&#x2019;m not expecting the checklist to magically make me write a lot of posts, nor to make the content interesting. Rather, I&#x2019;m expecting it to distill down all the steps, however stupid they may be, so that I won&#x2019;t miss any of them when I try to get my <a href="https://grugbrain.dev/?ref=jdan.dev">grug brain</a> to push words onto the blog.</p><p>So let me end it this way - below you&#x2019;ll find the current state of the checklist for this very post I&#x2019;m writing, captured as I&#x2019;m typing out this line.</p><p>Until next time,<br>Dan</p><figure class="kg-card kg-image-card"><img src="https://jdan.dev/content/images/2023/12/Untitled.png" class="kg-image" alt="A book in review: Checklist Manifesto by Atul Gawande" loading="lazy" width="1306" height="1494" srcset="https://jdan.dev/content/images/size/w600/2023/12/Untitled.png 600w, https://jdan.dev/content/images/size/w1000/2023/12/Untitled.png 1000w, https://jdan.dev/content/images/2023/12/Untitled.png 1306w" sizes="(min-width: 720px) 720px"></figure>]]></content:encoded></item><item><title><![CDATA[A different dependency injection in Rust]]></title><description><![CDATA[<p>I just blew my own mind, accidentally. This is a short little thingamabob about injecting dependencies. But <em>not like that</em>.</p><p>I come from a primarily Java background. I dabbled in Go and currently write a bunch in Python for backend and js/ts for frontend.</p><p>Yet I still carry with</p>]]></description><link>https://jdan.dev/a-different-dependency-injection-in-rust/</link><guid isPermaLink="false">64288928d12970003dedb8b8</guid><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Sat, 01 Apr 2023 20:46:11 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1570460147789-4e2e622bbb25?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDV8fGNoYWlufGVufDB8fHx8MTY4MDM3ODE2OA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1570460147789-4e2e622bbb25?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDV8fGNoYWlufGVufDB8fHx8MTY4MDM3ODE2OA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="A different dependency injection in Rust"><p>I just blew my own mind, accidentally. This is a short little thingamabob about injecting dependencies. But <em>not like that</em>.</p><p>I come from a primarily Java background. I dabbled in Go and currently write a bunch in Python for backend and js/ts for frontend.</p><p>Yet I still carry with me the way Mr. Martin (a.k.a. Uncle Bob) taught us all, in his Clean Code books - to inject the dependencies, any means necessary. Either directly to the class, as a constructor parameter, or through setters, or some other shenanigan. Use Spring Boot for all we care, just inject the dependency.</p><p>Not saying that this isn&apos;t possible in Rust. In fact, it&apos;s easy. Let&apos;s say, for the sake of an example, you have an <code>Action</code>, which has an <code>execute</code> method. And you&apos;d like to, well, execute the action when it&apos;s called. But what do you do when you need to use some service or client as part of that <code>execute</code> method call?</p><p>Let&apos;s talk concretions:</p><figure class="kg-card kg-code-card"><pre><code class="language-rust">// Action is the trait in question
trait Action {
    fn execute(&amp;self) -&gt; Result&lt;(), anyhow::Error&gt;;
}

// MessageAction represents a message to be sent to a specific user
struct MessageAction {
    message: String,
    user: String
}

// Implementing Action for MessageAction
impl Action for MessageAction {
    fn execute(&amp;self) -&gt; Result&lt;(), anyhow::Error&gt; {
        // do the things
        // then return
    }
}
</code></pre><figcaption>A small setup to explore</figcaption></figure><p>Now, let&apos;s say that we need to send a http request as part of the <code>MessageAction.execute()</code> call. How do we pass a certain client in?</p><p>We could do:</p><figure class="kg-card kg-code-card"><pre><code class="language-rust">trait Action {
    //                v---------------------v This is the new part
    fn execute(&amp;self, client: reqwest::Client) -&gt; Result&lt;(), anyhow::Error&gt;;
}</code></pre><figcaption>Same trait, but now client passed in as a parameter</figcaption></figure><p>But what if not all actions need a client? Or some actions need a database connection?</p><p>We could add the client to the <code>MessageAction</code> itself:</p><figure class="kg-card kg-code-card"><pre><code class="language-rust">struct MessageAction {
    // v The newly added field
    client: reqwest::Client,
    message: String,
    user: String
}</code></pre><figcaption>MessageAction struct, now with 50% more fields</figcaption></figure><p>Which, works, yes, in a way. But we&apos;re now mixing up data (<code>message</code> and <code>user</code>) with functionality (<code>client</code>). We could iterate on the idea a bit more - create a new struct, or an enum, which has the client and the action itself, but that&apos;s pretty much the same &quot;mixing data with functionality&quot;, just with more steps.</p><p>We could also create a tuple. An <em>unnamed</em> tuple. Kind of. See for yourself:</p><figure class="kg-card kg-code-card"><pre><code class="language-rust">// Note the parentheses around the type
//         here v                         and here v
impl Action for (ChatMessageAction, reqwest::Client) {
    fn execute(&amp;self) -&gt; Result&lt;(), Error&gt; {
        let (action, client) = self;
        // use the client to do stuff with the action
        todo!()
    }
}</code></pre><figcaption>Crazy to see parentheses in places we don&apos;t expect them to be</figcaption></figure><p>Meaning.. we&apos;re implementing the trait on a tuple where the first element is the <code>ChatMessageAction</code>, and the second is our http client, and then we destructure &quot;self&quot; to two variables - the action and the client.</p><p>But wait, you may be thinking to yourself, how is this better than having a struct like <code>ActionWithClient</code>, like:</p><figure class="kg-card kg-code-card"><pre><code class="language-rust">struct ActionWithClient {
    client: reqwest::Client,
    action: ChatMessageAction
}</code></pre><figcaption>&lt;3 reqwest</figcaption></figure><p>One word: <em>boilerplate</em>.</p><p>The less I need to type, the happier I am. Provided that the readability of the code does not suffer because of that. Because then I get grumpy.</p><p>Observe the difference:</p><figure class="kg-card kg-code-card"><pre><code class="language-rust">fn test() -&gt; Result&lt;(), Error&gt; {
    let message = ChatMessageAction {
        message: &quot;hello there&quot;.to_string(),
        user: &quot;general kenobi&quot;.to_string(),
    };
    let client = reqwest::Client::new();

    // First create the struct
    let struct_version = ActionWithClient { client, message };

    // Then call the execute method
    struct_version.execute()?;

    // redeclaring because Rust.
    let message = ChatMessageAction {
        message: &quot;hello there&quot;.to_string(),
        user: &quot;general kenobi&quot;.to_string(),
    };
    let client = reqwest::Client::new();

    // Pass in `client` as the second element, and call the execute method
    (message, client).execute()
}</code></pre><figcaption>Does Rust allow &amp;nbsp; as a function name? Thankfully no.</figcaption></figure><p>At this point you may still be trying to figure out the benefit of all. In essence, we&apos;re still only taking <code>reqwest::Client</code> as the second element in the tuple, why&apos;s that good for us?</p><p>Enter generics (and some boilerplate, <em>but the useful kind</em>):</p><figure class="kg-card kg-code-card"><pre><code class="language-rust">// HttpClient is a trait that represents a client that can make HTTP requests
trait HttpClient {
    fn get(&amp;self, url: &amp;str) -&gt; Result&lt;(), Error&gt;;
    fn post(&amp;self, url: &amp;str, body: &amp;str) -&gt; Result&lt;(), Error&gt;;
}

// Implement HttpClient for reqwest::Client
impl HttpClient for reqwest::Client {
    fn get(&amp;self, url: &amp;str) -&gt; Result&lt;(), Error&gt; {
        todo!()
    }

    fn post(&amp;self, url: &amp;str, body: &amp;str) -&gt; Result&lt;(), Error&gt; {
        todo!()
    }
}</code></pre><figcaption>Ignore the specifics of this trait. It&apos;s there as an example, not as a production grade abstraction of a http client</figcaption></figure><p>After creating a custom <code>trait</code>, and also implementing it for <code>reqwest::Client</code>, we&apos;re ready for the last piece of the puzzle</p><figure class="kg-card kg-code-card"><pre><code class="language-rust">impl&lt;T&gt; Action for (ChatMessageAction, T)
where
    T: HttpClient,
{
    fn execute(&amp;self) -&gt; Result&lt;(), Error&gt; {
        let (action, client) = self;
        // use the client to do stuff with the action
        todo!()
    }
}</code></pre><figcaption>&lt;3 todo! macro</figcaption></figure><p>There&apos;s some syntax to unpack, but generally speaking, it implements <code>Action</code> for all two-element tuples, where the first element is a <code>ChatMessageAction</code>, and the second is any type <code>T</code> that implements <code>HttpClient</code>. This includes <code>reqwest::Client</code> (because we implemented <code>HttpClient</code> for it manually), and anything else we may implement.. For example for testing purposes, we could have a <code>SpyClient</code> which records the calls it gets to be later inspected. We could also implement that in a test module which does not get compiled when we ship our binary.</p><p>We could get even further with this, if we want to make it as generic as possible, by introducing <em>another trait</em>:</p><figure class="kg-card kg-code-card"><pre><code class="language-rust">trait Message {
    fn message(&amp;self) -&gt; String;
    fn user(&amp;self) -&gt; String;
}</code></pre><figcaption>Message is a message and a user. You can tell I&apos;m running out of useful examples here</figcaption></figure><p>And then implement this for our different message types. Then, in the end:</p><pre><code class="language-rust">
impl&lt;M, T&gt; Action for (M, T)
where
    M: Message,
    T: HttpClient,
{
    fn execute(&amp;self) -&gt; Result&lt;(), Error&gt; {
        let (action, client) = self;
        let message = action.message();
        let user = action.user();
            
        // use the client to do stuff with the action
    }
}
</code></pre><p>And <em>that</em> is the ultimate form, right there. Implement <code>Action</code> for tuples where the first type implements <code>Message</code>, and the second one implements <code>HttpClient</code>.</p><p>We could, of course, add other traits, like <code>DatabaseClient</code>, or <code>DevNullClient</code>, and implement <code>Action</code> for those as well.</p><p>Of course, 99% of the power here is coming from generics themselves. But that 1%, that we can actually implement traits (or even just &quot;normal&quot; functions) on tuples directly, is mind blowing.</p>]]></content:encoded></item><item><title><![CDATA[First explore, then nail it down]]></title><description><![CDATA[<p>I&apos;ve been having a bit of trouble writing Rust recently. I&apos;ve been second guessing myself a lot about whether choosing it for a side project was a good idea. The reason for that is that I&apos;m creating something that I&apos;ve never done</p>]]></description><link>https://jdan.dev/first-explore-then-nail-it-down/</link><guid isPermaLink="false">63f64ad5453a1b003d35d50b</guid><category><![CDATA[Rust]]></category><category><![CDATA[Programming]]></category><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Wed, 22 Feb 2023 17:30:54 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1562504208-03d85cc8c23e?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDEyfHxtYXB8ZW58MHx8fHwxNjc3MDg1Mjkw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1562504208-03d85cc8c23e?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDEyfHxtYXB8ZW58MHx8fHwxNjc3MDg1Mjkw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="First explore, then nail it down"><p>I&apos;ve been having a bit of trouble writing Rust recently. I&apos;ve been second guessing myself a lot about whether choosing it for a side project was a good idea. The reason for that is that I&apos;m creating something that I&apos;ve never done before, and generally speaking, <em>I don&apos;t yet know what I&apos;m doing</em> (as it happens in the beginning whenever we try something new).</p><p>Rust is not very good at this, or so we may think. Here&apos;s the thing - people <s>pushing</s> evangelizing Rust do so by pointing out the absolute safety you can achieve with it. Or the most beautiful async code, or error handling, or program flow, or performance.</p><p>And it <em>can</em> do that. And it <em>does</em> do that.</p><p>The problem is if we understand this as &quot;this is the only way to write Rust code&quot;, and immediately try to write our magnum opus when starting to work on something new. But as Rome wasn&apos;t built in a day, so will we also struggle in the beginning. Not only because there are a truckload of rules you have to adhere to when writing Rust (otherwise the compiler and clippy will <em>gently</em> push you towards knowing better), but also because you have to <em>first figure out what you&apos;re building</em>, and <em>if that&apos;s what you want to build</em>!</p><p>And therein lies the problem. Of course, you can write perfect code for a problem you don&apos;t yet know how to solve, but it will be <em>hard</em>.</p><p>When you&apos;re typing some idea out for the first time, you usually don&apos;t know what it will eventually take to get right. You may have incorrect assumptions about the problem domain, or the language, or the concurrency model, or <em>all of them</em>.</p><p>If you just spent hours coming up with the best abstractions, the best control flow to go with it, and exceptionally descriptive errors and error handling, only to find out that it&apos;s actually unusable because <em>you haven&apos;t thought about how you need to put stuff into the database</em>, then that&apos;s <em>hours</em> wasted.</p><p>So what I learned is to first get it <em>done</em>, then get it <em>right</em>. Feel free to use <code>.unwrap()</code> and <code>.clone()</code> as if they were free. Use <code>anyhow</code> and make every error return <code>anyhow!</code> errors. Don&apos;t worry about panicing.</p><p>Explore the problem domain. Find working solutions.</p><p>Only after you have something that works, <em>then refactor</em>. Use Rust&apos;s advantages to your benefit. It has all the necessary tools and safeguards that allow you to refactor somewhat fearlessly. You may break things, but not in a horrible you&apos;ll-find-out-in-four-months-on-production way.</p><p>At this time, you should have a solution that <em>works</em>. Now you can replace the <code>unwrap()</code> calls with proper error propagation. Or see if you can replace the <code>.clone()</code> calls with references, or some other kind of magic.</p><p>It&apos;s okay to start with &quot;quick and dirty&quot; code.</p><p>P.s.: This of course isn&apos;t unique to Rust, as you can fall into the same pit with most other strongly typed (and even dynamic) languages. It&apos;s just that I feel it exceptionally with Rust.</p>]]></content:encoded></item><item><title><![CDATA[You can't understand the value proposition from outside]]></title><description><![CDATA[<p>This has been brewing for quite a while.</p><p>I&apos;ve witnessed many debates on programming languages - which is better, which is worse, how dumb you are for choosing one against the other.</p><p>And while I think that there is merit to these conversations - to some, at least</p>]]></description><link>https://jdan.dev/you-cant-understand-the-value-proposition-from-outside/</link><guid isPermaLink="false">63b34625bf547f003d7a93ab</guid><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Mon, 02 Jan 2023 21:53:33 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1533073526757-2c8ca1df9f1c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDN8fGRlY2lzaW9ufGVufDB8fHx8MTY3MjY5MzM0Mg&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1533073526757-2c8ca1df9f1c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDN8fGRlY2lzaW9ufGVufDB8fHx8MTY3MjY5MzM0Mg&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="You can&apos;t understand the value proposition from outside"><p>This has been brewing for quite a while.</p><p>I&apos;ve witnessed many debates on programming languages - which is better, which is worse, how dumb you are for choosing one against the other.</p><p>And while I think that there is merit to these conversations - to some, at least -, there&apos;s one aspect that I feel gets lost almost every time.</p><p>It&apos;s the fact that you, someone who&apos;s standing on the outskirts, can&apos;t fully understand the value proposition.</p><p>Alright, definition time. If we Google for &quot;define value proposition&quot;, we get this gem</p><blockquote><strong>value proposition</strong><br><em>noun</em><br>(in marketing) an innovation, service, or feature intended to make a company or product attractive to customers.</blockquote><p>Perhaps easier if we define the words separately, this time from Merriam-Webster:</p><blockquote><strong><a href="https://www.merriam-webster.com/dictionary/value?ref=jdan.dev">value</a></strong><br><em>noun</em><br>relative worth, utility, or importance</blockquote><p>..and..</p><blockquote><strong><a href="https://www.merriam-webster.com/dictionary/proposition?ref=jdan.dev">proposition</a></strong><br><em>noun</em><br>something offered for consideration or acceptance <strong>:</strong> <a href="https://www.merriam-webster.com/dictionary/proposal?ref=jdan.dev">proposal</a></blockquote><p>In simple terms, for our use-case, it&apos;s &quot;if I use this, what can this thing do (for me)?&quot;</p><p>I&apos;ve had my fair share with programming languages - I&apos;ve shipped code to production in Java, Python, Go, and Javascript / Typescript, have dabbled in shell scripting, Clojure, Kotlin, C#, and currently whacking together something in Rust.</p><p>You might say I have a problem when it comes to sticking to a single language. You might be right.</p><p>But the point is - each and every one of these languages have taught me important lessons about writing software. And most importantly, lessons I could take over to other languages.</p><h2 id="the-power-of-plain-functions">The power of plain functions</h2><p>Take <a href="https://clojure.org/?ref=jdan.dev">Clojure</a>, for example. It&apos;s a lisp-like language on the JVM (and CLR and browser, and also apparently transpiles to Dart?), wonderfully crafted with <em>very strong ideas about the value of type systems</em>. Or rather, <em>the lack thereof</em>.</p><p>See, Rich Hickey, its creator, decided that (apart from the primitive ones), 4 types are perfectly enough to write production-grade, maintainable, extensible, and performant software. An array list, a linked list, a map and a set. That&apos;s it.</p><p>But the whole language is designed around these 4 types. You can easily transform them into one another. You can iterate through them, check if they contain elements, filter them, transform them, and in the end, &quot;it&apos;s just data&quot;.</p><p>And it works. People love Clojure (<a href="https://survey.stackoverflow.co/2022/?ref=jdan.dev#technology-most-loved-dreaded-and-wanted">3rd most loved language</a> in the StackOverflow&apos;s 2022 developer survey), and do build amazing applications - like <a href="https://www.datomic.com/?ref=jdan.dev">Datomic</a> (a database), or <a href="https://nubank.com.br/en/?ref=jdan.dev">NuBank</a>, a Brazilian bank, which has most (if not all) of its services written in Clojure.</p><p>I myself have only dabbled in Clojure. And I see the glimpse of its value proposition - I see that if I were to have a project, a <em>real project</em>, that I finish, I would fully understand its value.</p><p>But until then, I can&apos;t claim that The Clojure Way is Good (or bad, for that matter). What I <em>can claim</em>, is that I&apos;ve taken a much more simplistic approach when writing code in other languages, because I saw how powerful that approach can be.</p><p>No need to over-complicate everything.</p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">I should add; Clojure is <em>way more than just &quot;no types, only functions&quot;</em>. It has an amazing REPL and philosophy and language design</div></div><h2 id="checking-everything-at-compile-time-is-good">Checking everything at compile time is good</h2><p>Then there&apos;s <a href="https://www.rust-lang.org/?ref=jdan.dev">Rust</a>. Rust <em>pushes you</em> towards types, and being explicit. Everything you do, you should use types. Create types. Implement traits. Fight the borrow checker, then yield because it&apos;s actually right.</p><p>It&apos;s a struggle. You <em>suffer</em>. But in the end, after months, it clicks. You no longer fight it. You create your nifty little types, you look ahead and see that you&apos;re about to embark on trying to implement a cyclic data structure, but you already have the scars to prove that that&apos;s not a good idea, in Rust at least.</p><p>So you rethink, redesign, reimplement. And the end is glorious.</p><p>I have enough experience with Rust to understand its value proposition.</p><p>And yet I don&apos;t, at least, not to its fullest. I don&apos;t have any services running in production (yet), so at this point I can&apos;t be sure that the promises that the borrow checker and Rust in general is giving me will come to fruition.</p><p>If the suffering up front is worth the calm after deployment. Only time will tell (and when it does, I&apos;ll write it up).</p><p>What I&apos;ve taken with myself to other languages is that I now see whether some patterns I&apos;m trying to implement would work. Whether there&apos;s a possibility of a race condition, or memory leak. I&apos;m not good at finding them, but when I do, I&apos;m happy (and a bit proud)</p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">I should add; Rust is <em>way more than just overused types and the borrow checker</em>. It has an amazing philosophy and language design and error messages and ecosystem</div></div><h1 id="how-to-make-a-decision-when-youre-looking-to-learn-a-new-language">How to make a decision when you&apos;re looking to learn a &#xA0;new language?</h1><p>Let&apos;s say you&apos;re evaluating learning a new language, say, Rust. Or Go. Or Javascript, it doesn&apos;t really matter. The point is, you have hearsay about it - people telling you how awesome or how horrible it is. Be that talks, books, or just chatting with people on Discord.</p><p>Here&apos;s what I want you to think about.</p><p>You don&apos;t know what the language is like, because, well, you don&apos;t know the language.</p><p>Your friends / coworkers / authors / presenters may very well have the adequate experience to have an authoritative opinion about it. And maybe they&apos;re very happy to share their opinions with you.</p><p>But they are an outsider <em>for you</em>. They don&apos;t have <em>your</em> experience, or <em>your</em> knowledge, or <em>your current circumstances</em>, what they have is <em>theirs</em>. So <em>their</em> experience, while it may be valuable for you, may not be as applicable for <em>you</em> as it is for <em>them</em>.</p><p>It&apos;s the same reason why people say <em>YMMV</em>. Or <em>idk tho</em>. Because they are not you and you are not them and therefore what they went through and what they have learned may not apply completely for you.</p><p>So the only way to know whether a language is worth learning <em>is to learn it</em>. There is <em>no other way</em>.</p><p>Which, when you think about it, is not the best situation to be in. By the time you actually realize what the language can offer you, you already know the language, and therefore, have made the task of making a decision void.</p><p>If you want a quicker decision, then the only piece of advice I can give is to go back and look at the <em>value proposition</em>. Think about whether that&apos;s something that could complement your already existing skillset, or if it&apos;s something that can be applied to the problems you&apos;re working on. Or heck, maybe help you find a position which you&apos;d enjoy more (and also earn more).</p><p>Look for a language that can teach you something. Be it functional programming, compile-time memory safety, REPL-driven-development, type-driven-development, or what have you.</p><p>You can (and probably should) look for people in the space you&apos;re trying to enter, and listen to what they say, and hope they&apos;re not bullshitting you.</p>]]></content:encoded></item><item><title><![CDATA[How much work do we actually work?]]></title><description><![CDATA[<p>This past two weeks I&apos;ve been off work - yearly PTO and everything. In that time, doing some personal project, I&apos;ve been contemplating about work - the things we have to do and the things we do enjoy. What better way to spend Christmas, right?</p><p>I</p>]]></description><link>https://jdan.dev/how-much-work-do-we-actually-work/</link><guid isPermaLink="false">63b1b0eebf547f003d7a934e</guid><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Sun, 01 Jan 2023 16:33:39 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1515378960530-7c0da6231fb1?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDIzfHx3b3JrfGVufDB8fHx8MTY3MjU4OTYwMA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1515378960530-7c0da6231fb1?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDIzfHx3b3JrfGVufDB8fHx8MTY3MjU4OTYwMA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="How much work do we actually work?"><p>This past two weeks I&apos;ve been off work - yearly PTO and everything. In that time, doing some personal project, I&apos;ve been contemplating about work - the things we have to do and the things we do enjoy. What better way to spend Christmas, right?</p><p>I was also listening to the Build For Tomorrow podcast&apos;s latest episode: <a href="https://www.jasonfeifer.com/episode/what-people-of-1923-predicted-about-2023/?ref=jdan.dev">What People of 1923 Predicted About 2023</a> - in there, Jason (the host), said the following:</p><blockquote>I have mostly chosen what to do for a living, and I really enjoy it, which is a luxury. Maybe for people like me, work is a kind of luxury, a kind of leisure. (...)<br>I don&apos;t know, maybe if I tallied it all up, I&apos;m doing four hours a day of work, work I don&apos;t want to do, of which there is plenty, believe me. And the rest of it, well, it&apos;s my version of luxury.</blockquote><p>This got me thinking - I never thought about making a distinction between work I enjoy doing, and work I don&apos;t. To me, it was either work (thing I&apos;m paid to do), or it wasn&apos;t (personal project at home, for example).</p><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">&#x2139;&#xFE0F;</div><div class="kg-callout-text">I highly recommend Jason Feifer&apos;s podcast, Built For Tomorrow. He also has a book out with the same title (currently on my reading list). For more info, check his website: https://www.jasonfeifer.com/</div></div><p>I&apos;m incredibly lucky to be in a profession in which I enjoy working - I&apos;m a software developer, and even when I&apos;m not working, I&apos;m either typing away on some idea (that usually never gets anywhere), or thinking about some problem I&apos;m trying to solve in one of my various projects (to the dismay of my wonderful partner).</p><p>But until now, when looking at opportunities, I only evaluated them based on how <a href="https://notacult.social/@cassidoo?ref=jdan.dev">@cassidoo</a> suggests:</p><blockquote>Money, Learning, People: the opportunity should have at least two</blockquote><p>Which means that the best opportunity is where you earn good money, can learn new things, and are surrounded by amazing people.</p><p>It never really occurred to me to also think about the ratio of work I&apos;d enjoy and work I wouldn&apos;t.</p><p>Perhaps it&apos;s time for me to add that to the list of things I weigh when deciding on staying at a company or going for another opportunity.</p><p>Because let&apos;s face it: it&apos;s important that we try to enjoy it to the best of our abilities. We spend a <em>lot of hours</em> doing work, after all.</p><p>I understand that I&apos;m privileged - I have the option to even consider an opportunity based on how much of the work I&apos;d enjoy doing versus how much of &quot;work work&quot; there would be.</p><p>Right now, current place - perhaps the scale is tipping in the wrong direction, which I now understand is the reason why I was thinking about these things this past two weeks.</p><p>So &quot;new year, new me&quot; I guess - let&apos;s start evaluating.</p>]]></content:encoded></item><item><title><![CDATA[Let’s talk about generics]]></title><description><![CDATA[Go is getting generics in 1.18, with half the devs loving and half of them hating the idea. What are they good for, really?]]></description><link>https://jdan.dev/lets-talk-about-generics/</link><guid isPermaLink="false">621d0191916ee6003d195760</guid><category><![CDATA[Foundations]]></category><category><![CDATA[Generics]]></category><category><![CDATA[Go]]></category><category><![CDATA[Rust]]></category><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Sun, 06 Mar 2022 22:48:12 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1498940757830-82f7813bf178?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGJhbGxzfGVufDB8fHx8MTY0NjA4MDc2Nw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1498940757830-82f7813bf178?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fGJhbGxzfGVufDB8fHx8MTY0NjA4MDc2Nw&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Let&#x2019;s talk about generics"><p>Some days ago there was a long discussion about generics on one of the Discord servers that I frequent. It was rather topical: <a href="https://go.dev/blog/generics-proposal?ref=jdan.dev">Go is getting support for generic typing in 1.18</a>, and the question arose: What are they good for? It&apos;s a divisive issue for sure - half the developers rejoiced that generics are finally landing, while the other half either hate it, or just don&apos;t understand <em>why Go needs generics.</em></p><p>I&apos;ve been writing code in a couple of languages in the past decade, with both languages that have generics and some that don&apos;t, so I had my fair share of run ins with this feature set.</p><p>I don&apos;t want to go into the question of <em>why</em> they are being added to Go, because I haven&apos;t followed the Go developer space for quite some time, and frankly, I don&apos;t know all the reasons.</p><p>What I would like to do, however, is try to shed some light on what generics are, and what you can use them for.</p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">&#x1F30D;</div><div class="kg-callout-text">If you&apos;re a veteran Go developer, I&apos;d like to ask you to put aside your knowledge of the ecosystem and what&apos;s possible to do with already existing tools. This post is about exploring the options that generics provide, which can be useful alongside the already powerful set of capabilities that Go has.</div></div><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://images.unsplash.com/photo-1586864387789-628af9feed72?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDR8fHRvb2x8ZW58MHx8fHwxNjQ2MDgyNDY5&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" class="kg-image" alt="Let&#x2019;s talk about generics" loading="lazy" width="5760" height="3840" srcset="https://images.unsplash.com/photo-1586864387789-628af9feed72?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDR8fHRvb2x8ZW58MHx8fHwxNjQ2MDgyNDY5&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=600 600w, https://images.unsplash.com/photo-1586864387789-628af9feed72?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDR8fHRvb2x8ZW58MHx8fHwxNjQ2MDgyNDY5&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=1000 1000w, https://images.unsplash.com/photo-1586864387789-628af9feed72?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDR8fHRvb2x8ZW58MHx8fHwxNjQ2MDgyNDY5&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=1600 1600w, https://images.unsplash.com/photo-1586864387789-628af9feed72?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDR8fHRvb2x8ZW58MHx8fHwxNjQ2MDgyNDY5&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2400 2400w" sizes="(min-width: 720px) 720px"><figcaption>Photo by <a href="https://unsplash.com/@imattsmart?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">iMattSmart</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a></figcaption></figure><h1 id="what-are-generics">What are generics?</h1><p>When we&apos;re talking about generics, we usually mean that something is generic over something else. It&apos;s usually about functions being generic over some input parameters, or structs / types / classes being generic over some of their fields.</p><p><em>But what does <strong>that</strong> mean?</em></p><p>It means slightly different things in different contexts, and we&apos;ll explore each of them in a bit.</p><p>But first, let me share a useful framing device: When designing a function, or writing up a struct or a class, it&apos;s useful to think about what kind of restrictions we&apos;re putting into place for our users (other developers, in this case), because our choices can mean the difference between a good API that is easy to use, and an API you wish you weren&apos;t forced to use.</p><p>On to the main course; I categorize generics into 4 different types:</p><ol><li>Concretions</li><li>Slot generics</li><li>Generics over functionality</li><li>Full generics</li></ol><h2 id="concretions">Concretions</h2><p>All right, I admit, concretions aren&apos;t generics. In fact, they&apos;re exactly the opposite. I still wanted to include it, because if we look at a scale of &quot;how generic is this thing&quot;, concretions are at the absolute start: none at all.</p><p>For example, imagine we have a web app and have created this struct to help us return results over the wire:</p><pre><code class="language-go">type Result struct {
	Status  uint
	Payload string
}</code></pre><p>We have a struct, which has a <code>uint</code> and a <code>string</code> field. This is a concretion, because we are <em>restricted</em> to only using a <code>uint</code> and a <code>string</code> for those fields, respectively. In other words, as the designer of this struct, we have restricted our users to these two types.</p><p>What if we wanted to return a list of items? Well:</p><pre><code class="language-go">type ListResult struct {
	Status  uint
	Payload []string
}</code></pre><p>Though this is better, we&apos;re still looking at a concretion: we can only return list of strings. If we wanted to return a list of, say, numbers, we&apos;d need a <code>NumberListResult</code>.</p><p>Having a non-trivial application, we can see where this may lead us: A proliferation of structs that are each good for one specific purpose.</p><p>This can get considerably worse if we&apos;re a library author and want to provide some convenience functions on instantiating our numerous <code>Result</code> structs. We can easily explode the codebase to handle all the use cases we can think of.</p><p>And then there&apos;s the domain of use cases that we can&apos;t think of. What if our users want to have a <code>MapStringStringResult</code>, and we absolutely loath using <code>map</code>s for anything, so much so that our brain ignores the existence of maps? There&apos;s little chance that we&apos;d have a constructor function for <em>that</em> use-case.</p><p>Let&apos;s look at how Generics can help us solve this problem.</p><h2 id="slot-generics">Slot generics</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://images.unsplash.com/photo-1595707678349-4b3f482bfbd3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDM3fHxzaGFwZSUyMHRveXxlbnwwfHx8fDE2NDY1OTQ5NzY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" class="kg-image" alt="Let&#x2019;s talk about generics" loading="lazy" width="4272" height="2848" srcset="https://images.unsplash.com/photo-1595707678349-4b3f482bfbd3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDM3fHxzaGFwZSUyMHRveXxlbnwwfHx8fDE2NDY1OTQ5NzY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=600 600w, https://images.unsplash.com/photo-1595707678349-4b3f482bfbd3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDM3fHxzaGFwZSUyMHRveXxlbnwwfHx8fDE2NDY1OTQ5NzY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=1000 1000w, https://images.unsplash.com/photo-1595707678349-4b3f482bfbd3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDM3fHxzaGFwZSUyMHRveXxlbnwwfHx8fDE2NDY1OTQ5NzY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=1600 1600w, https://images.unsplash.com/photo-1595707678349-4b3f482bfbd3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDM3fHxzaGFwZSUyMHRveXxlbnwwfHx8fDE2NDY1OTQ5NzY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2400 2400w" sizes="(min-width: 720px) 720px"><figcaption>Photo by <a href="https://unsplash.com/@accrualbowtie?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Ryan Wallace</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a></figcaption></figure><p>When I say <em>slot generics</em>, I mean that a struct (or class) is generic over one or more of the fields it contains. I call this <em>slot</em> generics, because we&apos;re specifying one or more <em>slots</em> which can hold a value of a type that will be specified later.</p><p>To go back to our previous <code>Result</code> example, we could have a generic version such that:</p><pre><code class="language-go">type Result[T any] struct {
	Status  uint
	Payload T
}</code></pre><p>This is weird syntax, but it&apos;s rather straightforward. In the above example, <code>T</code> is not a concrete type, it&apos;s an identifier, or placeholder for a type. You can read this type declaration the following way:</p><blockquote>Result is a struct which has a generic type <code>T</code>. It has a field <code>Status</code> of type <code>uint</code>, and a field <code>Payload</code>, of type whatever <code>T</code> will be when <code>Result</code> is constructed.</blockquote><div class="kg-card kg-callout-card kg-callout-card-accent"><div class="kg-callout-emoji">&#x261D;&#xFE0F;</div><div class="kg-callout-text">We also see that <code>T</code> can be <code>any</code>thing. More on this later.</div></div><p>How does one construct a generic <code>Result</code>?</p><pre><code class="language-go">package main

import &quot;fmt&quot;

type Result[P any] struct {
	Status  uint
	Payload P
}

func main() {
	//   	 &#x1F447; important bit
	result := Result[string]{
		Status:  200,
		Payload: &quot;Hello there&quot;,
	}

	fmt.Println(result)

	//        &#x1F447; also important bit
	result2 := Result[[]string]{
		Status:  200,
		Payload: []string{&quot;Hello there&quot;, &quot;General Kenobi&quot;},
	}

	fmt.Println(result2)
}

// output
{200 Hello there}
{200 [Hello there General Kenobi]}</code></pre><p>Above we&apos;ve constructed a <code>Result</code> struct with both a <code>string</code> and a <code>[]string</code>. The syntax may seem weird again, but it&apos;s as simple as the type declaration was:</p><ol><li><code>Result[string]</code> is a <code>Result[T any]</code> where <code>T = string</code></li><li><code>Result[[]string]</code> is a <code>Result[T any]</code> where <code>T = []string</code></li></ol><p>The best part is since <code>T</code> can be <code>any</code>thing, we can have nested generics (if we want, of course):</p><figure class="kg-card kg-code-card"><pre><code class="language-go">result3 := Result[Result[uint]]{
	Status: 301,
	Payload: Result[uint]{
		Status:  404,
		Payload: 401,
	},
}
fmt.Println(result3)

// output
{301 {404 401}}</code></pre><figcaption>Perfectly fine from the compiler&apos;s viewpoint.</figcaption></figure><p>But wait! Go already has the empty interface (<code>interface{}</code>), why do we need generics? We could just plop in <code>interface{}</code> and get the same results, right?</p><figure class="kg-card kg-code-card"><pre><code class="language-go">package main

import &quot;fmt&quot;

type IResult struct {
	Status  uint
	Payload interface{}
    //      &#x1F446; Oh look, a change!
}

func main() {
	iresult := IResult{
		Status:  200,
		Payload: &quot;Hello there&quot;,
	}

	fmt.Println(iresult)

	iresult2 := IResult{
		Status:  200,
		Payload: []string{&quot;Hello there&quot;, &quot;General Kenobi&quot;},
	}

	fmt.Println(iresult2)

	iresult3 := IResult{
		Status: 301,
		Payload: IResult{
			Status:  404,
			Payload: 404,
		},
	}
	fmt.Println(iresult3)
}
// output
{200 Hello there}
{200 [Hello there General Kenobi]}
{301 {404 404}}</code></pre><figcaption>Our IResult type has interface{} for Result.Payload&apos;s type</figcaption></figure><p>Yep, same result. Does this mean that Generics is just a more verbose syntactic sugar (or in this case.. salt?) for using <code>interface{}</code>?</p><p>Not exactly. Generics has two aces up its sleeve, and to show that, let&apos;s first see what happens here:</p><pre><code class="language-go">package main

import &quot;fmt&quot;

type IResult struct {
	Status  uint
	Payload interface{}
    //      &#x1F446; The interface version
}

func main() {
	iresult3 := IResult{
		Status: 301,
	//          &#x1F447; When instantiating, Payload gets an IResult as its value
		Payload: IResult{
			Status:  404,
			Payload: 404,
		},
	}
	fmt.Println(iresult3)

	// 				  &#x1F447; Overwriting the IResult with a string
	iresult3.Payload = &quot;oh no&quot;

	fmt.Println(iresult3)
}
</code></pre><p>In this instance, we&apos;re using the empty interface. Is this valid Go code? Let&apos;s ask the compiler:</p><pre><code class="language-shell">$ go run prog.go
{301 {404 404}}
{301 hehe}</code></pre><p>...yep. Alright, moving to the one with generics:</p><pre><code class="language-go">package main

import &quot;fmt&quot;

type Result[T any] struct {
	Status  uint
	Payload T
    //     &#x1F446; The generic version
}

func main() {
	// 				  &#x1F447; Typing it to an embedded Result
	iresult3 := Result[Result[uint]]{
		Status: 301,
		Payload: Result[uint]{
			Status:  404,
			Payload: 404,
		},
	}
	fmt.Println(iresult3)

	// 				  &#x1F447; Trying to overwrite it with a string
	iresult3.Payload = &quot;oh no&quot;

	fmt.Println(iresult3)
}
</code></pre><p>And the compiler says...</p><blockquote>./prog.go:20:21: cannot use &quot;oh no&quot; (untyped string constant) as Result[uint] value in assignment<br>Go build failed.</blockquote><p>Oh no. The compiler yelled at me. And it feels <em>good (your mileage may vary)</em>.</p><p>What&apos;s the difference here? Well, the empty interface, per the wonderful <a href="https://go.dev/tour/methods/14?ref=jdan.dev">Tour of Go</a>:</p><blockquote>...may hold values of any type. (Every type implements at least zero methods.)</blockquote><p>That&apos;s the absolute opposite of using a concrete type. While concretions restricts our users (devs) to using one specific type, the empty interface <em>allows anything</em>, even changing the value to another type within the same struct! And that&apos;s <em>dangerous.</em></p><p>We can thus change the value of a <code>uint</code> to a value of a <code>string</code>, because they are both <code>interface{}</code> types. The compiler is happy - we&apos;re still upholding the restrictions we&apos;ve put in place.</p><p>Another drawback of using the empty interface for this is that once we put a type in, we have lost information about <em>what</em> that is. We can of course get it back later by doing <a href="https://go.dev/ref/spec?ref=jdan.dev#Type_assertions">type assertions</a>, and, sure, it works:</p><pre><code class="language-go">package main

import &quot;fmt&quot;

type IResult struct {
	Status  uint
	Payload interface{}
    //     &#x1F446; hello interface
}

func main() {
	iresult3 := IResult{
		Status:  301,
		Payload: &quot;hehe&quot;,
	}
	fmt.Println(iresult3)

	// Type assertion right here &#x1F447;
	val, ok := iresult3.Payload.(string)
	if ok {
		fmt.Println(&quot;it&apos;s a string: &quot;, val)
	}
}
// result
{301 hehe}
it&apos;s a string:  hehe</code></pre><p>But we&apos;ve essentially delegated type checking to happen at runtime instead of at compile time, which can be the source of issues that the compiler could catch for us.</p><p>This is one of the points where generics shine: As soon as we create a <code>Result[string]</code>, the type of <code>Payload</code> for that struct will <em>always</em> be <code>string</code>. And it <em>is</em> a <code>string</code>, through and through:</p><pre><code class="language-go">type Result[T any] struct {
	Status  uint
	Payload T
    //     &#x1F446; generic type
}

func main() {
	//                 &#x1F447; instantiating with a string
	result3 := Result[string]{
		Status:  200,
		Payload: &quot;yep&quot;,
	}

	list := make([]string, 0)
    //    &#x1F447; Adding Payload to a slice of strings
	list = append(list, result3.Payload)

	fmt.Println(list)
}
// output
[yep]</code></pre><p>We couldn&apos;t say the same for the empty interface version without doing a type assertion:</p><blockquote>./prog.go:26:22: cannot use iresult3.Payload (variable of type interface{}) as type string in argument to append: need type assertion</blockquote><p>The other thing that generics lets us do is that once a <code>T</code> is specified, anything that has that type parameter <em>must be of that type</em>. </p><p>For example, let&apos;s look at the following:</p><pre><code class="language-go">package main

import &quot;fmt&quot;

type Pair[T any] struct {
	First  T
	Second T
	//    &#x1F446; Yes, you can use the same type parameter for multiple fields
}

func main() {
	//          &#x1F447; T = string, so both First and Second are string
	p := Pair[string]{
		First:  &quot;Ball&quot;,
		Second: &quot;Food&quot;,
	}

	fmt.Println(p)
}

// output
{Ball Food}</code></pre><p>Once we instantiate <code>Pair[string]</code>, both <code>First</code> and <code>Second</code> within <code>Pair</code> <em>has to be a <code>string</code></em>. We can&apos;t do <code>p.Second = 142</code>, because we&apos;ll be yelled at again:</p><blockquote>./prog.go:31:13: cannot use 142 (untyped int constant) as string value in assignment</blockquote><p>This is tremendously useful, and a huge benefit over using <code>interface{}</code> for both fields, as that would allow any combination of types both at instantiation and later down the struct&apos;s life.</p><h3 id="one-more-thing">One more thing</h3><p>Go already has slot generics, all the way back from day one. I&apos;m sure every go programmer has used them already, especially since it&apos;s part of the Tour of Go as well.</p><p>Arrays (and by extension, slices) and maps are both generic types in Go. They fit our restrictions of slot generics perfectly, although they have different syntax to what Go is getting with 1.18:</p><pre><code class="language-go">// Arrays
// primes is an array with 6 int elements
primes := [6]int{2, 3, 5, 7, 11, 13}
// names is an array with 2 string elements
names := [2]string{&quot;Alice&quot;, &quot;Bob&quot;}</code></pre><p>Arrays specify the length of its elements, as well as the type of said elements. The same holds true for maps as well:</p><pre><code class="language-go">// Maps
type Vertex struct {
	Lat, Long float64
}

// m is a map which has string keys and Vertex values
var m = map[string]Vertex{
	&quot;Bell Labs&quot;: Vertex{
		40.68433, -74.39967,
	},
	&quot;Google&quot;: Vertex{
		37.42202, -122.08408,
	},
}</code></pre><p>All in all, Go 1.18 is getting the same kind of flexibility that arrays, slices, and maps already had from day one (with regards to specifying the types at instantiation).</p><h2 id="generic-over-functionality">Generic over functionality</h2><p>We can call this generics just as much as we can call concretions generics. <em>Not really</em>.</p><p>It&apos;s interfaces. Interfaces aren&apos;t considered to be generic, but in some sense, when they are used, they <em>kinda are</em>.</p><p>Going back to our previous example, what if all we cared about for the payload is that it can be turned into a <code>string</code>?</p><pre><code class="language-go">package main

import &quot;fmt&quot;

type SResult struct {
	Status  uint
	Payload fmt.Stringer
    //      &#x1F446; A wild interface appears!
}

type Msg struct {
	message string
}

//   &#x1F447; Msg implements fmt.Stringer because of this.
func (m Msg) String() string {
	return m.message
}

func main() {
	result := SResult{
		Status:  500,
		Payload: Msg{message: &quot;Internal Server Error&quot;},
	}

	fmt.Println(&quot;result is:&quot;, result)
}
// output
result is: {500 Internal Server Error}</code></pre><p>Naturally, the above is a silly example, but it shows that interfaces can also be used for typing our structs. In that case, we&apos;re essentially telling the compiler (and our users [devs]), that we don&apos;t care what&apos;s in there, <em>as long as it implements the <code>Stringer</code> interface</em>.</p><p>That&apos;s a form of generics, in my book. The <code>SResult</code> struct above is generic over the <code>Stringer</code> interface. From a restrictions standpoint, we&apos;ve restricted the allowed types to only those that fulfill the <code>Stringer</code> contract. The compiler will check this for us, and the compiler will yell at people to provide what is required if they want the code to compile.</p><p>I don&apos;t really want to dwell too much on this - Go has this feature, and I believe it&apos;s well understood by pretty much all the devs. Nevertheless I felt that it was an important point to make, because...</p><div class="kg-card kg-header-card kg-width-full kg-size-small kg-style-dark" style data-kg-background-image><h2 class="kg-header-card-header" id="full-generics">Full generics</h2><h3 class="kg-header-card-subheader" id="what-a-segue">What a segue</h3></div><p>Remember that 13 Page-Ups ago, I mentioned that</p><blockquote>We also see that <code>T</code> can be <code>any</code>thing. More on this later.</blockquote><div class="kg-card kg-callout-card kg-callout-card-purple"><div class="kg-callout-emoji">&#x1F551;</div><div class="kg-callout-text">Later is now</div></div><p>The best part about generics is how easy it is to further restrict what our code can do. For example, to get the same functionality as the <code>SResult</code> above (that <code>Payload</code> must be a type that implements <code>fmt.Stringer</code>), we can do:</p><p></p><pre><code class="language-go">package main

import &quot;fmt&quot;

//          &#x1F447; This is the only part that&apos;s different from the above example
type SResult[T fmt.Stringer] struct {
	Status  uint
	Payload T
}

type Msg struct {
	message string
}

func (m Msg) String() string {
	return m.message
}

func main() {
	//        &#x1F447; Okay, and this as well
	result := SResult[Msg]{
		Status:  500,
		Payload: Msg{message: &quot;Internal Server Error&quot;},
	}

	fmt.Println(&quot;result is:&quot;, result)
}
// output
result is: {500 Internal Server Error}</code></pre><p>It&apos;s the same thing, we just moved some characters around. Some languages allow for a bit more powerful features when it comes to generics, for example, Rust can require that a type fulfills more than one trait (which for our purposes, are <em>kinda like </em>interfaces<em>)</em></p><p></p><pre><code class="language-rust">use std::cmp::Ord;
use std::fmt::Display;

//            &#x1F447; T must implement both Display (~fmt.Stringer) and Ord (can be ordered)
struct SResult&lt;T: Display + Ord&gt; {
    status: usize,
    payload: T,
}

fn main() {
    let r = SResult {
        status: 200,
        payload: &quot;Success!&quot;,
        //       &#x1F446; &amp;str implements both Display and Ord, so can be used here
    };
}
</code></pre><p>Unfortunately, at the moment Go doesn&apos;t seem to allow more complex restrictions, such as specifying that the type must implement more than one interfaces (or I haven&apos;t found how to do it yet). I&apos;m hopeful it&apos;ll be possible though, as this can be rather useful.</p><p>What it does allow, is creating type unions:</p><pre><code class="language-go">package main

import (
	&quot;fmt&quot;
)

//  &#x1F447; Number is either a uint, an int, or a float64
type Number interface {
	uint | int | float64
}

type SResult[T Number] struct {
	Status  uint
	Payload T
}

func main() {
	//                &#x1F447; in this case, we type it as an int
	result1 := SResult[int]{
		Status:  500,
		Payload: -10,
	}

	fmt.Println(&quot;result1 is:&quot;, result1)

	//                &#x1F447; in this case, we type it as a float64
	result2 := SResult[float64]{
		Status:  500,
		Payload: 10.0,
	}

	fmt.Println(&quot;result2 is:&quot;, result2)

	//                &#x1F447; in this case, we type it as a uint
	result3 := SResult[uint]{
		Status:  500,
		Payload: uint(10),
	}

	fmt.Println(&quot;result3 is:&quot;, result3)
}
// output
result1 is: {500 -10}
result2 is: {500 10}
result3 is: {500 10}</code></pre><p>..but as soon as we try to use a type that is <em>not</em> one of the ones we specified:</p><p></p><pre><code class="language-go">result1 := SResult[string]{
	Status:  500,
	Payload: &quot;oh no&quot;,
}
fmt.Println(&quot;result1 is:&quot;, result1)

// output
./prog.go:17:21: string does not implement Number</code></pre><p>This is important - the compiler is yelling at us again. But how is this useful? Well, one thing I haven&apos;t talked about yet is that functions can be generic as well:</p><figure class="kg-card kg-code-card"><pre><code class="language-go">package main

import (
	&quot;fmt&quot;
)

type Number interface {
	uint | int | float64
}

//      &#x1F447; Same as with structs; Add is generic over T, which has to be of type Number
func Add[T Number](a, b T) T {
	return a + b
}

func main() {
	//										           &#x1F447;int, int
	fmt.Printf(&quot;result: %[1]d, result type: %[1]T\n&quot;, Add(-10, 20))
    //										           &#x1F447;uint, uint
	fmt.Printf(&quot;result: %[1]d, result type: %[1]T\n&quot;, Add(uint(10), 20))
    //										           &#x1F447;float64, float64
	fmt.Printf(&quot;result: %[1]f, result type: %[1]T\n&quot;, Add(10.0, 20.0))
}
// output
result: 10, result type: int
result: 30, result type: uint
result: 30.000000, result type: float64</code></pre><figcaption><em>Technically</em>, they are not &quot;Number types&quot;, but types that implement the Number interface</figcaption></figure><p>Two powerful mechanisms are at work here:</p><h4 id="type-restriction-on-the-arguments">Type restriction on the arguments </h4><p><code>Add</code> is generic over its input arguments. It requires that both <code>a</code>, <code>b</code>, and its return type is a <code>Number</code>. In addition, it is also required that <code>a</code>, <code>b</code>, and the return type <em>must be of the same type</em>. For example, the following causes a compile error, even though both <code>uint</code> and <code>int</code> satisfy the <code>Number</code> interface:</p><p></p><pre><code class="language-go">Add(uint(10), int(39))
// output:
./prog.go:20:16: type int of int(39) does not match inferred type uint for T</code></pre><p>And that&apos;s <em>huge</em>. It allows us to move a myriad of type checking from runtime to compile time, as well as writing code that can leverage such restrictions, just like the silly little example for <code>Add</code> above.</p><h4 id="type-inference">Type inference</h4><p>Have you noticed that Go&apos;s type inference leapt into action? There&apos;s three things we didn&apos;t have to do:</p><ol><li>Specify what types we&apos;re calling <code>Add</code> with. The compiler was able to deduce that since we&apos;re invoking it with a valid type, we don&apos;t have to explicitly state the type like with the struct versions (Yes, I did have to add <code>uint</code>, but that was to make sure we&apos;re using that version of the function).</li><li>In case where we had to cast one of the arguments (<code>uint(10)</code>), we didn&apos;t have to do the same for the second. The compiler figured out that since <code>Add</code> requires that both its arguments <em>have to be <code>T</code></em>, the second argument <em>must also be a <code>uint</code></em>, so it did the &quot;cast&quot; for us.</li><li>The return value is typed accordingly as well, as can be seen from the output, so that was inferred for us as well. No need for type assertions &#x1F389;</li></ol><h3 id="some-closing-thoughts">Some closing thoughts</h3><p>I hope by this point you can see just how powerful generics can be, if used in the right places. Not all places are good for generics, mind you, sometimes all we need is a sturdy type and that&apos;s it. Other times we can use interfaces, but there are some situations where using generics is just a better approach altogether.</p><p>Go&apos;s <code>map</code> does this as well, and it even uses some restrictions. If we read through the <a href="https://go.dev/blog/maps?ref=jdan.dev">post about maps on the official Go language blog</a>, we&apos;ll see the following section:</p><blockquote>A Go map type looks like this:<br><br><code>map[KeyType]ValueType</code><br><br>where <code>KeyType</code> may be any type that is <a href="https://go.dev/ref/spec?ref=jdan.dev#Comparison_operators">comparable</a> (more on this later), and <code>ValueType</code> may be any type at all, including another map!</blockquote><p>...later on <em>(emphasis mine)</em>:</p><blockquote>As mentioned earlier, map keys may be of any type that is comparable. The <a href="https://go.dev/ref/spec?ref=jdan.dev#Comparison_operators">language spec</a> defines this precisely, but in short, comparable types are <strong>boolean, numeric, string, pointer, channel</strong>, and <strong>interface types</strong>, and <strong>structs </strong>or <strong>arrays </strong>that <strong>contain only those types</strong>. Notably absent from the list are slices, maps, and functions; these types cannot be compared using <code>==</code>, and may not be used as map keys.</blockquote><p>This sounds a lot like generics to me. You can use anything for the KeyType as long as those things can be compared to one another, and everything goes for the values.</p><p>I&apos;d argue Go&apos;s maps are <em>powerful</em>. I&apos;d argue that the doors generics open are <em>also powerful</em>.</p><p>Lastly, one thing I didn&apos;t mention, but is an important notion: You can have as many generic types on a struct / function as you want, and have different sets of restrictions for each of them. This is fair game:</p><pre><code class="language-go">type Tuple[T1 any, T2 any, T3 any, T4 any, T5 any, T6 any] struct {
	First  T1
	Second T2
	Third  T3
	Fourth T4
	Fifth  T5
	Sixth  T6
}</code></pre><p>Of course, you&apos;d probably want to stop at one or two generic types, anything above that can become hard to understand. As with any tools, one can go overboard and abuse it, generics isn&apos;t immune to that.</p><p>Code responsibly, and use the right tools for the job.</p><p>Until next time &#x1F44B;</p>]]></content:encoded></item><item><title><![CDATA[Year of Foundation]]></title><description><![CDATA[Foundations, foundations everywhere. In this one there's a bit about what I have planned as a personal improvement theme for 2022, from health through writing to programming]]></description><link>https://jdan.dev/year-of-foundation/</link><guid isPermaLink="false">620d8749953df2003be89f8e</guid><category><![CDATA[Yearly Themes]]></category><category><![CDATA[Foundations]]></category><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Wed, 23 Feb 2022 22:51:41 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1508802551395-fbecf2af43b1?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fGJhc2V8ZW58MHx8fHwxNjQ1MzczMTU1&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1508802551395-fbecf2af43b1?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fGJhc2V8ZW58MHx8fHwxNjQ1MzczMTU1&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Year of Foundation"><p>I&apos;ve been working in IT for over a decade now. Most of it as a Support Engineer, moving onto Software Engineer positions. Yet I chose 2022 as the <em>Year of Foundation</em>.</p><p>Don&apos;t know what this &quot;Year of&quot; thing is? Check out this post:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://jdan.dev/on-yearly-themes/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">On yearly themes</div><div class="kg-bookmark-description">The one about how new years resolutions are bad and how you can do better for yourself</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://jdan.dev/favicon.ico" alt="Year of Foundation"><span class="kg-bookmark-author">Dan&apos;s thoughts</span><span class="kg-bookmark-publisher">Daniel Javorszky</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1520549421221-3e77d246063d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDUyfHxyYWluYm93fGVufDB8fHx8MTY0NTM2NzA1OA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="Year of Foundation"></div></a></figure><p>There are many aspects of this year&apos;s theme. So far, I&apos;ve identified the following:</p><h2 id="health">Health</h2><p>Continue working out. Put focus on making the movements correctly and in control throughout the exercises. Even if that means doing the simpler routines, slower, and with smaller weights. Nail down the fundamentals before graduating to more complicated exercises.</p><h2 id="cooking">Cooking</h2><p>Learn the basics. Like how does one make bread? What are the different spices good for? Should I cook with butter or oil or fat or something completely different? Everything else builds on knowing the foundations, so it&apos;s probably that I figure out the basic stuff.</p><h2 id="blogging">Blogging</h2><p>Getting points across can be challenging. Gathering a cloud of abstract thoughts and arranging them in a coherent manner such that they convey the meaning you hope to convey is hard.</p><p>And I want to get good at it.</p><p>So hi! I&apos;m Dan. This is my blog.</p><p>I want to use this space to better my writing skills, as well as to give back to the (programming) community. I&apos;m a firm believer that writing about something is the best way to learn about it. Writing guides your thinking, and is especially good at pointing out if there are grey areas still.</p><p>Lastly, blogging acts as a simple accountability buddy to me. The theme of Foundation was a deliberate choice, and one that I didn&apos;t make lightly. By writing about it, and by documenting my progress, I&apos;m keeping myself accountable.</p><p>Although it&apos;s my tool to report the progress, some topics will have more weight than others. I plan on mostly writing about programming and software development, but who knows, the occasional weight lifting cassarrole may find its way into these pages.</p><h2 id="programming">Programming</h2><p>We, programmers, are essentially magicians. We write semi-meaningful words and obscure characters, and the computer shows us a message that says &quot;hello&quot;. Why? Because that&apos;s what we told it to do.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://images.unsplash.com/photo-1611262588019-db6cc2032da3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDI4fHxoZWxsb3xlbnwwfHx8fDE2NDU2NTYxMzY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" class="kg-image" alt="Year of Foundation" loading="lazy" width="3200" height="2400" srcset="https://images.unsplash.com/photo-1611262588019-db6cc2032da3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDI4fHxoZWxsb3xlbnwwfHx8fDE2NDU2NTYxMzY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=600 600w, https://images.unsplash.com/photo-1611262588019-db6cc2032da3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDI4fHxoZWxsb3xlbnwwfHx8fDE2NDU2NTYxMzY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=1000 1000w, https://images.unsplash.com/photo-1611262588019-db6cc2032da3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDI4fHxoZWxsb3xlbnwwfHx8fDE2NDU2NTYxMzY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=1600 1600w, https://images.unsplash.com/photo-1611262588019-db6cc2032da3?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDI4fHxoZWxsb3xlbnwwfHx8fDE2NDU2NTYxMzY&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2400 2400w" sizes="(min-width: 720px) 720px"><figcaption>3d illustration by <a href="https://unsplash.com/@alexbemore?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Alexander Shatov</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a></figcaption></figure><p>Thing is, there&apos;s <em>so much depth</em> when it comes to getting the computer to do what we want it to do. Although I&apos;ve done a fair share of exploring those options (I didn&apos;t just sit idly this past decade), there&apos;s still a lot more to cover.</p><p>So I&apos;m diving deep. I&apos;m going back to the building blocks - just shy of reaching the hardware-level abstraction. Already started by getting a couple of books about algorithms and data structures, and interpreters.</p><p>That&apos;s a good start. Let&apos;s see where it takes me.</p><h2 id="other-foundations">Other foundations?</h2><p>There are also the areas I don&apos;t yet know. I&apos;m sure 2022 will throw some curve balls and perhaps opportunities will also arise. Whatever happens, the guiding theme is Foundation: Focus on the fundamental building blocks instead of the ready-made high level end products.</p><p>Of course, it&apos;s important to stay flexible. It&apos;s entirely possible that my view on what foundational knowledge is will move throughout the year.</p><p>That&apos;s perfectly fine.</p><p>Another alternative is that I realize that what I thought the fundamentals are have a level below them on which they are built, and I descend into an ever evolving spiral of Inception-esque &quot;we need to go deeper&quot; investigations.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://images.unsplash.com/photo-1560961911-ba7ef651a56c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fGJ1aWxkaW5nJTIwYmxvY2tzfGVufDB8fHx8MTY0NTI5MTYxOQ&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" class="kg-image" alt="Year of Foundation" loading="lazy" width="4032" height="3024" srcset="https://images.unsplash.com/photo-1560961911-ba7ef651a56c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fGJ1aWxkaW5nJTIwYmxvY2tzfGVufDB8fHx8MTY0NTI5MTYxOQ&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=600 600w, https://images.unsplash.com/photo-1560961911-ba7ef651a56c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fGJ1aWxkaW5nJTIwYmxvY2tzfGVufDB8fHx8MTY0NTI5MTYxOQ&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=1000 1000w, https://images.unsplash.com/photo-1560961911-ba7ef651a56c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fGJ1aWxkaW5nJTIwYmxvY2tzfGVufDB8fHx8MTY0NTI5MTYxOQ&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=1600 1600w, https://images.unsplash.com/photo-1560961911-ba7ef651a56c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDJ8fGJ1aWxkaW5nJTIwYmxvY2tzfGVufDB8fHx8MTY0NTI5MTYxOQ&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2400 2400w" sizes="(min-width: 720px) 720px"><figcaption>We all have to stop somewhere - Photo by <a href="https://unsplash.com/@ryanquintal?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Ryan Quintal</a> / <a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit">Unsplash</a></figcaption></figure><p>That&apos;s less fine, but can still be OK to a certain degree. For example, if I were to start looking into &quot;How does Lego work&quot;, I would probably stop at the &quot;It&apos;s made of plastic&quot; and not look into how plastic is made.</p><p>So that&apos;s the plan for 2022. Here&apos;s hoping it&apos;ll be a successful one!</p><p>Until next time &#x1F44B;</p>]]></content:encoded></item><item><title><![CDATA[On yearly themes]]></title><description><![CDATA[The one about how new years resolutions are bad and how you can do better for yourself]]></description><link>https://jdan.dev/on-yearly-themes/</link><guid isPermaLink="false">620d8720953df2003be89f88</guid><category><![CDATA[Yearly Themes]]></category><dc:creator><![CDATA[Daniel]]></dc:creator><pubDate>Sun, 20 Feb 2022 14:43:16 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1520549421221-3e77d246063d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDUyfHxyYWluYm93fGVufDB8fHx8MTY0NTM2NzA1OA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1520549421221-3e77d246063d?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDUyfHxyYWluYm93fGVufDB8fHx8MTY0NTM2NzA1OA&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" alt="On yearly themes"><p>Have you ever made a new year&apos;s resolution, only to abandon it days or weeks into the year? I sure have. Comparing the average number of people at the gym on the first weeks of January versus a bit later in the year, I&apos;d say others have done so, too.</p><p>Maybe you&apos;re one of these people. Or maybe not. Perhaps you don&apos;t make such resolutions because you think they are stupid, or you don&apos;t want to subject yourself to facing the (inevitable?) failure.</p><p>But wait, I&apos;ve learned about this at work. Let&apos;s make it S.M.A.R.T.! Then, surely, I can navigate the resolution! For example:</p><blockquote class="kg-blockquote-alt">I will work out every week at least once in the next year</blockquote><p>..but then on week four, I catch a cold (or worse), and can&apos;t go. <em>I have failed</em> to accomplish the goal I set out.</p><p>The problem with this is that once you fail to do what you set out to do, often times you just give up. <em>Oh well, I&apos;ll get around to it next year</em>.</p><p>Same energy of saying &quot;<em>I&apos;ll start studying at 7 pm</em>&quot;, but then 7:01 comes and goes, and &quot;<em>Oh well, 8 pm it is</em>&quot;.</p><div class="kg-card kg-header-card kg-width-full kg-size-small kg-style-dark" style data-kg-background-image><h2 class="kg-header-card-header" id="the-theme-system">The Theme System</h2><h3 class="kg-header-card-subheader" id="new-years-resolutions-are-so-last-year">New Years Resolutions are so last year</h3></div><p>This is where The Theme System comes in. Let&apos;s look at mine from 2021:</p><blockquote class="kg-blockquote-alt">Year of Health</blockquote><p>First thing you&apos;ll notice, is that it&apos;s <em>broad</em>. It&apos;s not specific, at least not to corporate standards. But it&apos;s <em>specific enough</em> to help guide decisions and areas of focus.</p><p>Instead of spelling out all that I want to do and focus on, specifically, I just have a theme. A theme that helps me make decisions, that may (or may not) concern my health.</p><p>The real world is muddy and fuzzy, and there&apos;s never a clear cut distinction between two things with regards to their health benefits.</p><p>Sure, if the question is whether I should eat four bags of chips or a normal meal, then yes, but that&apos;s rarely the kind of decisions we make on a day-to-day basis (if it is for you, <em>I&apos;m really sorry</em>).</p><p>The questions I faced were more on the level of: </p><ol><li>should I work out or play video games?</li><li>should I be lazy and go to McDonald&apos;s (or order from them)?</li><li>should we go drinking or hiking?</li></ol><p>Writing them out, there&apos;s always an obvious answer, but if we really think about it - are they really that obvious?</p><p>Sometimes we want to take the easy route. Sometimes we are just dead tired. And it&apos;s okay to have fun.</p><p>The idea of the theme is that the overall direction, the trend of our progress is in line with what we envisioned for the year (or season, or month, or whatever).</p><p>So did it work?</p><div class="kg-card kg-header-card kg-width-full kg-size-small kg-style-dark" style data-kg-background-image><h2 class="kg-header-card-header" id="yes-yes-it-worked">Yes. Yes it worked</h2></div><p>I even managed to apply it to both physical and mental health.</p><p>From the physical perspective, I have focused on eating more healthy foods than before, went to the gym 58 times (thanks, <a href="https://fitbod.me/?ref=jdan.dev">FitBod</a>!), and had more outdoor activities (mostly hiking).</p><p>I wasn&apos;t the textbook description of health, mind you. My trips to fast food joints were in the double digits in the year, and I had my fair share of skipping leg days (or workout days, for that matter). But still, it was a better year for my health than the ones before it.</p><p>As for the mental aspect, I&apos;ve taken steps to increase my mental hygiene, like removing myself from Facebook, lowering the number of unnecessary notifications I&apos;m getting on my phone, and generally being more cognizant about how certain activities and sites/people are affecting me, mentally.</p><p>I&apos;m happy that I stumbled upon The Theme System, and I&apos;m always eager to suggest it to others if they&apos;re having some thoughts about their future. </p><p>If you&apos;d like more information, <a href="https://www.themesystem.com/?ref=jdan.dev">check the Theme System&apos;s website</a>, or this amazing video by CGP Grey (who&apos;s the co-creator of The Theme System, and also <em>much better at explaining this than I am</em>):</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/NVGuFdX5guE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure><p>Next time you want to make a new years resolution - choose a theme instead. You&apos;ll probably thank yourself a year later.</p><p>Until next time &#x1F44B;</p>]]></content:encoded></item></channel></rss>