<?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">
    <channel>
        <title><![CDATA[luciano@ratamero.com - RSS Feed]]></title>
        <description><![CDATA[luciano@ratamero.com - RSS Feed]]></description>
        <link>https://www.ratamero.com</link>
        <generator>RSS for Node</generator>
        <lastBuildDate>Mon, 03 Aug 2026 20:16:59 GMT</lastBuildDate>
        <atom:link href="https://www.ratamero.com/feed.xml" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[what I see when I go on walks]]></title>
            <description><![CDATA[<p>when I was getting my college degree in Journalism, on my first semester, I had a course called Theory of Perception. it sounded like one of those bogus course, with an artsy teacher and sketchy curriculum, that would amount to nothing.</p>
<p>the course was simple: every week the teacher would ask us to bring something we didn't notice to class, about things in our personal lives. the idea was to start rewiring our brains so we could be more effective reporters, interviewers, photographers.</p>
<p>sometimes the teacher asked us to bring something we noticed on the commute to the class, or something that could be newsworthy in the campus. sometimes it was something we didn't notice about someone important to us, like the way they walked, or how they talked. it didn't need to be big; just something.</p>
<p>some people didn't bother, and just came up with something to tell the teacher ("my mom laughs weird" became an in-joke). I took it a bit more seriously, though. in a few months, I went from "I want to turn my brain off while I commute" to "oh, there's an interesting graffiti here, I wonder what it means". since I always enjoyed photography, this class changed the way I go on walks.</p>
<p>so I invite you to do this experiment: the next time you go on a walk, look for things that would be interesting to you. you don't need a camera or your phone (though it helps). you don't even need to remember it afterwards - just look around you.</p>
<p>notice how the light hits the pavement, or how things look in a different time of day. pay attention to the people that are there, what they are doing, how they go about their lives.</p>
<p>bring something you didn't notice with you.</p>]]></description>
            <link>https://www.ratamero.com/blog/what-i-see-when-i-go-on-walks</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/what-i-see-when-i-go-on-walks</guid>
            <pubDate>Mon, 03 Aug 2026 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[On sloppification and dev costs]]></title>
            <description><![CDATA[<p>I want to start with the conclusion: I personally believe that developers that are not using AI for coding deserve a pay rise.</p>
<p>for people that know about my thoughts on AI, this is probably a logical conclusion. but for those who are not convinced, or that would like to understand a bit more about the whys, stay with me. breathe deep, this is a tough one.</p>
<h2 id="lets-start-with-some-disclaimers-you-may-skip-this"><a href="#lets-start-with-some-disclaimers-you-may-skip-this">let's start with some disclaimers (you may skip this)</a></h2>
<p>it's hard to talk about these topics, because discussing AI use on software development is tricky. you risk alienating some people if you're too careful with your words, and you risk offending others if you're not. so, for the sake of the argument, I'll try to present my thoughts in a way that establishes a common ground. hopefully.</p>
<p>as in all discussions, I will assume you always remember that I'm speaking in general. edge cases and model companies and teams will always exist. discussing them here is useless, since there's no such thing as a "one size fits all" opinion. so always assume that whatever I say is prepended with "in general".</p>
<p>second, this is not a discussion about what AI is good or bad for, or about the ethics of AI. I won't be talking about my opinions on the tech itself, so bring me to a bar and pay me a few beers if you want to discuss them (we'll need the alcohol). here, I'll try to be as down to earth as I can.</p>
<p>also, this is my opinion, folks. no need to be mad. always remember there's a human being on the other side of an internet discussion. I may also make jokes, or make things more dramatic than they are, because it wouldn't be me if I didn't.</p>
<p>ok, here we go.</p>
<h2 id="three-things-to-keep-in-mind"><a href="#three-things-to-keep-in-mind">three things to keep in mind</a></h2>
<p>to understand why I think that people should get a bonus for not using AI, we need to establish a few things.</p>
<h3 id="ai-speeds-up-software-development"><a href="#ai-speeds-up-software-development">AI speeds up software development</a></h3>
<p><em>wait, I thought you were saying that people that do NOT use AI deserve a bonus</em>, you thought.</p>
<p>yes. exactly. stay with me.</p>
<p>we already have scientific studies on how AI can speed up software development. <a href="https://sws.informatik.uni-leipzig.de/wp-content/uploads/2025/09/master_thesis_the_impact_of_llm_based_coding_assistants_on_developer_productivity.pdf">while some are inconclusive, or end up implying that results may vary from negative to positive</a>, <a href="https://arxiv.org/html/2506.10051v1">some show that there is a real and significant gain in development speed</a>.</p>
<p>since we're talking in general, and I don't want to talk too much about anecdotal stuff, let's assume a Good™ scenario, with gains of around 30%. yes, kind of a magic number. cool? cool.</p>
<h3 id="but-ai-generated-code-is-as-good-as-or-worse-than-a-good-devs-code-never-better"><a href="#but-ai-generated-code-is-as-good-as-or-worse-than-a-good-devs-code-never-better">but AI generated code is "as good as" or "worse" than a good dev's code, never better</a></h3>
<p>the general consensus is that <a href="https://arxiv.org/html/2511.04427v3">AI generated code tends to ramp up code complexity</a> and <a href="https://arxiv.org/html/2603.28592v2">add code with "code smells"</a> - you know, the classic <a href="https://en.wikipedia.org/wiki/Technical_debt">tech debt</a>. so if we want the best results, we would need to pair up these tools with a competent and experienced developer that can recognize bad code in real time or use the AI tools in better ways.</p>
<p>the thing is: competent and experienced developers already are good at what they do, and will deliver better code if they just make it themselves. they are the baseline.</p>
<p>sure, they can get <em>some</em> of the speed increase (and we're assuming they do for the sake of the argument), but usually the biggest speed ups are achieved by more junior people, with stinky code as a trade-off.</p>
<blockquote>
<p>friendly reminder: in general. there are edge cases, different ways to use AI, and person to person differences that will not be discussed here.</p>
</blockquote>
<h3 id="and-using-ai-will-potentially-deskill-your-team"><a href="#and-using-ai-will-potentially-deskill-your-team">and using AI will potentially deskill your team</a></h3>
<p>this might be the most controversial and situational topic of the bunch (that's why I threw in the "potentially" there). just to sum up this one: using AI tools <em>can</em> and probably <em>will</em> deskill your team if they're not careful, or make their learning journey longer - be it because they're not engaging with the code as well as they could, or because they're not remembering how the code was implemented, since they didn't write it themselves.</p>
<p>I'm not saying that it <strong>surely</strong> will deskill <strong>everyone</strong>; I'm not saying that your devs' brains will become goo if they touch AI. I'm saying that there is a <a href="https://www.anthropic.com/research/AI-assistance-coding-skills#conclusion">real <em>risk</em> that <em>some</em> of your devs will become over-reliant on AI tools</a> (yes, even Anthropic thinks so, though their answer is, who could've seen it coming, <strong>more</strong> AI). <a href="https://www.nature.com/articles/d41586-026-01947-1">we're seeing this happen</a> <a href="https://www.sciencedirect.com/science/article/pii/S2949820126000123">in other areas as well</a>.</p>
<p>anecdotally, I've seen it happen, both with people I worked with, and with myself. it feels pretty obvious, to be honest.</p>
<h3 id="oh-and-it-costs-money"><a href="#oh-and-it-costs-money">oh, and it costs money</a></h3>
<p>did I forget to say that? well, here it is: it costs money. you have to pay your dev <strong>and</strong> the tools.</p>
<h2 id="so-if-youre-keeping-tabs-you-know-where-this-is-going"><a href="#so-if-youre-keeping-tabs-you-know-where-this-is-going">so if you're keeping tabs, you know where this is going</a></h2>
<p><em>assuming a good scenario</em> (let's not talk about the bad ones), the pros and cons would be that AI tools:</p>
<ul>
<li>might speed your dev team up a bit. not 10x, not 2x, but a significant amount (single to double percentage points);</li>
<li>will probably give you worse code than people by themselves would, with more tech debt. bad, broken, unsafe code in the worst cases, Good™ code in the best;</li>
<li>risk making your team technically worse in the long run, and risk increasing the time it takes to transform junior devs into seniors, unless you have pretty strict guidelines on AI use;</li>
<li>cost a significant amount of extra money.</li>
</ul>
<p>if we have these in mind, we arrive at this conclusion: people in your dev team <strong>that opt not to</strong> use AI as much will tend to take a bit more time to get something done, but give you better code; will tend to keep their skills sharper in the long run; and will definitely save you money on that fancy AI subscription you're paying, even if it's means downsizing their AI subscription plan from the "Infinite Tokens" plan to the "I Only Have a Few Questions" plan.</p>
<p>so if the difference is just the type of dev person you get, and one costs more than the other, it's only fair that you just... <strong>give them the extra money you'd spend on the AI tool.</strong></p>
<h2 id="no-really-give-them-the-money"><a href="#no-really-give-them-the-money">no, really, give them the money</a></h2>
<p>jokes aside, I don't think what I'm saying is too far-fetched, or that this should be applied to every scenario. what I'm saying is that it's funny how most <strong>tech companies prefer to pay someone else</strong> - be it Anthropic, OpenAI, Cursor, whatever -, <strong>instead of investing in their own people</strong>. how they are always eager to outsource expertise.</p>
<p>so here's the deal: if the dev person wants an AI subscription, sure, give them. heck, some cases even <em>require</em> it, like projects that could benefit from LLM knowledge and/or integration. and knowing the basics about how AI tools work is important, even if it is only enough to be able to discuss it with people and future proof yourself.</p>
<p>but AI is a tool that has real costs - like those fancy JetBrains IDEs or good programming courses - and hidden costs, like tech debt and potential deskilling. if a dev person says "no, I prefer to code it myself and learn something else", not giving them a bonus is effectively punishing them for saving you money.</p>
<p>also, giving them the extra money sends your devs some hints: you're not doomed for not adopting AI, and you're not wrong in investing in yourself; you can try to use it if you want, see if it fits with your workflow, but know that there are trade-offs; and always remember that you'll be responsible for the code you put out there, AI assistance or not. there's already so much pressure to adopt AI out there, this might be worth it.</p>
<p>it also forces your company to be more mindful about the money you spend on AI subscriptions. I feel like we're currently in a spot of "we need to give the devs all them tokens", and that's not healthy for anyone involved.</p>
<p>oh, and if you're thinking "but this only means that you'd be punishing people that choose to use AI instead", <a href="#">you might need to read this post</a>. :)</p>
<hr>
<p>phew, I hope this whole thing made sense; this thought just crossed my brain while I was in the shower, and I just wanted to write it down so it doesn't keep nagging me. if there's anything that I missed, or if you want to curse at me and tell me I'm wrong about everything in life, talk to me on bluesky or mastodon.</p>
<p>this post is just a thought, not a manifesto, so please treat it as so. it's also very focused on software development, when there are <a href="https://okaneland.com/study/ai-productivity-roi-at-work/">other areas as well</a>.</p>
<p>I tried not to put my opinions on AI in this post, but I KNOW I failed. it's hard to talk about money costs, when there are so many other costs associated with AI. but hey, I tried.</p>
<p>I didn't touch on a topic I wanted to, which is "what if we don't even need the increased development speed in the first place", but I thought it was too opinionated and didn't fit well with the rest of the post.</p>
<p>also, I did not use any AI tool to write this post (typos are my own), but I did use local models and Lumo to help me find the academic papers I linked. I still read their conclusions before linking them up, though.</p>
<p>so yeah, I hope to see you next time!</p>]]></description>
            <link>https://www.ratamero.com/blog/on-sloppification-and-dev-costs</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/on-sloppification-and-dev-costs</guid>
            <pubDate>Sun, 21 Jun 2026 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[games I've played this year]]></title>
            <description><![CDATA[<p>inspired by <a href="https://pages.erickratamero.com/personal-website/posts/2025-12-16-2025-games/">my brother's blog post</a> (and knowing myself enough to understand I WON'T remember what I played the previous year), I've decided to write this one. these are not reviews, and aren't in any specific order, though I <strong>tried</strong> to keep them in the order I've played in the year.</p>
<p>I hate long intros, so here we go.</p>
<h2 id="summary"><a href="#summary">summary</a></h2>
<ul>
<li><a href="#the-ones-ive-fully-played">the ones I've fully played</a>
<ul>
<li><a href="#hollow-knight">hollow knight</a></li>
<li><a href="#contradiction">contradiction</a></li>
<li><a href="#everhood-2">everhood 2</a></li>
<li><a href="#metaphor-refantazio">metaphor: refantazio</a></li>
<li><a href="#rhythm-heaven-fever">rhythm heaven fever</a></li>
<li><a href="#hollow-knight-silksong">hollow knight: silksong</a></li>
<li><a href="#blippo">blippo+</a></li>
<li><a href="#hyperbeat">hyperbeat</a></li>
<li><a href="#unbeatable">unbeatable</a></li>
<li><a href="#year-walk">year walk</a></li>
<li><a href="#bits--bops">bits &#x26; bops</a></li>
</ul>
</li>
<li><a href="#the-ones-ive-tried-but-didnt-vibe-with">the ones I've tried, but didn't vibe with</a>
<ul>
<li><a href="#nine-sols">nine sols</a></li>
<li><a href="#void-stranger">void stranger</a></li>
<li><a href="#skin-deep">skin deep</a></li>
<li><a href="#felvidek">felvidek</a></li>
</ul>
</li>
<li><a href="#the-ones-im-currently-playing">the ones I'm currently playing</a>
<ul>
<li><a href="#possessors">possessor(s)</a></li>
<li><a href="#clair-obscur-expedition-33">clair obscur: expedition 33</a></li>
<li><a href="#metal-gear-rising-revengeance">metal gear rising: revengeance</a></li>
</ul>
</li>
</ul>
<h2 id="the-ones-ive-fully-played"><a href="#the-ones-ive-fully-played">the ones I've fully played</a></h2>
<h3 id="hollow-knight"><a href="#hollow-knight">hollow knight</a></h3>
<p>it's kinda crazy to me that I only got to play this game at the end of last year. it instantly became one of my favorites of all time (surely on the top 10). I looooove games that reward exploration, allow for player creativity to flourish, and offer a bit of <em>fair</em> challenge, so it does not surprise me that I enjoy most metroidvanias, this one included.</p>
<p>I loved it so much that, right before silksong, I've replayed it in one sitting, to get my brain ready for the next game in the series.</p>
<p>it was definitely an obsession. not as big as silksong though.</p>
<h3 id="contradiction"><a href="#contradiction">contradiction</a></h3>
<p><em>or Contradiction: Spot the Liar</em></p>
<p>this one was FUN. for those who don't know about it (I surely didn't before playing), it's a point-and-click detective game, focused on spotting, well, <em>contradictions</em> in the characters' testimonies.</p>
<p>the fun part: everything, from the setting to the characters, was acted with real people, on real places - so it feels more like you're interacting with a movie. you know, like we used to on those DVD menu games. #old</p>
<p>it all started when my brother was starting to speedrun it. the game was made with <a href="https://nwjs.io/">NW.js</a>, a very... <em>quirky</em> webkit wrapper for desktop applications that I've used professionally before. it was the perfect game for me to mod and dive under the hood. in a few days, we found some very interesting unintended behaviors, mostly related to how the game autosaves and how it flags that a cutscene has been watched.</p>
<p>so I started by fiddling with the source code, and ended up just playing the game. except for a few <strong>very</strong> obtuse puzzles, it was a great time. the story is interesting, the characters are <strong>amazing</strong>, and the game never takes itself too seriously. 100% recommend it for people that have the patience for puzzle games and don't mind looking up a guide once in a while.</p>
<h3 id="everhood-2"><a href="#everhood-2">everhood 2</a></h3>
<p>everhood 1 was a very psychedelic rhythm game I'd previously played, and had a great time with. I'm a sucker for rhythm games (as you'll see), so playing the second game in the series was a sure thing.</p>
<p>and yeah, it was basically the first one (very, <em>very</em> trippy), with a marginally worse story (if you can call it a story), and bigger scale.</p>
<p>if you like rhythm games, check it out. it's pretty goos. very goos even. nothing more to add.</p>
<h3 id="metaphor-refantazio"><a href="#metaphor-refantazio">metaphor: refantazio</a></h3>
<p>a good game. a <strong>very deeply flawed</strong> game, but a good game. metaphor is a JRPG that follows the persona blueprint very closely. it fixes a lot of gameplay issues I've had with persona games, but ends up making <em>a lot</em> of its own mistakes, mostly in the story department.</p>
<p>imo, the pacing is all over the place, and there are <strong>giant</strong> plot holes everywhere. I do mean <strong>everywhere</strong>. also, the plot twists are so frequent that you can never trust anything - so I ended up not even trying to make sense of things. I won't spoil it, just in case you want to give it a go, but there's a part of the game that you go through 5 plot twists in 30 minutes, one making less sense than the next. it's SO fatiguing.</p>
<p>the characters, art style, gameplay, and overall mechanics are good though. nothing groundbreaking, but good. if you like persona games, you'll probably like it.</p>
<p>I'm glad I've played it, but it's one of those that I'll never play again.</p>
<h3 id="rhythm-heaven-fever"><a href="#rhythm-heaven-fever">rhythm heaven fever</a></h3>
<p>wabadubadub, is that true? yeh.</p>
<p><strong>the</strong> quintessential rhythm game, made for the wii. two buttons, good minigames, and a great soundtrack is all you need to make a classic rhythm game. a <strong>must</strong> play, if you can press buttons on cue.</p>
<h3 id="hollow-knight-silksong"><a href="#hollow-knight-silksong">hollow knight: silksong</a></h3>
<p>without a doubt, my game of the year. it's like team cherry fixed all of the mistakes from hollow knight, expanded the world threefold, and learned how to be cruel.</p>
<p>let's be real: you haven't learned about this game through this post. either you already know about it and will/is/has played it, or you don't really love the genre, which is totally valid. I just need to say that ever since the game has launched, I've played it more than I'd like to admit, and sometimes I catch myself going on twitch to find some random streamer playing it for the first time.</p>
<p>and yes, I love it more than the first one. and it was the equivalent of 12 dollars here in Brazil, I've had lunches <em>this week</em> that were more expensive. it will forever be the best deal (and, at the time of writing, it's with a 20% discount on steam). a masterpiece - a <em>very challenging</em> masterpiece. and I would be mad that it didn't win more categories in the game awards, <em>if the game awards weren't a shitpost</em>.</p>
<h3 id="blippo"><a href="#blippo">blippo+</a></h3>
<p>ok, this one was a trip. the premise of the game is: you're watching cable tv. a very weird, very different cable tv. lots of channels, lots of recurrent programs and characters, and all around a good time. of course, there's more to it than just that, but I don't want to spoil it. just grab a drink and blippo+ and chill.</p>
<h3 id="hyperbeat"><a href="#hyperbeat">hyperbeat</a></h3>
<p>yeah, another rhythm game. I know, I have a problem.</p>
<p>hyperbeat was probably the most artsy of them all, and the one with the weirdest (but most amazing) control scheme. it's kinda hard to describe: you basically control a customizable avatar in a tunnel, and use the analog stick and the shoulder buttons to match the rhythm of tiles that appear in front of you. kind of like super hexagon, but way better.</p>
<p>it's a very challenging, and a very niche game, since you do need to <em>really</em> like rhythm games to enjoy it. but if you do, you'll have a great time. the characters and the instrumental electronic soundtrack are a blast. there isn't much of a story, though.</p>
<p>I'm just sad it was too short - though it's pretty cheap too.</p>
<h3 id="unbeatable"><a href="#unbeatable">unbeatable</a></h3>
<p>guess what? it's a rhythm game. :)</p>
<p>this one, in my opinion, is all about the story; and the story is <strong>reeeeeally good</strong> (except for a small section, that will remain unspoiled). the game is about a dystopic society in which music is forbidden, so the setting is really interesting.</p>
<p>but it's also about how to deal with emotions, grief, and growing up - so be sure to have water and tissues nearby, because you <strong>are</strong> going to cry.</p>
<p>the gameplay is good, but some decisions are questionable. for example: the game has two lanes (one top, one bottom), and you have to press buttons when tiles appear on them, one button per lane. the problem is that the default controls are left and right triggers, instead of up and down; though they do have a reason for that.</p>
<p>also, the left trigger controls the bottom lane, not the top one. my brain always thinks that left is up, right is down, since I read from left to right. half of the game, my brain was short-circuiting on which button I should press. changing the settings is <strong>fully</strong> recommended.</p>
<p>even so, the game slowly grew on me, even the gameplay sections. the soundtrack is very nice (if you enjoy pop punk rock), the art style is <em>gorgeous</em>, and the characters are very relatable. it also has an arcade mode, if you want to play specific tracks on different difficulties. very nice.</p>
<p>I'm fully replaying it. like, right now, as you're reading this. yes.</p>
<h3 id="year-walk"><a href="#year-walk">year walk</a></h3>
<p>not a rhythm game this time. year walk is a point-and-click adventure game made by Simogo, the studio behind some of my favorite games (sayonara wild hearts and lorelei and the laser eyes). as expected, it's a <em>very</em> interesting story that blurs the line between real and fake, with a mix of swedish folklore and spooky gameplay.</p>
<p>very short, and a great time. just be ready for jumpscares, they <em>will</em> get you.</p>
<h3 id="bits--bops"><a href="#bits--bops">bits &#x26; bops</a></h3>
<p>aaaand we're back to rhythm games. this one is an homage to the rhythm heaven series - but it can barely be called that. it's borderline plagiarism. the minigames are <strong>really</strong> "inspired" by rhythm heaven games, so if you like rhythm heaven, you'll have a good time.</p>
<p>but it's just not worth the price, in my opinion. at the time of writing, it's more expensive than silksong, and it took me 3 hours to beat. I expected at least triple the gameplay. really sad.</p>
<h2 id="the-ones-ive-tried-but-didnt-vibe-with"><a href="#the-ones-ive-tried-but-didnt-vibe-with">the ones I've tried, but didn't vibe with</a></h2>
<h3 id="nine-sols"><a href="#nine-sols">nine sols</a></h3>
<p>yeah, I know. you're thinking "how can you like hollow knight and silksong, but not nine sols?"</p>
<p>I don't know, a mix of everything? personally, I don't like the art style (I can't really explain why). I'm not a fan of its parry mechanics. and I hate, <strong>hate</strong> skill trees. the story didn't really catch me, but, being honest, it didn't really have the time to, since the gameplay didn't hold my attention enough for the story to really get started.</p>
<p>I still don't know, but I can't see myself playing this game. it feels like a metroidvania specifically made to not vibe with me. <em>*shrugs*</em></p>
<h3 id="void-stranger"><a href="#void-stranger">void stranger</a></h3>
<p>I didn't keep playing this one not because it's bad, or that it's a bad match for my tastes. this game committed the sin of having <em>too</em> interesting of a story, and combining it with interesting, but grueling and long puzzle sections. it just felt like the devs said "hey, here's a great plot and interesting characters, but to read the next page you need to solve 100 wordles. yes, every page."</p>
<p>so I ended up just watching the story on youtube. it's really good, kind of a mindfuck really, and there definitely are some gameplay sections that tickled the right parts of my brain.</p>
<p>but when your job already requires you to solve puzzles every day, seeing even more puzzles as fun is sometimes a bit too much. I'll probably revisit this one one day.</p>
<h3 id="skin-deep"><a href="#skin-deep">skin deep</a></h3>
<p>I've seen some people talk about this game with high praise, but when I tried it, it just didn't catch my attention. tbh, I didn't play it for very long, so I can't talk too much about it. seems interesting; not right now.</p>
<h3 id="felvidek"><a href="#felvidek">felvidek</a></h3>
<p>this is another one of the "seems interesting; not right now". it's a very crude game, but with a cool art style, and it seems to subvert some of the tropes of the genre. but yeah, it didn't really click, so I'll leave this for the future Luciano to deal with.</p>
<h2 id="the-ones-im-currently-playing"><a href="#the-ones-im-currently-playing">the ones I'm currently playing</a></h2>
<h3 id="possessors"><a href="#possessors">possessor(s)</a></h3>
<p>this is another metroidvania game, and it's from heart machine, the studio behind hyper light drifter, one of my favorite games. nice aesthetics, nice soundtrack, nice gameplay, but I'm still not too fond of the characters and the story, and that's kind of a deal breaker.</p>
<p>I'm one of those people that prefers a game with no story or with bland characters, instead of one that does have a story, but it's bad, or that does have characters with personality, but they're annoying.</p>
<p>hopefully things get better on the plot department. if they don't, I can see myself skipping this one.</p>
<h3 id="clair-obscur-expedition-33"><a href="#clair-obscur-expedition-33">clair obscur: expedition 33</a></h3>
<p>the motherlode of overhyping. I've played like an hour, so I don't have much to report, but this game was so hyped that I have the highest of expectations; when I know I shouldn't. I really hope it's a good one.</p>
<h3 id="metal-gear-rising-revengeance"><a href="#metal-gear-rising-revengeance">metal gear rising: revengeance</a></h3>
<p>yeah, the meme game. I mean, it was not <em>meant</em> to be a meme game, but it is. it feels like a team of edgy 15 y/o metal gear solid fans wrote it, and I love it.</p>
<p>certainly the game I'll reach for when I have a bad day. it's laughter guaranteed.</p>
<hr>
<p>well, that's it. all in all, I think this was an awesome year for gaming, and I've had a great time. I don't have any expectations for new games for 2026, but at the very least we'll have the silksong DLC.</p>
<p>if you have any recommendations, add a comment, or bug me anywhere. see you next time!</p>]]></description>
            <link>https://www.ratamero.com/blog/games-ive-played-this-year</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/games-ive-played-this-year</guid>
            <pubDate>Wed, 17 Dec 2025 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[por que eu desliguei o copilot - além da ética]]></title>
            <description><![CDATA[<p>hoje eu tava lendo uns posts de blog e dei de cara com esse post aqui, do Alberto Fortin: <a href="https://albertofortin.com/writing/coding-with-ai">https://albertofortin.com/writing/coding-with-ai</a></p>
<p>em resumo:</p>
<blockquote>
<p>TLDR: LLMs are okay at coding, but at scale they build jumbled messes. I’ve scaled back my use of AI when coding and gone back to using my brain and pen and paper.</p>
</blockquote>
<p>faz duas semanas, eu fiz a mesma coisa: desliguei tudo que era baseado em LLM pro trabalho. achei que seria legal compartilhar os motivos, os resultados e alguns pensamentos, por mais parecidos que sejam aos de Alberto. recomendo inclusive que leiam o post dele, é bem interessante.</p>
<p>e meu intuito é não discutir tanto a parte ética, apesar de eu colocar alguns dos meus pensamentos sobre isso no final do post. se você for uma pessoa só interessada na parte ética, pula pro final!</p>
<h2 id="antes-de-tudo-vou-falar-do-que-tentei"><a href="#antes-de-tudo-vou-falar-do-que-tentei">antes de tudo, vou falar do que tentei</a></h2>
<p>eu sei que tem uma parcela (pequena, mas extremamente chata) que vai olhar pra esse post e falar que eu não usei os LLMs de forma correta, ou que não configurei ou passei parâmetros suficientes pros modelos; então já vou logo me defender.</p>
<p>eu tentei <strong>bastante coisa</strong>: desde ferramentas feitas pro uso de LLM como o Cursor, até opções como o Continue + Ollama. múltiplos projetos, múltiplas linguagens de programação, múltiplos modelos, múltiplas abordagens.</p>
<p>também vou dizer que eu <strong>não acho essas ferramentas inúteis</strong>. como dev frontend, muita parte do meu trabalho é lidar com estruturas repetitivas, e esse é o melhor dos problemas pra serem resolvidos com LLM.</p>
<p>defesa feita, vamos falar dos problemas, começando pelos que todo mundo já sabe.</p>
<h2 id="os-problemas-óbvios"><a href="#os-problemas-óbvios">os problemas óbvios</a></h2>
<p>bom, o problema óbvio mais gritante é que o código gerado sempre - e eu digo <strong>sempre</strong> - é pior do que o código que você poderia escrever. se você acha que o LLM faz um código melhor que o seu, mais motivo ainda pra não usar e aprender a fazer por si só. afinal, <strong>se você não sabe fazer tão bem quanto um LLM, como que você vai revisar o código gerado</strong>?</p>
<p>"ah, mas é só dar acesso a sua base de código, fazer um <em>prompt engineering</em>, que tudo funciona bem", alguém vai dizer. vou ser direto e sincero com a minha opinião: se você tá tendo todo esse trabalho de ler artigo, testar o que funciona ou não, usar modelos diferentes pra problemas diferentes, <strong>seria mais fácil aprender como resolver o problema</strong>. você sairia sabendo mais e se sentindo uma pessoa mais confiante no que faz.</p>
<p>e aqui chegamos no meu ponto principal.</p>
<h2 id="meu-jeito-de-programar-tava-mudando---pra-pior"><a href="#meu-jeito-de-programar-tava-mudando---pra-pior">meu jeito de programar tava mudando - pra pior</a></h2>
<p>comecei a notar que eu escrevia duas palavras e fazia uma pausa, que variava de 2 a 10 segundos, esperando uma resposta do Copilot - resposta essa que precisava de modificação ao menos 70% das vezes. ok, tudo bem, é uma ferramenta útil, mas <strong>ainda tá num estágio bem ruim</strong>.</p>
<p>juro pra você que eu não teria problema em virar revisor de código, desde que o código <strong>fosse bom</strong>. e quanto maior o problema, mais ele erra, ou gera algo que exige adaptação. muitas vezes eu caía no ciclo de "não tá bom, ajeita isso pra mim, nossa, ficou pior".</p>
<p>e eu quase posso ouvir a pessoa dizendo "comigo funciona, você deve tá fazendo algo errado", mas a verdade é que se os LLMs fossem tudo isso que as pessoas dizem que é, <strong>uma galera não estaria tendo esse problema</strong>, eu incluído. se tem uma coisa que eu me orgulho como pessoa dev é que eu sobrevivi trabalhando em frontend desde os tempos da jQuery até as doideiras de hoje, e isso demonstra uma coisa: que eu <strong>ao menos consigo</strong> me adaptar a novas tecnologias.</p>
<p>mas quanto mais eu usava o Copilot, mas eu percebia que eu tava <strong>perdendo a noção de como fazer as coisas, que meu cérebro ficava com preguiça de fazer na mão</strong>, e eu ficava dependendo cada vez mais de uma ferramenta que não entrega bem, e que gera <strong>muita frustração</strong>.</p>
<h2 id="então-eu-desliguei-o-copilot-e"><a href="#então-eu-desliguei-o-copilot-e">então eu desliguei o Copilot e...</a></h2>
<p>imediatamente me senti uma pessoa improdutiva. essa é a parte que me irrita mais sobre isso tudo: <strong>eu me senti lerdo e incapaz de entregar coisas rápido</strong>. e, até certo ponto, eu tava correto em me sentir assim. agora, aquele trecho gigantesco de HTML que antes tava sendo gerado pra mim não tava mais aparecendo no autocomplete.</p>
<p>eis que eu descobri duas coisas: copiar e colar. claro que tô sendo sarcástico aqui, mas o que tava fazendo eu me sentir lento era <strong>a falta do retorno visual dos próximos passos</strong>. <strong>era a dopamina</strong> que era jogada no meu sangue toda vez o Copilot tava certo e eu não precisava digitar aquilo tudo, esquecendo de todas as vezes que eu tive que corrigir algo errado.</p>
<p>mas me forcei a passar por essa sensação, lembrar que eu trabalhei sem Copilot por mais de uma década, e que tá tudo bem. continuei o processo.</p>
<p>em dois dias, uma tarefa que era pra demorar uma semana tava pronta. o código tava limpo, lindo, <em>perfumado</em>. não tive que adaptar nada, porque não tinha nada pra adaptar; não tive que revisar nada, porque fui eu que fiz. eu me senti tão produtivo quanto antes - minto, eu me senti <strong>mais</strong> produtivo do que antes -, porque agora eu <strong>sabia o que tava acontecendo</strong>.</p>
<p>precisei passar por isso pra entender o óbvio, que <strong>fazer as coisas com calma nos faz bem</strong>. que meu problema com o uso do Copilot era que há uma tentação gigantesca de aceitar uma recompensa pequena em curto prazo, em vez de lutar por uma recompensa muito maior em longo prazo.</p>
<h2 id="quer-dizer-então-que-você-não-usa-mais-llm-pra-nada-né"><a href="#quer-dizer-então-que-você-não-usa-mais-llm-pra-nada-né">quer dizer então que você não usa mais LLM pra nada, né?</a></h2>
<p>dizer que sim seria um exagero. é fato que eu cancelei minha assinatura do Copilot e removi as extensões do meu editor de texto, mas vez ou outra eu ainda uso o Chato GPT (não é um typo).</p>
<p>um exemplo é quando eu quero converter componentes Vue escritos com a API de options pra API de composição + script setup. outro exemplo é revisar (mas não reescrever) textos grandes em inglês, principalmente quando é algo corporativo. ou seja, coisas que eu <strong>sei fazer</strong>, mas que o LLM vai me dar um retorno muito mais rápido, facilmente revisável.</p>
<p>mas vou dizer que não uso mais de um prompt por semana. fica a mensagem pro povo que gosta de LLM: <strong>dá pra viver melhor sem essas ferramentas</strong>.</p>
<p>mas e se essas ferramentas fossem boas?</p>
<h2 id="ética-e-ideologia"><a href="#ética-e-ideologia">ética e ideologia</a></h2>
<p>acho que não preciso dissertar sobre o quanto esses modelos de LLM foram desenvolvidos em cima de conteúdos com copyright. também acho desnecessário dizer o quanto de energia e recursos naturais e humanos são usados no desenvolvimento dessas ferramentas. esses pontos são totalmente factuais.</p>
<p>mas viver no capitalismo é isso: as empresas vão investir em coisas sem pensar na ética ou nas repercussões sociais. <strong>os LLMs já existem</strong>, e falar que a OpenAI é x, y ou z não vai fazer ela parar de explorar ninguém.</p>
<p>já que essas ferramentas já existem, o que nos resta é decidir se queremos usar elas ou não; ou melhor, <strong>qual o limite mínimo que nos faria usar</strong>. é o impacto energético? é a licensa do modelo? é a origem dos dados de treinamento? é o fato do processamento ser local ou remoto?</p>
<p>no final das contas, não foi nada disso que me fez tomar a decisão de cancelar o Copilot, mas o fato de eu ter certeza que <strong>eu não preciso saber mexer com LLM pra garantir meu emprego</strong>. de que eu não tô em risco de ser trocado por uma pessoa que sabe usar LLMs pra programar melhor e mais rápido.</p>
<p>pelo menos <em>por enquanto</em>.</p>
<hr>
<p>fica aqui meu convite pra você também tentar parar de usar essas ferramentas. se tiver alguma dúvida, ou quiser me xingar, só falar comigo no mastodon/bluesky/telegram, ok? até a próxima!</p>]]></description>
            <link>https://www.ratamero.com/blog/por-que-eu-desliguei-o-copilot---além-da-ética</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/por-que-eu-desliguei-o-copilot---além-da-ética</guid>
            <pubDate>Fri, 16 May 2025 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[#ajudaLuciano - Ferramentas para fazer seu blog]]></title>
            <description><![CDATA[<p>ontem, durante a live de 8 anos da <a href="https://www.youtube.com/@Dunossauro">Live de Python</a>, o Dunossauro levantou uma bandeira ótima: <a href="https://crieaporradeum.blog/">crie a porra de um blog</a>. muita gente não sabe bem como, então vou deixar aqui algumas das ferramentas que eu pessoalmente acho ótimas pra fazer um blog.</p>
<hr>
<h2 id="só-quero-escrever-uns-negócio"><a href="#só-quero-escrever-uns-negócio">só quero escrever uns negócio</a></h2>
<p>olha, nada te impede de usar alguma plataforma proprietária, mas se você tá aqui, você provavelmente quer fugir delas e ter seus próprios dados. infelizmente, é um pouco difícil fazer isso sem saber um pouco de programação.</p>
<p>então recomendo que você comece criando uma conta no <a href="https://github.com/">Github</a> ou (ainda melhor) no <a href="https://codeberg.org/">Codeberg</a>. com a conta e um pouco de conhecimentos de git e markdown, você pode usar qualquer ferramenta de geração de sites estáticos (<a href="https://en.wikipedia.org/wiki/Static_site_generator">SSG</a>) e publicar em um domínio usando <a href="https://pages.github.com/">Github Pages</a> ou <a href="https://codeberg.page/">Codeberg Pages</a>. caso você já tenha um domínio e não queira usar o domínio gerado automaticamente, você também pode usá-lo de graça.</p>
<p>daqui pra frente, vou assumir que vamos usar uma ferramenta de geração de sites estáticos e que estamos usando o Codeberg como plataforma. vamo lá!</p>
<h2 id="geradores-de-sites-estáticos"><a href="#geradores-de-sites-estáticos">geradores de sites estáticos</a></h2>
<p><em>geradores de sites estáticos</em> são ferramentas que lêem seu conteúdo de algum lugar no seu computador (em geral arquivos <code>.md</code>) e geram páginas HTML prontas para serem servidas na web. existem várias dessas ferramentas, então vou colocar aqui as <strong>minhas</strong> favoritas, em nenhuma ordem específica.</p>
<h3 id="marmite"><a href="#marmite">marmite</a></h3>
<p>o <a href="https://rochacbruno.github.io/marmite/">marmite</a> é uma ferramenta criada pelo nosso caro <a href="https://bruno.rocha.social/">Bruno Rocha</a>, escrita em Rust, e projetada pra ser extremamente veloz e direta ao ponto. ela te dá de cara tudo que você precisa: um bom tema visual, conversão de Markdown pra HTML, feed RSS, tudo.</p>
<p>caso você já tenha as ferramentas do Rust instaladas, você pode <a href="https://rochacbruno.github.io/marmite/getting-started.html#quick-start">instalar via <code>cargo</code></a>, mas caso você não tenha, dá pra baixar o binário diretamente.</p>
<p>como eu disse, o marmite é simples e direto, perfeito pra quem só quer escrever uns negócio e publicar. não vou colocar o passo a passo aqui porque <a href="https://rochacbruno.github.io/marmite">a documentação é ótima</a>, mas basicamente é só rodar um comando pra criar um post novo, escrever em Markdown e gerar o HTML.</p>
<p>testei localmente com os posts que já tenho no meu site (todos são em Markdown), e ele gerou todas as páginas e o RSS bonitinho, depois de eu adaptar um pouco os metadados.</p>
<p>como toda ferramenta simples, você vai sofrer um bocado a mais caso queira fazer algo um pouco mais rebuscado, então eu recomendo mais pra pessoas que só estejam interessadas em fazer um blog simples.</p>
<h3 id="astro"><a href="#astro">astro</a></h3>
<p>o <a href="https://astro.build/">astro</a> é, na minha opinião, um ótimo meio termo. ele não é tão veloz quanto o marmite, mas também não precisa ser, a não ser que você tenha centenas ou milhares de posts. ele também oferece tudo que você precisa, e é bem mais flexível caso você queira algo mais que só um blog.</p>
<p>pra usar o astro, você precisa ter o <a href="https://nodejs.org/en">NodeJS e o NPM instalados</a>. depois, é só entrar em <a href="https://astro.new">astro.new</a>, escolher um dos templates e rodar o comando que eles te dão. no meu caso, escolhi o template de blog, que foi gerado usando <code>npm create astro -- --template blog</code>.</p>
<p>ele tem um passo a passo bem tranquilo de seguir (em inglês) e também te dá opções de adicionar <a href="https://astro.new/latest/frameworks/">frameworks de frontend</a>, pra quando você quer adicionar algo mais dinâmico nas suas páginas e posts. a documentação como um todo é ótima também.</p>
<p>assim como o marmite, é só criar um arquivo <code>.md</code> novo na pasta de conteúdo que você tem um post novo pronto. a diferença é que você pode rodar um servidor de desenvolvimento pra ver como as coisas estão sendo geradas em tempo real.</p>
<p>ele também funcionou com os meus posts em <code>.md</code>, depois de adaptar os metadados. um único problema que tive foi que eu gosto de ter o post de blog inteiro no meu feed RSS, mas <a href="https://docs.astro.build/en/recipes/rss/#including-full-post-content">a própria documentação</a> tem instruções de como customizar o XML.</p>
<p>então se você quer algo mais customizado, ou pretende adicionar outras páginas além do blog, o astro é uma ótima ideia.</p>
<h2 id="menções-honrosas"><a href="#menções-honrosas">menções honrosas</a></h2>
<p>como não quero ficar eternamente enumerando opções (que são muitas), aqui ficam outras ferramentas que são tão boas quanto as que citei, mas que pessoalmente eu não usaria ou já usei:</p>
<ul>
<li><a href="https://gohugo.io/">Hugo</a>: extremamente famoso, escrito em Go, mas não tão focado em blogs especificamente;</li>
<li><a href="https://getpelican.com/">Pelican</a>: pros pythonistas, o Pelican é ótimo pra blogs e pequenos sites, também razoavelmente flexível;</li>
<li><a href="https://www.11ty.dev/">11ty</a>: baseado em JS, a ideia do Eleventy é ter o mínimo de configuração possível, com o máximo de flexibilidade de conteúdo e altíssima performance de geração de conteúdo. ótimo pra galera do Node que precisa de algo mais parrudo que o astro;</li>
<li>faz o teu: se você gosta de se ferrar (como eu), não é tão difícil fazer seu próprio site que usa algum framework web e ferramentas de conversão de Markdown. se quiser um péssimo exemplo, dá uma olhada no <a href="https://github.com/lucianoratamero/ratamero-com">código do meu site</a>.</li>
</ul>
<h2 id="beleza-escolhi-o-meu-e-gerei-os-htmls-e-agora"><a href="#beleza-escolhi-o-meu-e-gerei-os-htmls-e-agora">beleza, escolhi o meu e gerei os HTMLs. e agora?</a></h2>
<p>agora é <a href="https://docs.codeberg.org/codeberg-pages/">seguir o passo a passo</a> do Codeberg Pages. em resumo, o caminho mais fácil é:</p>
<ul>
<li>cria um repositório no Codeberg pro código fonte e taca seu código lá;</li>
<li>cria um segundo repositório no Codeberg chamado <code>pages</code> (tem que ser esse nome). não inicializa com nada não, e deixa a página com as instruções finais aberta;</li>
<li>na pasta do seu projeto, cria uma pasta <code>pages</code>;</li>
<li>dentro dessa nova pasta, cria outro repositório (<code>git init</code>) e aponta pro repositório <code>pages</code> usando os detalhes da página de instruções no Codeberg;</li>
<li>quando tiver com o conteúdo pronto, gera os arquivos HTML e copia tudo pra pasta <code>pages</code>;</li>
<li>commita tudo e dá push pra ambos os repos.</li>
</ul>
<p>se tudo deu certo, você vai ter seu site pronto e acessível em <code>https://nome-do-seu-usuario.codeberg.page</code>. quer um post novo? adiciona o conteúdo, gera e copia o HTML, faz o push, tá no ar.</p>
<p>se quiser exemplos de como isso funciona, dá uma olhada nos meus <a href="https://codeberg.org/lucianoratamero/astro-blog">dois</a>  <a href="https://codeberg.org/lucianoratamero/pages">repositórios</a> no Codeberg, tem todos os detalhes lá. caso queira usar o astro então, é só fazer fork e seguir com a vida.</p>
<p>depois é <a href="https://docs.codeberg.org/codeberg-pages/using-custom-domain/">configurar seu domínio</a>, caso queira e tenha um, e seguir postando! qualquer dúvida ou sugestão, manda aqui nos comentários ou fala comigo no <a href="https://bolha.us/@lucianoratamero">Mastodon</a> ou <a href="https://bsky.app/profile/ratamero.com">Bluesky</a>. abraço pra quem é de abraço e até a próxima!</p>]]></description>
            <link>https://www.ratamero.com/blog/ferramentas-para-fazer-seu-blog</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/ferramentas-para-fazer-seu-blog</guid>
            <pubDate>Tue, 22 Apr 2025 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Por que empresas não migram pra Svelte?]]></title>
            <description><![CDATA[<p>quanto mais eu trabalho com outras tecnologias, mais eu vejo que trabalhar com <a href="/notes/Svelte">Svelte</a> é <strong>maravilhoso</strong>. o modelo mental é simples, os módulos embutidos resolvem praticamente tudo do dia-a-dia e o resultado é uma aplicação leve, performática, bonita, acessível e fácil de usar.</p>
<p>então por que as empresas não migram pra Svelte? e o que nós podemos fazer sobre isso?</p>
<hr>
<p>acho que consigo resumir meu pensamento em alguns pontos, então aqui vai o tl;dr:</p>
<ul>
<li>as empresas que <strong>vendem</strong> frontend moderno <strong>acham "mais fácil"</strong> contratar pessoas e vender projetos que usam React ou Vue;</li>
<li>empresas que <strong>compram</strong> esse software <strong>não querem o risco</strong> de perder dinheiro comprando algo que usa uma ferramenta vista como nova, quando as alternativas são mais sólidas e famosas, como React e Vue;</li>
<li>empresas em geral não querem <strong>gastar dinheiro</strong> pesquisando ferramentas novas, quando as que existem funcionam.</li>
</ul>
<p>vou usar o React como exemplo principal pra comparar, mas mais como um símbolo de ferramentas com maior adoção. então bora explorar cada tópico um pouquinho mais.</p>
<h2 id="contratar-pessoas-e-vender-projetos-em-react-é-mais-fácil"><a href="#contratar-pessoas-e-vender-projetos-em-react-é-mais-fácil">contratar pessoas e vender projetos em React é "mais fácil"</a></h2>
<p>já ouvi essa frase várias vezes, principalmente quando citei que Svelte - principalmente o Svelte 5 - era muito fácil de aprender e de manter a longo prazo. as empresas adotam essa postura de contratar pessoas e vender projetos em React por ser <strong>uma decisão mais fácil</strong>, cujos <strong>custos são fáceis de estimar</strong>, mesmo que isso acarrete em ineficiências.</p>
<p>por exemplo, abrir vagas em Svelte significa:</p>
<ul>
<li><strong>ter gente interna</strong> que treine pessoas em Svelte (mesmo que o treinamento seja ridiculamente curto);</li>
<li><strong>saber qual o preço de mercado</strong> de pessoas que trabalham com Svelte;</li>
<li><strong>aceitar que muito menos pessoas vão se candidatar</strong>, por mais que qualquer pessoa que saiba outros frameworks consiga trabalhar com Svelte em pouquíssimo tempo.</li>
</ul>
<p>na hora de vender um produto pra outras empresas, <strong>convencer a pessoa</strong> que tá te contratando que seu projeto vai ser mais estável e mais fácil de manter em longa data <strong>já é uma baita tarefa</strong>. isso se torna ainda mais difícil se essas pessoas não conseguirem reconhecer imediatamente a ferramenta principal que vai ser usada no projeto, sejam essas pessoas devs ou não. as chances de tomar uma decisão correta crescem muito se essa ferramenta que vai ser usada já for famosa.</p>
<blockquote>
<p>a verdade é que o caminho mais fácil não é o que as pessoas dev querem, ou o que é objetivamente melhor pro produto, mas o que as empresas já usam.</p>
</blockquote>
<h2 id="comprar-projetos-em-tecnologias-novas-é-um-risco"><a href="#comprar-projetos-em-tecnologias-novas-é-um-risco">comprar projetos em tecnologias "novas" é um risco</a></h2>
<p>acho que não preciso explicar muito sobre isso. React, por exemplo, é um projeto famoso desde 2013; o Angular, desde 2010. foram projetos extremamente inovadores, que mudaram o jeito com que a gente faz frontend. o futuro dessas ferramentas é visto como algo 100% garantido. algumas pessoas já chamam ferramentas como o React de "ferramentas de legado", que ficarão em bases de código por décadas.</p>
<p><strong>e isso é algo que o Svelte não é, e não vai ser tão cedo.</strong></p>
<p>não é um problema só de adoção, documentação ou ecossistema, mas de <strong>percepção de longo prazo</strong>. mesmo nós, que gostamos e acompanhamos o Svelte faz muito tempo, não temos certeza de até quando a Vercel vai ter dinheiro pra bancar o desenvolvimento do Svelte, e mesmo que a Vercel fosse uma empresa com uma marca mais forte, não temos como comparar ela com a Meta.</p>
<p>então na hora de comprar um projeto, o nome React tem peso.</p>
<h2 id="empresas-não-querem-investir-em-ferramentas-novas"><a href="#empresas-não-querem-investir-em-ferramentas-novas">empresas não querem investir em ferramentas "novas"</a></h2>
<p>é rara a liberdade das pessoas dev pra criar projetos nas tecnologias que elas querem dentro de empresas. mesmo quando, em raríssimas situações, as pessoas dev possam tomar de decisões de maior impacto, sempre há a necessidade de explicar os motivos da adoção de uma nova ferramenta pra quem é gerente, ou é da parte de negócios.</p>
<p>isso <strong>quando essa discussão pode acontecer</strong>, que também não é algo comum de acontecer.</p>
<p>para as empresas, <strong>minimizar riscos vem antes de investir em inovação</strong>. por isso, o tempo de estudo em uma ferramenta nova, mesmo que sejam poucas horas, significa "perder dinheiro" pro pessoal de negócio, principalmente quando React funciona, <strong>e funciona bem</strong>.</p>
<h2 id="então-o-que-podemos-fazer"><a href="#então-o-que-podemos-fazer">então o que podemos fazer?</a></h2>
<p>antes de tudo, precisamos continuar o trabalho que já fazemos: traduzir documentação, criar conteúdo, publicar ferramentas novas, etc. também acho óbvio dizer que, no caso do Brasil, <strong>nossa comunidade perdeu bastante força</strong>, e falta gente pra tomar a frente de fazer encontros online e conteúdos em língua brasileira (não foi um typo). sem esses fatores, fica muito difícil mudar a cabeça de empresas.</p>
<p>mas, <strong>na minha opinião</strong>, o mais importante é <strong>mostrar como é objetivamente melhor</strong> usar Svelte pras pessoas que trabalham com a gente. isso significa criar e compartilhar aquele projetinho de fim de semana com a galera, <a href="https://crieaporradeum.blog/">fazer um blog</a>, conversar com mais gente, tomar pra si a decisão de fazer um projeto interno da empresa usando Svelte.</p>
<p>e eu sei que nada disso é fácil de fazer. a gente já <strong>trabalha demais</strong>, toma <strong>risco demais</strong> de ser demitida, e, em grande parte, <strong>ganha pouco</strong> pro que a gente faz.</p>
<p>mas como em tudo na vida, <strong>a gente só ganha confiança</strong> e transparece essa confiança aos outros <strong>quando a gente sabe como e quando usar as ferramentas</strong> - suas aplicações, seus limites, seu produto final. sem essa confiança, a gente não convence nem nós mesmos de que dá pra usar Svelte em projetos grandes e corporativos.</p>
<p>pra fechar, deixo aqui o link pro <a href="https://github.com/lucianoratamero/ratamero-com">código do meu blog</a> e pras [minhas ferramentas de fazer live]. bora compartilhar algo em Svelte?</p>]]></description>
            <link>https://www.ratamero.com/blog/por-que-empresas-não-migram-pra-svelte</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/por-que-empresas-não-migram-pra-svelte</guid>
            <pubDate>Mon, 14 Apr 2025 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Showing a loading spinner when navigation is delayed in SvelteKit - Updated]]></title>
            <description><![CDATA[<blockquote>
<p>This is an update to my 2022 post about this issue.
Since we're now at the Svelte 5 era, stores are starting to be deprecated, so here's the update.</p>
</blockquote>
<p>Sometimes, when the internet connection is not ideal, <a href="/notes/SvelteKit">SvelteKit</a> apps might look like they froze when navigating to another page. This is how I solved this issue.</p>
<p><a href="/notes/SvelteKit">SvelteKit</a> provides <a href="https://svelte.dev/docs/kit/$app-state">a lot of useful state objects</a> that may give you a better insight on how the app is behaving. One of them is the <code>navigating</code> state. Whenever the client-side routing is transitioning between pages, this state is updated with the paths of where you're coming <code>from</code>, and where you're going <code>to</code> (and some other useful data):</p>
<pre><code class="hljs language-js">{
   <span class="hljs-attr">from</span>: <span class="hljs-string">"/"</span>
   <span class="hljs-attr">to</span>: <span class="hljs-string">"https://ratamero.com/blog"</span>
}
</code></pre>
<p>When it's not transitioning between pages, the <code>from</code> and <code>to</code> keys just return <code>null</code>. That allows us to add an <code>{#if}</code> block that renders a loading overlay is there's any value on the store:</p>
<pre><code class="hljs language-svelte"><span class="xml"><span class="hljs-tag">&#x3C;<span class="hljs-name">script</span>></span></span><span class="javascript">
  <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">import</span> { fade } <span class="hljs-keyword">from</span> <span class="hljs-string">"svelte/transition"</span>;
  <span class="hljs-keyword">import</span> { <span class="hljs-title class_">Circle3</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"svelte-loading-spinners"</span>;
  <span class="hljs-keyword">import</span> { navigating } <span class="hljs-keyword">from</span> <span class="hljs-string">"$app/state"</span>;
</span><span class="xml"><span class="hljs-tag">&#x3C;/<span class="hljs-name">script</span>></span>

</span><span class="hljs-comment">&#x3C;!-- ... --></span><span class="xml">

</span><span class="javascript">{</span><span class="hljs-keyword">#if</span><span class="javascript"> navigating.<span class="hljs-property">to</span>}</span><span class="xml">
<span class="hljs-tag">&#x3C;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fixed w-full h-full z-10"</span> <span class="hljs-attr">in:fade</span>=</span></span><span class="javascript">{{ <span class="hljs-attr">duration</span>: <span class="hljs-number">150</span> }}</span><span class="xml"><span class="hljs-tag">></span>
  <span class="hljs-tag">&#x3C;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute w-full h-full bg-white dark:bg-cyan-800 opacity-50 z-10"</span>></span><span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span>
  <span class="hljs-tag">&#x3C;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute w-full h-full flex justify-center items-center z-20"</span>></span>
    <span class="hljs-tag">&#x3C;<span class="hljs-name">Circle3</span> /></span>
  <span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span>
<span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span>
</span><span class="javascript">{</span><span class="hljs-keyword">/if</span><span class="javascript">}</span><span class="xml">
</span></code></pre>
<p>This implementation works fine, but there's a problem: since <a href="/notes/SvelteKit">SvelteKit</a> is <strong>really</strong> fast, the user may see flashes of the loading overlay when navigating, since there's simply no time for the user to recognize that the flash <em>is</em> the loading overlay.</p>
<p>To fix that, I added a <code>navigationIsDelayed</code> state to my base <code>+layout.svelte</code> that listens to the <code>navigating.to</code> state and only changes it's value to true when the navigation is hanged for more than 500ms:</p>
<pre><code class="hljs language-js"><span class="hljs-keyword">let</span> timer = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">let</span> navigationIsDelayed = $state(<span class="hljs-literal">false</span>);

$effect(<span class="hljs-function">() =></span> {
	<span class="hljs-keyword">if</span> (timer) {
		<span class="hljs-built_in">clearTimeout</span>(timer);
	}
	<span class="hljs-keyword">if</span> (navigating.<span class="hljs-property">to</span>) {
		timer = <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =></span> {
			navigationIsDelayed = <span class="hljs-literal">true</span>;
		}, <span class="hljs-number">500</span>);
	}
	navigationIsDelayed = <span class="hljs-literal">false</span>;

	<span class="hljs-keyword">return</span> <span class="hljs-function">() =></span> {
		<span class="hljs-keyword">if</span> (timer) {
			<span class="hljs-built_in">clearTimeout</span>(timer);
		}
	};
});
</code></pre>
<p>Notice the <code>timer</code> is a plain JS variable, since we <strong>don't</strong> want the effect to be triggered when <code>timer</code>'s value changes.</p>
<p>This way, the loading overlay only appears if the user's internet is <strong>so bad</strong> that can't load a couple of KBs in less than 500ms.</p>
<p>That's it for now! I hope this was useful to you, and see you next time :]</p>]]></description>
            <link>https://www.ratamero.com/blog/showing-a-loading-spinner-when-navigation-is-delayed-in-sveltekit-updated</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/showing-a-loading-spinner-when-navigation-is-delayed-in-sveltekit-updated</guid>
            <pubDate>Sat, 28 Dec 2024 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[impressões sobre a python brasil 2024]]></title>
            <description><![CDATA[<p>muita coisa aconteceu no evento desse ano. entre rever amigos e assistir a palestras, aprendi algumas coisas que quero compartilhar. :)</p>
<h2 id="ia-veio-pra-ficar"><a href="#ia-veio-pra-ficar">IA veio pra ficar</a></h2>
<p>pra felicidade de uns e chateação de outros (eu tô no segundo campo), IA teve um papel bem grande no evento. das 23 palestras, 6 tinham IA como tópico principal. até pra mim, uma pessoa que não gosta do assunto, algumas foram interessantes, como a de "IA Generativa no Combate à Desinformação" e a de Langflow; mas ficou o sentimento de que foi um pouco demais pra um mesmo assunto.</p>
<h2 id="diversidade-importa-cada-vez-mais"><a href="#diversidade-importa-cada-vez-mais">diversidade importa cada vez mais</a></h2>
<p>achei maravilhoso o quão diverso foi o público e as pessoas palestrantes. tivemos muitas, MUITAS palestras maravilhosas sobre isso, sob várias perspectivas: carreira (Sankofa: Educação em Tecnologia e Sonhos de Carreira), comunidade (Orumverso: Tecnologia Afrorreferenciada Na Prática) e inclusão (Inclusão e diversidade - do discurso para a realidade), dentre outras.</p>
<p>essa última foi a que me abriu mais os olhos, por abordar um assunto que eu praticamente nunca vejo abordado, que é o da neurodivergência. é impressionante pensar em como empresas geralmente não tem estrutura, tanto hierárquica quanto física, pra lidar com pessoas neurodivergentes. também foi interessante pensar em quanto o modelo 100% remoto remedia grande parte dos problemas presentes em empresas em geral.</p>
<h2 id="vinta-trazendo-sua-experiência-com-django-como-sempre"><a href="#vinta-trazendo-sua-experiência-com-django-como-sempre">vinta trazendo sua experiência com django, como sempre</a></h2>
<p>na questão técnica/web, a vinta sempre entrega bastante conteúdo bom, e não foi diferente dessa vez. a palestra do Bessa sobre django migrations foi muito rica, e trouxe pra mim duas ferramentas que vou ter que olhar mais a fundo: django-pg-zero-downtime-migrations e django-safemigrate.</p>
<h2 id="só-ter-uma-trilha-qualidade-vs-quantidade"><a href="#só-ter-uma-trilha-qualidade-vs-quantidade">só ter uma trilha: qualidade vs quantidade</a></h2>
<p>esse evento foi bem diferente dos outros em um aspecto: não tivemos múltiplas trilhas de palestras. isso teve uma série de repercussões; algumas positivas, muitas negativas (na minha opinião). sem dúvida, a qualidade das palestras foi altíssima, e o experimento de ter uma trilha só funcionou muito bem.</p>
<p>no entanto, menos trilhas significa menos espaço e menos gente participando. senti falta de ter palestras menores, com pessoas mais iniciantes, sobre assuntos de nicho. ter mais palestras menores incentiva quem tá entrando na comunidade, recompensando essa entrada com um palco.</p>
<p>também temos o problema de vivermos em um momento em que um assunto é dominante, como IAs. meu caso foi esse: eu não tenho nenhum interesse na área, e se um terço das palestras é sobre um assunto que você não tem interesse, não importa o quão alta é a qualidade do conteúdo.</p>
<p>apesar dessas opiniões, achei o experimento maravilhoso e super bem executado. o pessoal da organização mandou bem demais, e valeu muito a pena - mas definitivamente é outro tipo de evento.</p>
<h2 id="comunidade-comunidade-comunidade"><a href="#comunidade-comunidade-comunidade">comunidade, comunidade, comunidade</a></h2>
<p>uma coisa sempre é certa: a comunidade de python no brasil continua linda. pra ser sincero, não importa o formato do evento, ou o conteúdo ser útil ou não, eu sempre vou ter um grande motivo pra ir às pybrs, rever velhos amigos.</p>
<p>já comprei o ingresso pro ano que vem, que vai ser em São Paulo. vejo vocês lá!</p>]]></description>
            <link>https://www.ratamero.com/blog/impressoes-sobre-a-python-brasil-2024</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/impressoes-sobre-a-python-brasil-2024</guid>
            <pubDate>Wed, 23 Oct 2024 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[#ajudaLuciano - Como escrever posts de blog]]></title>
            <description><![CDATA[<blockquote>
<p>Esse post foi publicado originalmente em 2019. Não sou muito fã da maneira com que escrevi, então dei uma reeditada. No entanto, o conteúdo é bom e vai ser útil, então decidi repostar.</p>
</blockquote>
<p><strong>Escrever texto é muito difícil.</strong> Pra nós programadores, as coisas muitas vezes fazem total sentido dentro da nossa cabeça de uma maneira intuitiva. Mesmo assim, <strong>colocar as ideias no papel</strong> parece ser uma <strong>tarefa monumental</strong>. Nessas horas, ter me formado em jornalismo me ajuda muito - então vim aqui compartilhar com vocês algumas das coisas que me ajudam a escrever um post ou formatar uma palestra. Vamos lá!</p>
<h2 id="problemas-mais-comuns"><a href="#problemas-mais-comuns">Problemas mais comuns</a></h2>
<p>Quando eu converso com a galera da <a href="https://labcodes.com.br/">Labcodes</a>, eu noto que <strong>os problemas mais comuns</strong> são os seguintes:</p>
<ul>
<li>não saber <strong>qual</strong> assunto abordar;</li>
<li>não saber <strong>o que falar</strong> sobre dado assunto;</li>
<li>não conseguir <strong>encadear</strong> o conteúdo direitinho;</li>
<li>não saber <strong>como concluir ou resumir</strong> o texto.</li>
</ul>
<p>A questão é que jornalistas fazem isso <strong>o tempo todo</strong>; <em>até quando não devem</em>.</p>
<p></p>
<p><a href="https://www.terra.com.br/diversao/gente/caetano-veloso-passeia-pelo-leblon-e-estaciona-o-carro,e0d3399ae915a310VgnCLD200000bbcceb0aRCRD.html">A matéria jornalística que chocou o mundo</a></p>
<p>E se você tá se perguntando, <strong>sim</strong>, nós temos uma <strong>receitinha</strong> de como fazer essas <em>chocantes</em> matérias.</p>
<h3 id="ao-pensar-sobre-o-assunto-o-importante-é-o-público"><a href="#ao-pensar-sobre-o-assunto-o-importante-é-o-público">Ao pensar sobre o assunto, o importante é o público</a></h3>
<p>Quando você começa a pensar sobre um post/palestra, a primeira coisa que eu gosto de fazer é pensar em <strong>quem vai ler/assistir</strong> ao conteúdo. Esse post é pra prospectar <strong>clientes</strong>? Então de repente vale ter os <strong>valores</strong> do cliente na cabeça. É uma palestra pra <strong>iniciantes</strong>? Então vale deixar de lado os <strong>jargões</strong>.</p>
<p>Outro fator importante é ter em mente que um post é uma via de mão dupla. <strong>Você</strong>, autor, está contribuindo com algo que você <strong>pode dar</strong> (conteúdo, entretenimento) em <strong>troca</strong> pelo que a pessoa leitora pode dar: <strong>atenção</strong>.</p>
<blockquote>
<p>Manter essa troca de <strong>informação</strong> por <strong>atenção</strong> é essencial se você quer que as pessoas continuem lendo seu texto.</p>
</blockquote>
<p>Pra fechar essa parte, uma boa dica pra resolver sobre <strong>qual</strong> assunto abordar é pensar sobre <strong>o que te frustra</strong> diariamente como profissional. Os ModelSerializers do DRF te incomodam por serem acoplados demais? O docker é muito complicado de configurar? Então provavelmente esses são assuntos que poderiam interessar a <strong>outras pessoas</strong>. E com o assunto em mãos…</p>
<h3 id="tudo-começa-com-uma-frase"><a href="#tudo-começa-com-uma-frase">…tudo começa com uma frase</a></h3>
<p>A gente tem que começar de algum lugar, certo? Pessoalmente, acho a <strong>primeira frase</strong> muito importante. Ela delimita o <strong>tom</strong> do texto; e ela nem precisa dar informações sobre o assunto. Pode ser algo como:</p>
<ul>
<li><em>Fazer deploy é chato.</em></li>
<li><em>É 2019 e ainda tem muita gente que não usa grid nos layouts.</em></li>
<li><em>Essa é a história de como eu descobri o Flask.</em></li>
<li><em>Escrever texto é muito difícil.</em></li>
</ul>
<p>Pegando o exemplo do deploy, vemos que a primeira frase geralmente é o <strong>porquê</strong> de você estar escrevendo o texto. O que você quer com essa frase é <strong>dar contexto</strong> e <strong>se engajar</strong> com o leitor. Fale algo que faça a pessoa leitora pensar “<em>putz, é verdade, deploy é chato mesmo, quero ver que que essa pessoa vai falar</em>”.</p>
<p>E com o tom dado, a gente pode continuar o primeiro parágrafo com <strong>informações</strong> mais precisas sobre o tópico. Você poderia continuar, por exemplo, com “<em>Aqui na Labcodes, a gente resolveu esse problema com x, y, z de uma maneira bem elegante e simples</em>”. Algo que deixe <strong>claro</strong> sobre o que você vai falar, <strong>deixando os detalhes</strong> pro corpo do texto.</p>
<p>Pra concluir o primeiro parágrafo, é importante ter algo que <strong>ligue</strong> o que você <strong>disse</strong> com o que você <strong>vai falar</strong>. Ainda no caso do deploy, poderia ser algo como “<em>Mas as soluções que nós demos criaram um novo desafio: como vamos usar x, y, z nos nossos projetos legados?</em>” que deixaria a pessoa leitora <strong>pronta e interessada</strong> em ler a próxima parte do texto.</p>
<blockquote>
<p>A estrutura de <strong>contexto > informação > ligação</strong> é uma boa receita tanto pra começar quanto pra escrever todo o texto.</p>
</blockquote>
<p>E com o primeiro parágrafo rascunhado, as coisas ficam bem mais simples.</p>
<h3 id="escrevendo-o-corpo-do-texto"><a href="#escrevendo-o-corpo-do-texto">Escrevendo o corpo do texto</a></h3>
<p>Escrever o corpo do texto geralmente é mais fácil. Nesse ponto, você provavelmente já tem uma noção de quais tópicos abordar, e já dá pra montar qual parte vai ver depois da outra. Mesmo assim, é importante ter algumas coisas sempre em mente.</p>
<p>Lembra que eu falei pra ter em mente seu público ao escrever? No corpo do texto, isso é <strong>importante</strong> pra você saber como dosar partes de <strong>respiro</strong>. Essas partes geralmente são imagens, gifs, subtítulos ou frases de destaque.</p>
<blockquote>
<p>No corpo do texto, mais que nunca, a troca entre <strong>informação</strong> e <strong>atenção</strong> é essencial.</p>
</blockquote>
<p>Pra me manter focado, eu gosto de me dar um <strong>número de minutos</strong> pra <strong>escrever cada parágrafo</strong>. Isso me previne de ficar mexendo em coisa que já tá pronta enquanto eu podia estar pensando em outra coisa. Escrever é um processo <strong>cíclico</strong> (iterativo) e <strong>de descoberta</strong>, então é melhor você escrever muito e <strong>cortar</strong> o que é demais do que ficar polindo um parágrafo e nunca terminar o texto.</p>
<p>De resto, é repetir a estrutura de <em>contexto > informação > ligação</em> e escrever a conclusão.</p>
<h3 id="legal-mas-meu-problema-é-exatamente-concluir"><a href="#legal-mas-meu-problema-é-exatamente-concluir">Legal, mas meu problema é exatamente concluir!</a></h3>
<p>Relaxa, já chegamos no que te interessa então! Como sempre, tudo depende de <strong>quem</strong> vai estar lendo o texto e <strong>qual sentimento</strong> ou informação você quer que a pessoa <strong>saia dali sentindo</strong> ou sabendo. Pra facilitar, eu gosto de falar sobre três possíveis <strong>padrões</strong> de conclusão:</p>
<ul>
<li>revisão;</li>
<li>opinião;</li>
<li>referenciação.</li>
</ul>
<p><strong>Revisão</strong> é o mais autoexplicativo. Pense exatamente sobre o que a pessoa <strong>precisa sair do post sabendo</strong>, ou o que é mais difícil de entender, e escreva sobre. Um exemplo seria o seguinte:</p>
<p><em>“Vimos hoje que o Django Rest Framework tem muitos pontos de acoplamento, mas que com uma boa estrutura de código, podemos testar tudo sem abrir mão da documentação automática. Lembre-se de separar bem a lógica de negócio do framework e testar tudo direitinho. Nos vemos por aí, até a próxima!”</em></p>
<p><strong>Opinião</strong> é um pouquinho mais complicada. Se você está <strong>concluindo</strong> com uma opinião, é importante que <strong>todo seu texto</strong> tenha já expressado sua opinião, e que a conclusão seja só para que a pessoa saiba <strong>resumidamente qual opinião foi dita</strong>. Por exemplo:</p>
<p><em>“O Django Rest Framework deixa muito a desejar. Os ModelSerializers, além de lentos, geram um acoplamento muito grande entre os Models e a API. Pense bem se ele é a melhor opção antes de entrar de cabeça, e cuidado com os hacks. Nos vemos por aí, até a próxima!”</em></p>
<p>A forma mais popular de concluir, no entanto, é o <strong>referenciação</strong>. Basicamente, você deve falar sobre <strong>onde</strong> a pessoa pode adquirir <strong>mais informações</strong> sobre o assunto. Algo como:</p>
<p><em>“Caso queira saber mais sobre o Django Rest Framework, leia a documentação (link) e veja essa app Django que eu criei com os exemplos (link). Não tenha medo de comentar com as suas dúvidas, e se quiser dicas sobre casos específicos, falem comigo no telegram da Python Brasil. Nos vemos por aí, até a próxima!”</em></p>
<h3 id="epa-então-fechou-né"><a href="#epa-então-fechou-né">Epa, então fechou, né?</a></h3>
<p><strong>Pera</strong>, calma, tenho umas coisinhas pra falar ainda, mas é jogo rápido! Com o texto pronto, se dê um tempinho pra colocar em <strong>bold</strong> as palavras-chaves; isso ajuda <strong>muito</strong> quem tá lendo rápido ou relendo pra pegar referências.</p>
<p>E se você <strong>não tá se sentindo bem</strong> com alguma parte do texto, tente identificar <strong>qual frase</strong> ou qual termo tá te deixando desconfortável. Às vezes é uma palavra, às vezes é o fluxo da frase, mas muitas vezes é a ordem gramatical mesmo. <em>E eu não quero falar de gramática não.</em></p>
<h3 id="no-pior-dos-casos"><a href="#no-pior-dos-casos">No pior dos casos…</a></h3>
<p><strong>…comece do zero. Sério</strong>. Como tudo na vida, escrever bem é questão de prática. No começo, vai demorar muito e vai ser um processo chatinho, mas depois de você internalizar o processo, você vai conseguir criar em cima disso com uma certa facilidade.</p>
<p>E se teve algo que você queria que eu falasse sobre e eu não falei, pode me <a href="https://twitter.com/lucianoratamero">xingar no twitter</a>. Mentira, melhor que você me diga nos comentários mesmo, com calma, pra eu poder complementar depois. Valeu pela atenção, e nos vemos na próxima!</p>]]></description>
            <link>https://www.ratamero.com/blog/ajudaluciano-como-escrever-posts-de-blog</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/ajudaluciano-como-escrever-posts-de-blog</guid>
            <pubDate>Thu, 01 Dec 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Next.js vs SvelteKit: pros and cons]]></title>
            <description><![CDATA[<p><a href="/notes/SvelteKit">SvelteKit</a> has released their first release candidate for the 1.0 version last week, and this was the last push I needed to start playing with it again - but lately, for work, I've been really impressed with <a href="https://nextjs.org/">Next.js</a>. something in my svelty brain told me that I would like <a href="/notes/SvelteKit">SvelteKit</a> better, but whenever this kind of thought goes through my head, I try to force myself to evaluate the gut feeling properly, so I just recreated the same app on both frameworks. here are my thoughts on my experiences with them.</p>
<hr>
<h2 id="tldr"><a href="#tldr">tl;dr</a></h2>
<p>if you want a simple answer, I don't really have one. both of them are better for specific cases, and both are "good enough" for 99% of the scenarios.</p>
<p>that being said, my gut feeling was right, and I ended up liking the developer experience of <a href="/notes/SvelteKit">SvelteKit</a> better. it comes around to the features that I care about most, like simplicity, amount of code, and, well, using Svelte instead of React.</p>
<p>if you want to just look at the code, here are the repos. just be mindful that they are proof of concepts, so I bypassed most of the things I would do properly on a real app, like better error handling and a more intuitive UI.</p>
<ul>
<li><a href="https://github.com/lucianoratamero/sveltekit-todo">https://github.com/lucianoratamero/sveltekit-todo</a></li>
<li><a href="https://github.com/lucianoratamero/nextjs-todo">https://github.com/lucianoratamero/nextjs-todo</a></li>
</ul>
<p>there's a bit more nuance to it, so if you're interested on the details, here they come.</p>
<h2 id="the-project"><a href="#the-project">the project</a></h2>
<p>whenever I try to test a full-stack framework (which is the case for both of them), a CRUD scenario with small bits of interactivity is always a good proof of concept. to do that, I opted to use <a href="https://www.prisma.io">Prisma</a> to interact with a Postgres database (provided by <a href="https://supabase.com/">Supabase</a>, which was a great combo), and to make a simple 'todo' app, with editable and autosaving todos.</p>
<p>that meant that the user would have to be able to not only create the todos, but update them inline, and having them autosave whenever the user changes the todo in any way. this way, I could test the front-end features (sending data automatically to the backend, adding loading overlays, etc.), while experimenting with ways to interact with the data on the back-end.</p>
<p>I also used TypeScript for the <a href="https://nextjs.org/">Next.js</a> app, and TypeScript in comments (JSDoc) for the <a href="/notes/SvelteKit">SvelteKit</a> app, which are both recommended by their own stacks. both of them were deployed to Vercel.</p>
<h2 id="lessons-learned-from-nextjs"><a href="#lessons-learned-from-nextjs">lessons learned from Next.js</a></h2>
<p>as I expected, developing with Next.js was really straightforward. whenever you create an app, it comes with plenty of examples, so you don't really need to go to the docs as much; and when you do, the docs are great.</p>
<p>the way we deal with creating and updating data in a Next app is really close to what people are used to with React: get data from the form, send a fetch request to an API endpoint, update the UI with the new data, done.</p>
<p>creating the API endpoints was pretty easy, so I have absolutely nothing to complain about this topic. great job by the Next team.</p>
<p>there were a couple of problems that I needed to go through, though. for example, using TypeScript with React requires a bit of a learning curve, and the temptation to not type anything is pretty big. I already had a little of experience with it, so it wasn't that time consuming, but it's always, <strong>always</strong> frustrating to not get something done because of mismatching types that you know are compatible. Prisma helped me a lot on this front, since it autogenerates types for the database models.</p>
<p>another issue was, well, working with React again. I know, React pays my bills, but <a href="https://joshcollinsworth.comhttps://ratamero.com/blog/self-fulfilling-prophecy-of-react">there's not that much argument to keep using it</a>, since most frameworks, including Svelte, are way ahead of it in many aspects. I always feel that React requires more of my brain to work with, and that the cognitive load is always a bit bigger than it should.</p>
<p>I also couldn't make the forms work without javascript - at least not in an easy way. I'll talk more about it on the <a href="/notes/SvelteKit">SvelteKit</a> section.</p>
<p>some other small things that bugged me were not having Prettier installed by default, not having the possibility of having a test structure set up from the start, and having to force a page reload to update the content of the page in a little bit of a hacky way. nothing major, though.</p>
<p>but <a href="/notes/SvelteKit">SvelteKit</a>... <em>oh, man</em>, I <strong>loved</strong> working with <a href="/notes/SvelteKit">SvelteKit</a>.</p>
<h2 id="lessons-learned-from-sveltekit"><a href="#lessons-learned-from-sveltekit">lessons learned from SvelteKit</a></h2>
<p>first of all, most of the good things from Next were found in SvelteKit as well, like file-based routing and architecture in general. but I think it's safe to say most of the good parts were even better here.</p>
<p>for example, when creating a <a href="/notes/SvelteKit">SvelteKit</a> app, the CLI asks me a few questions that helped me a lot from the get-go. not having to set up Prettier and Playwright helps <strong>a lot</strong> when you're starting a project.</p>
<p></p>
<p>I also felt like I was just writing HTML with sprinkled bits of JS instead of JS everywhere, and that's an easy win provided by Svelte, the whole "use the platform" thing. I wrote the forms like real forms, I dealt with native Request and Response objects instead of something custom, and that even helped me learn a bit on how HTML forms work.</p>
<p>another thing that caught my eye was that it was really easy to make the forms work without JS, since <a href="/notes/SvelteKit">SvelteKit</a> comes with the <a href="https://kit.svelte.dev/docs/form-actions#progressive-enhancement-use-enhance"><code>use:enhance</code></a> action. just by adding <code>use:enhance</code> to the form tag (and, in my case, adding a callback to turn the loading overlay on and off), <a href="/notes/SvelteKit">SvelteKit</a> is able to provide an app-like experience to a normal HTML form, not needing a full page reload.</p>
<p>there's also the <a href="https://kit.svelte.dev/docs/form-actions">form actions</a> feature, that allowed me to not need to write API endpoints, giving me a simpler way to deal with forms. in summary, the whole CRUD experience was simpler and required less code. it did take me a one-time while to learn how to make them, though, since they're specific to SvelteKit.</p>
<p>there were other small improvements as well, like autogenerated types for server to client page data, faster build times (like 3x faster), smaller bundles (70k vs 280kb), and slightly lower layout shifts.</p>
<p>it wasn't all good, though. Intellij users, like myself, have to deal with a worse developer experience when writing typed code, because JetBrains hasn't made much effort to make the Svelte plugin as good as the one for VS Code (so I just used VS Code instead). also, <a href="/notes/SvelteKit">SvelteKit</a> is clearly the less stable and debuggable of them both, since Next is a way more mature and battle-tested platform. it's also missing some of the key features from Next, like <a href="https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration">Incremental Static Regeneration</a>, making <a href="/notes/SvelteKit">SvelteKit</a> not proper for all types of apps.</p>
<h2 id="conclusion"><a href="#conclusion">conclusion</a></h2>
<p>as I always say, when making the decision to use one vs the other, everything depends on everything. they are clearly better for different use cases. but if you asked me which one I liked more, I can't stress <strong>how much</strong> I enjoyed developing this app with <a href="/notes/SvelteKit">SvelteKit</a>. it took me a little bit to understand some of the naming conventions and the design decisions, but when I did, everything just clicked - and it didn't take more than a few hours to understand the differences.</p>
<p>I also really, <strong>really</strong> enjoyed using Prisma as a database ORM with Supabase. the experience was so good that now I'm seriously considering leaving Django behind and just using SvelteKit + Prisma for full stack apps. I can make another blog post about it, if people want me to.</p>
<p>I'll leave you with my pros and cons for each framework, and if you have anything to ask or add, be free to use the comments :]</p>
<h2 id="pros-and-cons"><a href="#pros-and-cons">pros and cons</a></h2>
<h3 id="nextjs"><a href="#nextjs">Next.JS</a></h3>
<h4 id="pros"><a href="#pros">pros</a></h4>
<ul>
<li>really easy to get started</li>
<li>familiar to those that are used to the React way</li>
<li>great docs</li>
</ul>
<h4 id="cons"><a href="#cons">cons</a></h4>
<ul>
<li>react's DX is seriously lacking in comparison with svelte</li>
<li>typescript on react is a bit hard to understand sometimes. prisma helped a lot with their autogenerated types for models</li>
<li>didn't come with prettier installed out of the box (personal preference)</li>
<li>still needs js to create/update data (or, in other words, it's not easy to do so)</li>
<li>bigger bundles and slower build times</li>
</ul>
<h3 id="sveltekit"><a href="#sveltekit">SvelteKit</a></h3>
<h4 id="pros-1"><a href="#pros-1">pros</a></h4>
<ul>
<li>the cli to create the project is great</li>
<li>closer to "the platform" - I ended up learning a lot about how forms work</li>
<li>form actions take a bit of time to properly understand, but when you do, they're awesome</li>
<li>progressively enhanced forms means my forms will still work if js fails or is blocked</li>
<li>svelte improvements: less code, less cognitive load</li>
<li>significantly faster builds and smaller bundles</li>
</ul>
<h4 id="cons-1"><a href="#cons-1">cons</a></h4>
<ul>
<li>bad integration with my preferred IDE (intellij idea)</li>
<li>missing big features such as incremental static regeneration</li>
<li>a little bit harder to debug when things go wrong, mainly on the back-end</li>
</ul>]]></description>
            <link>https://www.ratamero.com/blog/nextjs-vs-sveltekit-pros-and-cons</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/nextjs-vs-sveltekit-pros-and-cons</guid>
            <pubDate>Sun, 11 Sep 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[First impressions of Elixir]]></title>
            <description><![CDATA[<p>I remember being in a <a href="/notes/Python-Brasil">Python Brasil</a> (I think it was in Belo Horizonte), on a bar after the talks of the day were done, talking with some friends, when one of the people around said wonders about Erlang and <a href="/notes/Elixir">Elixir</a>. I also remember trying it later that year, and getting completely confused about a lot of topics.  thinking about back then, I think I wasn't ready as a programmer to learn it in a meaningful way. this last week, I came back to Elixir, and I'm loving every second with it. here are my first impressions.</p>
<hr>
<h2 id="getting-started"><a href="#getting-started">getting started</a></h2>
<p>when I'm trying out a new language, there are a few pain points that make me lose my interest fast. they are mostly:</p>
<ul>
<li>difficulty on starting a project: I'm way too spoiled with <a href="/notes/Python">Python</a> and <a href="/notes/JavaScript">JavaScript</a>, so if installing the language tools, configuring the IDE, and writing and executing code demands a manual, I won't do it;</li>
<li>weird syntax: to me, programming should be democratic, should be readable. of course, every language will introduce new things, and, for that, new syntax needs to be introduced - but if your programming language is not easy to intuitively understand, or the balance between readability and features is too big, that turns me off. currently, my limit would be something like Rust, which is hard to understand, but extremely powerful;</li>
<li>weak standard library and bad dependency/module management: in my opinion, if the language has a bad or problematic standard library (hello JS!), or if the tools for dependency/module management are complicated (hello Go!), I'll struggle <strong>a lot</strong>;</li>
<li>bad documentation: well, I don't think I need to explain this one;</li>
<li>too many hoops needed for me to test my code: when I play with a language, I <strong>need</strong> to get confident with it, and one of the ways to be confident is to have a simple way to create and run tests. I don't really mind having to install separate tools to test my code, but it has to be simple.</li>
</ul>
<p>I'll go topic by topic in the next sections.</p>
<h2 id="starting-an-elixir-project"><a href="#starting-an-elixir-project">starting an Elixir project</a></h2>
<p>to start a project, you need to install Elixir (it was one command), then run <code>mix new</code>. that's it. configuring the IDE was as straightforward as with other languages: install the plugin, set up which version I was using, and that was it as well, it all worked on the first try.</p>
<p>writing new code was easy (I'll talk about the syntax next) and running it was a breeze. even the interactive shell (<code>iex</code>) was easy to use, and together with <code>mix</code> (which comes with the language), I was recompiling and executing code in minutes.</p>
<h2 id="elixirs-syntax"><a href="#elixirs-syntax">Elixir's syntax</a></h2>
<p>the first thing to note here is the elephant in the room: Elixir is a language based on functional programming. somehow, inside my head, functional programming made a lot of sense, but came with a huge syntax cost. I had played with Elm and even a bit of Haskell before (not that I remember anything about them), and both of them left me a bad impression. for the old me, the syntax you needed to learn was far too abstracted from what the code was doing, while being far too powerful to ignore.</p>
<p>so when I started playing with Elixir last week, I came prepared, clad in armor, ready to dig in and get my hands dirty.</p>
<p>but the confusion and the weird syntax never came. in fact, <strong>I didn't remember how close to Ruby the language feels</strong>; at least at first. I felt like I was just playing around with functions, and that was <strong>exactly</strong> what I was doing - without fear, without any of the hardships I was expecting.</p>
<p>that left me open to appreciate some of the amazing features Elixir has - and I don't use the word amazing lightly.</p>
<p>here's a sample of Elixir's syntax. tell me if it's hard to understand:</p>
<pre><code class="hljs language-elixir">defmodule Cards do
  def create_deck do
    values = ["Ace", "Two", "Three", "Four", "Five"]
    suits = ["Clubs", "Spades", "Hearts", "Diamonds"]

    for suit &#x3C;- suits, value &#x3C;- values do
      "#{value} of #{suit}"
    end
  end
</code></pre>
<h2 id="standard-library-and-dependency-management"><a href="#standard-library-and-dependency-management">standard library and dependency management</a></h2>
<p>Elixir's standard library, at least as far as I've gone, is no more than expected for a functional language. the <code>Enum</code> module has everything you need to deal with lists, and if you know the basic types and knows how to deal with lists, you're mostly set.</p>
<p>installing new dependencies with <code>hex</code> was pretty easy too. not as easy as on JS (<code>npm install packagename</code>) or with Python + Poetry (<code>poetry add packagename</code>), but still easy enough. you just need to run <code>mix hex.info packagename</code>, copy the package info into your <code>mix.exs</code> file and install it with <code>mix deps.get</code>. pretty straightforward, so no complaints here.</p>
<h2 id="documentation-oh-beautiful-documentation"><a href="#documentation-oh-beautiful-documentation">documentation, oh, beautiful documentation</a></h2>
<p>not only Elixir's documentation is plentiful, but it's also easily searchable and literally built into the language. it was really easy to find what I needed with a couple of web searches, and, together with the IDE's autocomplete, it was a bit rare to really <strong>need</strong> to search for it.</p>
<p>if, for example, you want to understand how the <code>Enum</code> module works, you just need to go into the interactive shell by running <code>iex</code>, then type <code>h Enum</code>. that gives you all you need to know about the module right from the command line. the same goes for module functions. for example, <code>h Enum.split</code> returns you this:</p>
<p></p>
<h2 id="testing-elixir-code"><a href="#testing-elixir-code">testing Elixir code</a></h2>
<p>whenever you start a new project or module, it automatically creates a test file for it. not only that, but it also has all the basic tools to test your code built-in. I just needed to run <code>mix test</code> and the test was running.</p>
<p>that would be enough for me to give it more than a passing grade, but there was one more thing that caught my eye, and that's insanely useful: Doctests.</p>
<p>when you're writing your Elixir code, as with any other language, it's encouraged to write documentation for your functions. here's what it looks like:</p>
<pre><code class="hljs language-elixir">defmodule Cards do
  def create_deck do
    values = ["Ace", "Two", "Three", "Four", "Five"]
    suits = ["Clubs", "Spades", "Hearts", "Diamonds"]

    for suit &#x3C;- suits, value &#x3C;- values do
      "#{value} of #{suit}"
    end
  end

  @doc """
    Deals cards to a hand, returning the hand and the deck's remaining cards.
    The `number_of_cards` argument relates to the size of the hand dealt.

  ## Examples
      iex> {hand, _deck} = Cards.create_deck |> Cards.deal(1)
      iex> hand
      ["Ace of Clubs"]
  """
  def deal(deck, number_of_cards) do
    Enum.split(deck, number_of_cards)
  end
end

</code></pre>
<p>do you see the <code>Examples</code> section above the <code>deal</code> function? cool, right? it's always nice to add examples on how the code works, right? what if I told you that <em>the example you see there is already a test</em>? because it is. if you open the test file, you'll see this:</p>
<pre><code class="hljs language-elixir">defmodule CardsTest do
  use ExUnit.Case
  doctest Cards
end
</code></pre>
<p>the <code>doctest</code> line signals to the testing framework that you want to use the examples inside of the documentation as tests, and it's generated by default. so if I run <code>mix test</code>, I'll see this:</p>
<p></p>
<p>that not only gives you a free test for your code, but it also encourages you to write the docs and to keep them updated. this is the first time I've seen such a feature on any stack, and for that to be built into the language is awesome!</p>
<p>btw, you can also generate a full fledged static site from your code documentation too with <a href="https://github.com/elixir-lang/ex_doc">ex_doc</a>. just install it and run <code>mix docs</code> and it's done.</p>
<h2 id="so-yeah-i-really-like-it"><a href="#so-yeah-i-really-like-it">so yeah, I really like it</a></h2>
<p>I'll keep on learning and trying to document some of the cool and bad things here on the blog. I've not been this interested in learning a new programming language in ages, so I'll be completely honest with my findings. my goal is to properly understand what I'm doing when I get to a <a href="/notes/Phoenix">Phoenix</a> app, but that will probably take a while.</p>
<p>any thoughts or questions? leave a comment! and, as always, thanks for your attention :]</p>]]></description>
            <link>https://www.ratamero.com/blog/first-impressions-of-Elixir</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/first-impressions-of-Elixir</guid>
            <pubDate>Sun, 21 Aug 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Reading MP3 metadata with Python]]></title>
            <description><![CDATA[<p>Music is one of my real passions. If I'm not listening to something, I'm probably singing something to myself all the time. But for the longest time, I never had the time (or money) to have a better listening experience. Since I'm at home, and the pandemic is not over, I decided to understand a little bit better what (and how) I'm listening to music - with Python :]</p>
<h2 id="quick-summary-on-how-i-listen-to-music"><a href="#quick-summary-on-how-i-listen-to-music">Quick summary on how I listen to music</a></h2>
<p>So, as millenials do, I have grown listening to cassette tapes, CDs, and eventually MP3s. I remember being 15, using a huge ass pair of headphones (real cheap ones too) with my 128MB MP3 player - and it was <strong>awesome</strong>.</p>
<p>With time, I grew my MP3 collection, both through good channels (like bandcamp for example), and less... legal channels (like Napster, Kazaa, and Souseek, whic I still use now and then). I can't say my library is big, but it's around 4200 musics in size.</p>
<p>The problem is that a good chunk of it is garbage; not in quality of the music itself, but in the quality of the <em>file compression</em>. And now that I have the money to get some better headphones, some of my music library is just <strong>too dank</strong>.</p>
<p>As with anything, Python can help me.</p>
<h2 id="enter-mutagen"><a href="#enter-mutagen">Enter <code>mutagen</code></a></h2>
<p><a href="https://mutagen.readthedocs.io/en/latest/"><code>mutagen</code></a> is a Python library that helps us to find metadata for our audio files. After discovering it, discovering which MP3 files were too compressed was pretty straightforward.</p>
<p>First, I installed it locally (in my case, it was already installed somehow. I probably fiddled around with it in a distant past):</p>
<pre><code class="hljs language-sh">pip3 install --user mutagen
</code></pre>
<p>Then, I wrote a quick <em>and really dirty</em> Python script to tell me which of my MP3 had a bitrate lower than 256kbps. The higher the bitrate, the less it's compressed:</p>
<pre><code class="hljs language-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> mutagen


<span class="hljs-keyword">def</span> <span class="hljs-title function_">list_dank_mp3s</span>(<span class="hljs-params">folder</span>):
    matches = []
    <span class="hljs-keyword">for</span> root, dirnames, filenames <span class="hljs-keyword">in</span> os.walk(folder):
        <span class="hljs-keyword">for</span> filename <span class="hljs-keyword">in</span> filenames:
            <span class="hljs-keyword">if</span> filename.endswith(<span class="hljs-string">".mp3"</span>):
                <span class="hljs-comment"># I didn't take the time to understand </span>
                <span class="hljs-comment"># why it was formatting things wrong</span>
                <span class="hljs-comment"># so I just hammered the names</span>
                matches.append(os.path.join(root, filename)[:-<span class="hljs-number">1</span>] + <span class="hljs-string">"3\n"</span>)

    bad_mp3s = []
    <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> matches:
        <span class="hljs-comment"># here, we get the bitrateof the MP3 file</span>
        <span class="hljs-comment"># there are a LOT of other metadata there,</span>
        <span class="hljs-comment"># if you want to use it</span>
        bitrate = mutagen.File(item.strip()).info.bitrate
        <span class="hljs-comment"># if the bitrate doesn't end with 000, it means it's most likely variable</span>
        <span class="hljs-comment"># if it is, we leave it be. if not, we check if it's below 256kbps</span>
        <span class="hljs-keyword">if</span> <span class="hljs-built_in">str</span>(bitrate).endswith(<span class="hljs-string">"000"</span>) <span class="hljs-keyword">and</span> bitrate / <span class="hljs-number">1000</span> &#x3C; <span class="hljs-number">256</span>:
            bad_mp3s.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), item))
    <span class="hljs-keyword">return</span> bad_mp3s
</code></pre>
<p>This function gives me a list, that has the paths of the MP3s that I may want to buy or redownload in a better bitrate. I then write the list to a file, and <em>voilà</em>, all my bad sounding MP3s are listed.</p>
<hr>
<p>Do you have any other uses for this kind of library? Do you have any tips on good headphones? Send me a comment down here so we can keep the discussion going! Thanks for your attention, and see you next time :]</p>]]></description>
            <link>https://www.ratamero.com/blog/reading-mp3-metadata-with-python</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/reading-mp3-metadata-with-python</guid>
            <pubDate>Mon, 18 Apr 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Showing a loading spinner when navigation is delayed in SvelteKit]]></title>
            <description><![CDATA[<p>Sometimes, when the internet connection is not ideal, <a href="/notes/SvelteKit">SvelteKit</a> apps might look like they froze when navigating to another page. This is how I solved this issue.</p>
<p><a href="/notes/SvelteKit">SvelteKit</a> provides <a href="https://kit.svelte.dev/docs/modules#$app-stores">a lot of useful stores</a> that may give you a better insight on how the app is behaving. One of them is the <code>navigating</code> store. Whenever the client-side routing is transitioning between pages, this store is updated with an object that contains the paths of where you're coming <code>from</code>, and where you're going <code>to</code>:</p>
<pre><code class="hljs language-js">{
   <span class="hljs-attr">from</span>: <span class="hljs-string">"/"</span>
   <span class="hljs-attr">to</span>: <span class="hljs-string">"https://ratamero.com/blog"</span>
}
</code></pre>
<p>When it's not transitioning between pages, it just returns <code>null</code>. That allows us to add an <code>{#if}</code> block that renders a loading overlay is there's any value on the store:</p>
<pre><code class="hljs language-svelte"><span class="xml"><span class="hljs-tag">&#x3C;<span class="hljs-name">script</span>></span></span><span class="javascript">
  <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">import</span> { fade } <span class="hljs-keyword">from</span> <span class="hljs-string">"svelte/transition"</span>;
  <span class="hljs-keyword">import</span> { <span class="hljs-title class_">Circle3</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"svelte-loading-spinners"</span>;
  <span class="hljs-keyword">import</span> { navigating } <span class="hljs-keyword">from</span> <span class="hljs-string">"$app/stores"</span>;
</span><span class="xml"><span class="hljs-tag">&#x3C;/<span class="hljs-name">script</span>></span>

</span><span class="hljs-comment">&#x3C;!-- ... --></span><span class="xml">

</span><span class="javascript">{</span><span class="hljs-keyword">#if</span><span class="javascript"> <span class="hljs-title class_">Boolean</span>($navigating)}</span><span class="xml">
<span class="hljs-tag">&#x3C;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fixed w-full h-full z-10"</span> <span class="hljs-attr">in:fade</span>=</span></span><span class="javascript">{{ <span class="hljs-attr">duration</span>: <span class="hljs-number">150</span> }}</span><span class="xml"><span class="hljs-tag">></span>
  <span class="hljs-tag">&#x3C;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute w-full h-full bg-white dark:bg-cyan-800 opacity-50 z-10"</span>></span><span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span>
  <span class="hljs-tag">&#x3C;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute w-full h-full flex justify-center items-center z-20"</span>></span>
    <span class="hljs-tag">&#x3C;<span class="hljs-name">Circle3</span> /></span>
  <span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span>
<span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span>
</span><span class="javascript">{</span><span class="hljs-keyword">/if</span><span class="javascript">}</span><span class="xml">
</span></code></pre>
<p>This implementation works fine, but there's a problem: since <a href="/notes/SvelteKit">SvelteKit</a> is <strong>really</strong> fast, the user may see flashes of the loading overlay when navigating, since there's simply no time for the user to recognize that the flash <em>is</em> the loading overlay.</p>
<p>To fix that, I created a <code>navigationIsDelayed</code> store that listens to the <code>navigating</code> store and only changes it's value to true when the navigation is hanged for more than 500ms:</p>
<pre><code class="hljs language-js"><span class="hljs-keyword">import</span> { derived } <span class="hljs-keyword">from</span> <span class="hljs-string">"svelte/store"</span>;
<span class="hljs-keyword">import</span> { navigating } <span class="hljs-keyword">from</span> <span class="hljs-string">"$app/stores"</span>;

<span class="hljs-keyword">let</span> timer = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> navigationIsDelayed = <span class="hljs-title function_">derived</span>(navigating, <span class="hljs-function">(<span class="hljs-params">newValue, set</span>) =></span> {
  <span class="hljs-keyword">if</span> (timer) { <span class="hljs-built_in">clearTimeout</span>(timer); }
  <span class="hljs-keyword">if</span> (newValue) {
    timer = <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =></span> <span class="hljs-title function_">set</span>(<span class="hljs-literal">true</span>), <span class="hljs-number">500</span>);
  }
  <span class="hljs-title function_">set</span>(<span class="hljs-literal">false</span>);
});
</code></pre>
<p>Then updated my <code>__layout.svelte</code> using the new store:</p>
<pre><code class="hljs language-svelte"><span class="xml"><span class="hljs-tag">&#x3C;<span class="hljs-name">script</span>></span></span><span class="javascript">
  <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">import</span> { fade } <span class="hljs-keyword">from</span> <span class="hljs-string">"svelte/transition"</span>;
  <span class="hljs-keyword">import</span> { <span class="hljs-title class_">Circle3</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"svelte-loading-spinners"</span>;
  <span class="hljs-keyword">import</span> { navigationIsDelayed } <span class="hljs-keyword">from</span> <span class="hljs-string">"$lib/stores.js"</span>;
</span><span class="xml"><span class="hljs-tag">&#x3C;/<span class="hljs-name">script</span>></span>

</span><span class="hljs-comment">&#x3C;!-- ... --></span><span class="xml">

</span><span class="javascript">{</span><span class="hljs-keyword">#if</span><span class="javascript"> $navigationIsDelayed}</span><span class="xml">
  <span class="hljs-tag">&#x3C;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fixed w-full h-full z-10"</span> <span class="hljs-attr">in:fade</span>=</span></span><span class="javascript">{{ <span class="hljs-attr">duration</span>: <span class="hljs-number">150</span> }}</span><span class="xml"><span class="hljs-tag">></span>
    <span class="hljs-tag">&#x3C;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute w-full h-full bg-white dark:bg-cyan-800 opacity-50 z-10"</span>></span><span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span>
    <span class="hljs-tag">&#x3C;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"absolute w-full h-full flex justify-center items-center z-20"</span>></span>
      <span class="hljs-tag">&#x3C;<span class="hljs-name">Circle3</span> /></span>
    <span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span>
  <span class="hljs-tag">&#x3C;/<span class="hljs-name">div</span>></span>
</span><span class="javascript">{</span><span class="hljs-keyword">/if</span><span class="javascript">}</span><span class="xml">

</span></code></pre>
<p>This way, the loading overlay only appears if the user's internet is <strong>so bad</strong> that can't load a couple of kbs in less than 500ms.</p>
<p>That's it for now! I hope this was useful to you, and see you next time :]</p>]]></description>
            <link>https://www.ratamero.com/blog/showing-a-loading-spinner-when-navigation-is-delayed-in-sveltekit</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/showing-a-loading-spinner-when-navigation-is-delayed-in-sveltekit</guid>
            <pubDate>Sun, 03 Apr 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[This post was written in Obsidian]]></title>
            <description><![CDATA[<p>For the last three years, I was not satisfied with my process of writing blog posts. It was too artisanal, so I always found something less boring to do. Here's how it all changed with my two new favorite tools: <a href="/notes/SvelteKit">SvelteKit</a> and <a href="/notes/Obsidian">Obsidian</a>.</p>
<blockquote>
<p>Every time you see a link, I encourage you to take a look. Most of them are not direct external links, but notes I've made about that topic. Some of the information there can complement what you're reading right now :]</p>
</blockquote>
<h2 id="how-it-was"><a href="#how-it-was">How it was</a></h2>
<p>My previous site, while entirely made by me and very customized, was not 100% easy to maintain. It already used <a href="/notes/SvelteKit">SvelteKit</a>, but in a very, <em>very</em> dumb way. The thing is: I wanted to keep old posts alive, and they were converted to plain HTML, which was served by <a href="/notes/SvelteKit">SvelteKit</a>, and that was that.</p>
<p>That meant that every time I wanted to write something new, I needed to write it in HTML. It's not entirely bad, and allowed me to do some fancy stuff, but it was <strong>impractical</strong>, to say the least. Because of that, I never posted anything anymore, and didn't want to migrate to something else, since that meant migrating lots of posts from HTML to something like <a href="/notes/Markdown">Markdown</a>.</p>
<h2 id="how-it-changed"><a href="#how-it-changed">How it changed</a></h2>
<p>It all changed when I discovered <a href="/notes/Obsidian">Obsidian</a>. If you want to know more about my feelings about it, take a look at the <a href="/notes/a-week-with-obsidian">A week with Obsidian</a> post. But what really enticed me to make a blog based on it were two details: it's really easy to write notes on it (like most <a href="/notes/Markdown">Markdown</a>-based editors), and that the notes link to each other easily. That blew my mind a little bit, since it meant I could write things fast and give more context through links.</p>
<h2 id="how-it-is"><a href="#how-it-is">How it is</a></h2>
<p>Now, while I still use <a href="/notes/SvelteKit">SvelteKit</a> for the ease of use and the performance, I decided to go with a mix between two SvelteKit templates: <a href="https://github.com/sw-yx/swyxkit">SwyxKit</a> and <a href="https://github.com/svelteland/svelte-kit-blog-demo">Svelteland's Markdown Blog Demo</a>. SwyxKit gave me the basic infrastructure and sane visual defaults, while the Markdown Blog Demo gave me the piping necessary to write in Markdown and output HTML.</p>
<p>So I write everything in <a href="/notes/Obsidian">Obsidian</a>, which makes notes in Markdown, and my <em>SwyxKit Markdown Frankenstein's monster</em> publishes it as HTML. The problem then was moving what was inside of the Obsidian vault to the folder my site expected the posts to be.</p>
<p>To solve that, I used this byotiful python library called <a href="https://obsidian-html.github.io/">obsidianhtml</a>. It's mostly used to generate static sites from an Obsidian vault, but it's flexible enough to do strictly what I want it to: to capture internal links between the notes and substitute them with real links, and output the Markdown files to the blog posts folder of my site. <a href="/notes/obsidianhtml-configs-and-script">I've made a custom shellscript function to do that for me</a>.</p>
<h2 id="the-end-result"><a href="#the-end-result">The end result</a></h2>
<p>Now, I can simply open Obsidian, write what I want to write (links, images and all), run a command to export the <a href="/notes/Markdown">Markdown</a> files to the site's source code, check that it's working on the site locally, and push the code. Oh, and I've been using <a href="https://vercel.com">Vercel</a> as the hosting/publishing solution (and it's been awesome so far), since it takes care of building the app and publishing the new version.</p>
<p>Be free to take a look at <a href="https://github.com/lucianoratamero/swyxkit-blog/">the site's source code</a> and give me feedbacks and suggestions on <a href="https://twitter.com/lucianoratamero">Twitter</a>! Thanks for your attention, and see you next time :]</p>]]></description>
            <link>https://www.ratamero.com/blog/this-post-was-written-in-obsidian</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/this-post-was-written-in-obsidian</guid>
            <pubDate>Sun, 03 Apr 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[My favorite obsidian plugins]]></title>
            <description><![CDATA[<p>Obsidian alone is already a pretty nice tool to help us figure out the mess that's inside of our heads, but I wouldn't be a software developer without overcomplicating things - so here's my list of my favorite plugins.</p>
<p>Since some of these are community plugins, to use them, you need to know <a href="https://help.obsidian.md/Advanced+topics/Community+plugins#Safe+Mode">how to turn on community plugins</a>.</p>
<h2 id="periodic-notes--calendar"><a href="#periodic-notes--calendar">Periodic notes + Calendar</a></h2>
<p>Ok, these are two different plugins, but they help each other a lot. The Periodic Notes plugin helps us organize... well, periodic notes. For example, I use it to create (almost) daily notes about what I've done, how I'm feeling, things people did that are worthy of note, etc. It keeps the notes organized.</p>
<p>With Calendar, though, it shines ✨ Calendar gives me a visualization on which days I've made notes, how much did I write on that day, and, if you click any day, it creates the note for that day using Periodic Notes' configs, so they're put at the right folder, with the right name.</p>
<p>
For example, I wrote <strong>too much</strong> on the 21st, since it has two dots below the day number. I love it.</p>
<h2 id="templater"><a href="#templater">Templater</a></h2>
<p><em>Not to be mixed up with Templates, which is a core plugin.</em></p>
<p>Templater gives people with a little bit of development experience (or a lot of patience) some superpowers for creating new notes. For example, I have a <code>blog post</code> template that puts all needed metadata in a Frontmatter block:</p>
<p>
With this template, all dates are correctly set, and, as long as create the note with a title <code>hyphenated-like-this</code>, the post title will be <code>Capitalized like this</code>. Saves a lot of time for recurrent notes at work too.</p>
<h2 id="kanban"><a href="#kanban">Kanban</a></h2>
<p><em>Because I'm an Agile software development lapdog.</em></p>
<p>Kanban gives you a kanban board inside of a <a href="/notes/Markdown">Markdown</a> file. Really useful for tracking down to-dos, be them work or life related.</p>
<p>
While it shows you and interacts like a Kanban board (you can drag things around, archive cards, etc.), it's still a <a href="/notes/Markdown">Markdown</a> file under the hood, so yeah 👍</p>
<h2 id="various-complements"><a href="#various-complements">Various Complements</a></h2>
<p>This plugin gives you a better autocomplete, almost IDE-like. Not much to say here, it's just <strong>better</strong>.</p>
<h2 id="slides--fullscreen-mode-plugin"><a href="#slides--fullscreen-mode-plugin">Slides + Fullscreen mode plugin</a></h2>
<p>Obsidian comes with a pretty handy feature: you can make a presentation with multiple slides just by writing sections in a <a href="/notes/Markdown">Markdown</a> file separated by a <code>---</code> line. With the note done, you just need to press <code>Ctrl+P</code>, search for <code>Start presentation</code> and you'll have it on your screen. Sometimes it's a little buggy when the presentation starts, so I just go to the second slide and back, and it fixed itself.</p>
<p>
It only has <em>one small issue</em>: it's not fullscreen. You can't see it in the gif above, but my OS's top bar is still appearing for people that see me sharing my screen, for example. That's where the Fullscreen mode plugin comes in. I just need to enable focus mode (<code>Ctrl+P</code> is your friend here as well), and then start the presentation. Done.</p>
<h2 id="emoji-shortcodes"><a href="#emoji-shortcodes">Emoji shortcodes</a></h2>
<p>👍💖</p>
<h2 id="thats-it-for-now"><a href="#thats-it-for-now">That's it for now!</a></h2>
<p>Those are the plugins that I've been enjoying as of late. If you have any other that you like, or want more information on any of them, ping me on <a href="https://twitter.com/lucianoratamero">Twitter</a>! Thanks, and see you next time! ✨</p>]]></description>
            <link>https://www.ratamero.com/blog/my-favorite-obsidian-plugins</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/my-favorite-obsidian-plugins</guid>
            <pubDate>Wed, 30 Mar 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Hiding scrollbars with CSS]]></title>
            <description><![CDATA[<p>Today I learned of a really simple way to make scrollbars functional, but hidden :]</p>
<p>It's really simple, you just need to add a couple of rules into your CSS and you'll be good to go:</p>
<pre><code class="hljs language-css"><span class="hljs-selector-class">.hide-scrollbar</span> {
  -ms-<span class="hljs-attribute">overflow</span>-style: none;  <span class="hljs-comment">/* IE and Edge */</span>  
  <span class="hljs-attribute">scrollbar-width</span>: none;  <span class="hljs-comment">/* Firefox */</span>
}

<span class="hljs-comment">/* Chrome, Safari and old Opera */</span>
<span class="hljs-selector-class">.hide-scrollbar</span>::-webkit-scrollbar { <span class="hljs-attribute">display</span>: none; }
</code></pre>
<p>This is really useful for when you have an off-canvas panel (or anything absolute/fixed positioned), and you want it to scroll by itself if it has too much content.</p>
<blockquote>
<p>Reference: <a href="https://www.w3schools.com/howto/howto_css_hide_scrollbars.asp">https://www.w3schools.com/howto/howto_css_hide_scrollbars.asp</a></p>
</blockquote>]]></description>
            <link>https://www.ratamero.com/blog/hiding-scrollbars-with-css</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/hiding-scrollbars-with-css</guid>
            <pubDate>Mon, 28 Mar 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[A week with Obsidian]]></title>
            <description><![CDATA[<p>
It's been a week since I started using Obsidian. It sells itself as a "second brain" app, and I must say: until now, it has not disappointed. Come with me and you'll see that it's not just about productivity, but about being healthier. :]</p>
<h2 id="what-is-obsidian"><a href="#what-is-obsidian">What is Obsidian?</a></h2>
<p><a href="https://obsidian.md/">Obsidian</a> is mostly a text editor, and it was made for you to organize your thoughts, research topics, writings, anything. The general idea is that you write simple <a href="/notes/Markdown">Markdown</a> files, which is plenty for most writing scenarios, and link them together, effectively making a <a href="/notes/knowledge-base">knowledge base</a>.</p>
<p>That way, you can slowly build a graph of what you know about a topic. The simple linking of your documents is enough to make a rough map of what's on your brain.</p>
<h2 id="why-would-i-need-that"><a href="#why-would-i-need-that">Why would I need that?</a></h2>
<p>Well, I can't say about your habits, but I'm using it for three main areas:</p>
<ul>
<li>researching and publishing about topics I like (this blog is built based on my Obsidian notes!);</li>
<li>work related issues, like keeping notes about meetings, making new workshops or talks, keeping track on how people I mentor are evolving, what has been most effective, etc.;</li>
<li>life things, like mood tracking, to-dos, and a general daily notes on what I've done and how I was feeling that day.</li>
</ul>
<h3 id="researching"><a href="#researching">Researching</a></h3>
<p>Obsidian is almost perfect for research notes, be them academic or not. The two important features here are forward-referencing notes, and the graph view.</p>
<p>To make a link between notes, you just need to wrap them with <code>[double brackets](/notes/double brackets)</code>. If the note exists, you're done, the link is made; but if the note does not exist, it creates the link anyway, and when you click it, it opens up a new note with the link's title. It seems so simple, and it is.</p>
<p>This allows us to preemptively select certain words that may be popping out too much, or may be important for the subject. It also makes us remember that maybe a specific idea or topic needs more work.</p>
<p>When you're done with your notes, or if you want to have a better idea on what the main topics are, you can open the graph view.</p>
<p>
It not only helps a lot on visualizing how things relate to each other, but it gives us a better sense on how much we've accomplished with our learnings - and I love this feeling of accomplishment. It gives me more confidence that I really worked hard on something, and that, if I need my notes on that, they're there.</p>
<p>Oh, and I think I don't need to tell you about <a href="/notes/the-benefits-of-writing-things-down">the benefits of writing things down</a>, right?</p>
<h3 id="work-related-notes"><a href="#work-related-notes">Work related notes</a></h3>
<p>I need to be frank: my memory sucks. It's <strong>so</strong> bad. To mitigate that...<em>characteristic</em>, a couple of years ago I started taking small notes, even if not entirely accurate, about what happened at meetings, or about project roadmaps, anything I thought that was useful or that I was sure I'd forget.</p>
<p>It already helped me a lot, but sometimes it was a bit hard extracting useful, long time data from the notes I had. If I wanted, for example, to know what were the areas that people I've mentored had the most trouble with, I'd have to go through all the notes, for all people, and reread everything, making even more notes. And I'm too lazy for that.</p>
<p>Forward-referencing links help me a lot here as well. I can see pretty quickly how many people had the same problem, or how much they talked about it, just by looking at the graph. This kind of information is priceless for people that teach, write, or make content.</p>
<h3 id="life-things"><a href="#life-things">life... things</a></h3>
<p>This may be the area Obsidian had the most impact with, and the advantages will probably keep getting bigger with time. Before Obsidian, I never kept notes about myself, never had a tool to track my mood, or what brought me down or made me happy.</p>
<p>Now, it's pretty easy for me to, you know, sit down and write about shit. Just write about shit. The good and the bad. And just by referencing things, you start to notice patterns emerging, be it bad/good habits, situations, or people that help me feel better or make me feel bad.</p>
<p>I started to understand a bit better <strong>what</strong> are the things I love, <strong>how</strong> to to them, <strong>why</strong> I do them. And while the other two areas were about productivity, <strong>this one is not</strong>. This one is about mental health, about keeping in touch with yourself and others, and <em>maybe</em> a little bit about recording history too; so that when I'm 40, even if Obsidian is not a thing anymore, or my life has completely changed, I still have notes.</p>
<p>Notes about what I learned. Notes about what work was all about. Notes about love.</p>]]></description>
            <link>https://www.ratamero.com/blog/a-week-with-obsidian</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/a-week-with-obsidian</guid>
            <pubDate>Sat, 26 Mar 2022 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Python para desenvolvedores javascript]]></title>
            <description><![CDATA[<p>logo depois de ter lido <a href="https://dev.to/underdogio/python-for-javascript-developers">esse post</a>, eu percebi que as poucas dificuldades que tive durante minha adaptação de javascript pra python (há anos) nunca foram ensinadas pra mim de uma maneira clara.</p>
<p>apesar de ambas as linguagens serem razoavelmente parecidas, achei interessante a ideia, então aqui vão algumas diferenças pra se ter em mente na hora de virar a chave. algumas são de Mario Pabon, o autor do post original, e algumas coisas são minhas mesmo. :)</p>
<p>ah, só um detalhe: aqui vamos supor que você está usando python 3, sim? bem, vamos lá!</p>
<h2 id="resumo"><a href="#resumo">Resumo</a></h2>
<ul>
<li><a href="#sintaxe">sintaxe</a>
<ul>
<li><a href="#declara%C3%A7%C3%A3o-de-vari%C3%A1veis">declaração de variáveis</a></li>
<li><a href="#blocos">blocos</a></li>
<li><a href="#controle-de-fluxo">controle de fluxo</a></li>
<li><a href="#ifelse">if...else</a></li>
<li><a href="#while">while</a></li>
<li><a href="#for">for</a></li>
</ul>
</li>
<li><a href="#tipos">tipos</a>
<ul>
<li><a href="#n%C3%BAmeros">números</a></li>
<li><a href="#listas">listas</a></li>
<li><a href="#strings">strings</a></li>
<li><a href="#dicion%C3%A1rios">dicionários</a></li>
<li><a href="#none">None</a></li>
<li><a href="#fun%C3%A7%C3%B5es">funções</a></li>
</ul>
</li>
<li><a href="#m%C3%B3dulos">módulos</a>
<ul>
<li><a href="#definindo-um-m%C3%B3dulo">definindo um módulo</a></li>
</ul>
</li>
<li><a href="#programa%C3%A7%C3%A3o-orientada-a-objetos">programação orientada a objetos</a>
<ul>
<li><a href="#heran%C3%A7a">herança</a></li>
</ul>
</li>
</ul>
<h2 id="sintaxe"><a href="#sintaxe">sintaxe</a></h2>
<h3 id="declaração-de-variáveis"><a href="#declaração-de-variáveis">declaração de variáveis</a></h3>
<p>para ambas as linguagens, declarar variáveis é simples.</p>
<p><strong>javascript</strong></p>
<pre><code class="hljs language-js"> <span class="hljs-keyword">var</span> x = <span class="hljs-number">3</span>;
</code></pre>
<p><strong>python</strong></p>
<pre><code class="hljs language-python">x = <span class="hljs-number">3</span>
</code></pre>
<p>mais tarde vamos falar de tipos, que fazem toda a diferença entre as linguagens. só vamos deixar clara, por enquanto, uma grande diferença: <strong>variáveis em python sempre pertencem ao contexto do seu bloco</strong>.</p>
<h3 id="blocos"><a href="#blocos">blocos</a></h3>
<p>python tende a sempre ser mais estrito do que javascript. em python, não seguir a indentação do código pode fazer com que ele nem rode. isso se dá porque o python usa a indentação para definir blocos, no lugar das chaves do javascript.</p>
<p><strong>blocos em javascript</strong></p>
<pre><code class="hljs language-js"> <span class="hljs-keyword">function</span> <span class="hljs-title function_">exampleFunction</span> (<span class="hljs-params"></span>) {
   <span class="hljs-comment">// isso é um bloco, com um contexto pras variáveis</span>
   <span class="hljs-keyword">var</span> a = <span class="hljs-number">5</span>;
 }
</code></pre>
<p><strong>blocos em python</strong></p>
<pre><code class="hljs language-python"> <span class="hljs-keyword">def</span> <span class="hljs-title function_">example_function</span>():
     <span class="hljs-comment"># isso também é, também com seu próprio escopo</span>
     <span class="hljs-comment"># que é definido pelo que tá no mesmo nível de indentação</span>
     x = <span class="hljs-number">5</span>
     <span class="hljs-built_in">print</span>(x)
</code></pre>
<p>se a linha do <code>print(x)</code> tivesse mais um ou menos um espaço antes da chamada da função, o interpretador do python levantaria uma exceção <code>IndentationError</code>, porque a diferença de espaços criaria um bloco inválido.</p>
<p>outro possível problema causado pelo mau uso de indentação em python é o de escopo.</p>
<pre><code class="hljs language-python"> x = <span class="hljs-string">"fora"</span>
 <span class="hljs-comment"># no escopo de fora, x = "fora"</span>
 <span class="hljs-keyword">def</span> <span class="hljs-title function_">example_function</span>():
     x = <span class="hljs-string">"dentro"</span>
     <span class="hljs-comment"># no de dentro, x = "dentro"</span>
     <span class="hljs-built_in">print</span>(x)
     <span class="hljs-comment"># retornaria "dentro"</span>
 <span class="hljs-built_in">print</span>(x)
 <span class="hljs-comment"># retornaria "fora"</span>
</code></pre>
<h3 id="controle-de-fluxo"><a href="#controle-de-fluxo">controle de fluxo</a></h3>
<p><code>if...else</code>, <code>while</code> e <code>for</code> em python são razoavelmente parecidos com javascript.</p>
<h3 id="ifelse"><a href="#ifelse">if...else</a></h3>
<p><strong>javascript</strong></p>
<pre><code class="hljs language-js"> <span class="hljs-keyword">if</span> (x > <span class="hljs-number">1</span>) {
     <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'oi'</span>);
 } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!x > <span class="hljs-number">1</span>) {
     <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'io'</span>);
 } <span class="hljs-keyword">else</span> {
     <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">'ioi'</span>);
 }
</code></pre>
<p><strong>python</strong></p>
<pre><code class="hljs language-python"> <span class="hljs-keyword">if</span> x > <span class="hljs-number">1</span>:
     <span class="hljs-built_in">print</span>(<span class="hljs-string">'oi'</span>)
 <span class="hljs-keyword">elif</span> <span class="hljs-keyword">not</span> x > <span class="hljs-number">1</span>:
     <span class="hljs-comment"># 'elif' em vez de 'else if', 'not' em vez de '!'</span>
     <span class="hljs-built_in">print</span>(<span class="hljs-string">'io'</span>)
 <span class="hljs-keyword">else</span>:
     <span class="hljs-built_in">print</span>(<span class="hljs-string">'ioi'</span>)
</code></pre>
<h3 id="while"><a href="#while">while</a></h3>
<p><strong>javascript</strong></p>
<pre><code class="hljs language-js"> <span class="hljs-keyword">while</span> (x &#x3C; <span class="hljs-number">3</span>){
   x++;
 }
</code></pre>
<p><strong>python</strong></p>
<pre><code class="hljs language-python"> <span class="hljs-keyword">while</span> x &#x3C; <span class="hljs-number">3</span>:
     x += <span class="hljs-number">1</span>
</code></pre>
<h3 id="for"><a href="#for">for</a></h3>
<p>em python, ao iterar sobre uma lista, não precisamos declarar o índice ou resgatar o objeto internamente - o objeto da vez já está implícito.</p>
<p><strong>javascript</strong></p>
<pre><code class="hljs language-js"> <span class="hljs-keyword">var</span> lista = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
 <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i=<span class="hljs-number">0</span>; i &#x3C; lista.<span class="hljs-property">length</span>; i++){
   <span class="hljs-keyword">var</span> item = lista[i];
   <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(item); <span class="hljs-comment">// 1; 2; 3</span>
 }
</code></pre>
<p><strong>python</strong></p>
<pre><code class="hljs language-python"> lista = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
 <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> lista: <span class="hljs-comment"># o item da vez ficará na variável 'item'</span>
     <span class="hljs-built_in">print</span>(item) <span class="hljs-comment"># 1; 2; 3</span>
</code></pre>
<p>o javascript até aceita a sintaxe de <code>for (item in lista)</code>, mas se comporta de maneira diferente, colocando na variável <code>item</code> o valor do contador do loop.</p>
<h2 id="tipos"><a href="#tipos">tipos</a></h2>
<p>os tipos em python são razoavelmente parecidos ao de javascript, já que você não precisa declarar os tipos para cada variável na hora da declaração (como se faz com java ou C#, por exemplo).</p>
<p>a grande diferença é como os tipos interagem, já que várias operações permitidas em javascript não são em python. python prefere levantar um erro em vez de fazer uma operação entre tipos que pode gerar um dado errado.</p>
<p>um dos exemplos mais clássicos é o da soma de números com strings:</p>
<p><strong>javascript</strong></p>
<pre><code class="hljs language-js"> <span class="hljs-keyword">var</span> a = <span class="hljs-number">5</span>; <span class="hljs-comment">// número inteiro;</span>
 <span class="hljs-keyword">var</span> b = <span class="hljs-string">"5"</span>; <span class="hljs-comment">// uma string que contém o número 5</span>
 a + b <span class="hljs-comment">// retornará a string "55"</span>
</code></pre>
<p><strong>python</strong></p>
<pre><code class="hljs language-python"> a = <span class="hljs-number">5</span> <span class="hljs-comment"># número inteiro</span>
 b = <span class="hljs-string">"5"</span> <span class="hljs-comment"># uma string que contém o número 5</span>
 a + b <span class="hljs-comment"># 'TypeError', já que não se pode somar tipos diferentes</span>
 <span class="hljs-comment"># em python, devemos transformar o número em string</span>
 <span class="hljs-comment"># ou a string em número</span>
 <span class="hljs-built_in">str</span>(a) + b <span class="hljs-comment"># string "55"</span>
 a + <span class="hljs-built_in">int</span>(b) <span class="hljs-comment"># inteiro 10</span>
</code></pre>
<p>já que tiramos essa dúvida da reta, vou dar um apanhado básico dos tipos em python.</p>
<h3 id="números"><a href="#números">números</a></h3>
<p>ao contrário de javascript, python tem vários tipos diferentes para diferentes números.</p>
<ul>
<li>inteiros (integer): <code>1</code>, <code>2</code>, <code>3</code></li>
<li>ponto flutuante (float): <code>4.20</code>, <code>4e420</code></li>
<li>números complexos: <code>4 + 20j</code></li>
<li>booleanos (boolean): <code>True</code>, <code>False</code></li>
</ul>
<p>você pode fazer as mesmas operações em ambas as linguagens, como, por exemplo, soma, subtração, divisão, multiplicação e potenciação.</p>
<h3 id="listas"><a href="#listas">listas</a></h3>
<p>listas em python são bem parecidas com as de javascript, com alguns adereços a mais. elas podem conter uma mistura de tipos:</p>
<pre><code class="hljs language-python"> [<span class="hljs-number">4</span>, <span class="hljs-string">"2"</span>, [<span class="hljs-number">0</span>, <span class="hljs-string">"zero"</span>]]
</code></pre>
<p>há também uma sintaxe especial para pegar partes de uma lista:</p>
<pre><code class="hljs language-python"> lista = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
 lista[<span class="hljs-number">0</span>:<span class="hljs-number">2</span>] <span class="hljs-comment"># 1, 2, 3</span>
 lista[<span class="hljs-number">3</span>:] <span class="hljs-comment"># 4, 5</span>
 lista[<span class="hljs-number">2</span>, -<span class="hljs-number">2</span>] <span class="hljs-comment"># 3, 4</span>
 <span class="hljs-comment"># se aceitam índices negativos, pegando do final da lista</span>
</code></pre>
<p>e algumas funções e métodos úteis:</p>
<pre><code class="hljs language-python"> <span class="hljs-built_in">len</span>([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]) <span class="hljs-comment"># 3</span>
 [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>].reverse() <span class="hljs-comment"># [3, 2, 1]</span>
 [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>].append(<span class="hljs-number">3</span>) <span class="hljs-comment"># [1, 2, 3], igual ao 'push' do js</span>
</code></pre>
<p>para concatenar listas, é só somá-las:</p>
<pre><code class="hljs language-python"> <span class="hljs-comment"># [1, 2, 3, 4]</span>
 [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>] + [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
</code></pre>
<p>pra fechar, temos em python o que chamam de <code>list comprehension</code>. é uma forma de criar listas dinamicamente.</p>
<pre><code class="hljs language-python"> lista = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
 maiores_que_2 = [numero <span class="hljs-keyword">for</span> numero <span class="hljs-keyword">in</span> lista <span class="hljs-keyword">if</span> numero > <span class="hljs-number">2</span>]
 <span class="hljs-comment"># maiores_que_2 é agora [3, 4]</span>
</code></pre>
<h3 id="strings"><a href="#strings">strings</a></h3>
<p>strings em python são praticamente iguais às de javascript. você pode acessar cada caractere individualmente, mas só pode alterar o conteúdo ao reassinalar a variável.</p>
<pre><code class="hljs language-python"> nome = <span class="hljs-string">'Luciano'</span>
 <span class="hljs-built_in">print</span>(nome[<span class="hljs-number">0</span>]) <span class="hljs-comment"># L</span>
 nome[<span class="hljs-number">0</span>] = <span class="hljs-string">'D'</span> <span class="hljs-comment"># TypeError</span>
</code></pre>
<h3 id="dicionários"><a href="#dicionários">dicionários</a></h3>
<p>dicionários são listas associativas em python, muito parecidos com objetos em javascript. eles são declarados praticamente da mesma forma.</p>
<pre><code class="hljs language-python"> pessoa = {
     <span class="hljs-string">'nome'</span>: <span class="hljs-string">'Luciano'</span>,
     <span class="hljs-string">'idade'</span>: <span class="hljs-number">27</span>
 }
 <span class="hljs-built_in">print</span>(pessoa[<span class="hljs-string">'nome'</span>]) <span class="hljs-comment"># Luciano</span>
 <span class="hljs-built_in">print</span>(pessoa[<span class="hljs-string">'gênero'</span>]) <span class="hljs-comment"># KeyError, gênero não foi declarado</span>
</code></pre>
<p>já que em python nós preferimos levantar erros em vez de falhar silenciosamente, temos um método padrão dos dicionários para resgatar valores default no caso de eles não terem sido declarados:</p>
<pre><code class="hljs language-python"> pessoa.get(<span class="hljs-string">'gênero'</span>, <span class="hljs-string">'não-binário'</span>)
 <span class="hljs-comment"># não achamos a chave "gênero", retornamos 'não-binário'</span>
</code></pre>
<h3 id="none"><a href="#none">None</a></h3>
<p><code>None</code> é equivalente a <code>null</code> em javascript. isso significa que <code>None</code> representa a ausência de um valor e é avaliado como <code>false</code>.</p>
<p>detalhe: não há par para <code>undefined</code> em python, já que tentar acessar algo não definido em python levanta uma exceção <code>NameError</code>.</p>
<h3 id="funções"><a href="#funções">funções</a></h3>
<p>assim como em javascript, funções também são objetos em python. isso significa que você pode passar funções como argumentos/callbacks ou até assinalar propriedades pra funções.</p>
<pre><code class="hljs language-python"> <span class="hljs-keyword">def</span> <span class="hljs-title function_">func_tainha</span>(<span class="hljs-params">a, other_func</span>):
     <span class="hljs-built_in">print</span>(a)
     other_func()
 
 <span class="hljs-keyword">def</span> <span class="hljs-title function_">another_func</span>():
     <span class="hljs-built_in">print</span>(<span class="hljs-string">'marilene'</span>)
 
 func_tainha(<span class="hljs-string">'olá'</span>, another_func)
 <span class="hljs-comment"># olá</span>
 <span class="hljs-comment"># marilene</span>
 
 func_tainha.vinho = <span class="hljs-string">'sinuelo'</span>
 <span class="hljs-built_in">print</span>(func_tainha.vinho)
 <span class="hljs-comment"># sinuelo</span>
</code></pre>
<h2 id="módulos"><a href="#módulos">módulos</a></h2>
<p>não quero falar sobre ES6 aqui, mas os módulos (pacotes) em python são bem parecidos (em sintaxe) com os módulos em javascript ES6.</p>
<h3 id="definindo-um-módulo"><a href="#definindo-um-módulo">definindo um módulo</a></h3>
<p>ao contrário de ES6, em que você tem que declarar o que você tá exportando pro seu módulo, em python você sõ precisa criar um arquivo <code>.py</code> e suas punções/classes/oquefor estão prontas pra serem importadas. basta que, na mesma pasta do seu módulo, você coloque um arquivo <code>__init__.py</code> pra que o interpretador python reconheça o módulo</p>
<pre><code class="hljs language-python"> <span class="hljs-comment"># qualquercoisa/qualquercoisa.py</span>
 <span class="hljs-keyword">def</span> <span class="hljs-title function_">dizer_quelquercoisa</span>():
   <span class="hljs-built_in">print</span>(<span class="hljs-string">'qualquercoisa'</span>)
</code></pre>
<hr>
<pre><code class="hljs language-python"> <span class="hljs-comment"># qualquercoisa/__init__.py</span>
 <span class="hljs-comment"># pode ser vazio mesmo</span>
</code></pre>
<hr>
<pre><code class="hljs language-python"><span class="hljs-comment"># qualquercoisa/lala.py</span>
<span class="hljs-keyword">import</span> qualquercoisa
<span class="hljs-comment"># importando o módulo inteiro</span>
qualquercoisa.dizer_quelquercoisa()
<span class="hljs-comment"># qualquercoisa</span>

<span class="hljs-keyword">from</span> qualquercoisa <span class="hljs-keyword">import</span> dizer_quelquercoisa
<span class="hljs-comment"># importando apenas a função 'dizer_quelquercoisa'</span>
dizer_quelquercoisa()
<span class="hljs-comment"># 'qualquercoisa'</span>
</code></pre>
<p>ah, e pra instalar pacotes disponibilizados pela comunidade, tipo <code>npm</code>, você usa o <code>pip</code>.</p>
<pre><code class="hljs language-python">pip install django
</code></pre>
<h2 id="programação-orientada-a-objetos"><a href="#programação-orientada-a-objetos">programação orientada a objetos</a></h2>
<p>em python, assim como ES6, há suporte a classes e herança entre objetos. isso é diferente da herança baseada em <code>prototypes</code> clássica do javascript.</p>
<pre><code class="hljs language-python">  <span class="hljs-comment"># você pode definir uma classe que representa qualquer animal</span>
 <span class="hljs-keyword">class</span> <span class="hljs-title class_">Animal</span>:
     <span class="hljs-comment"># qualquer variável definida aqui será uma propriedade da classe</span>
     idade_inicial = <span class="hljs-number">1</span>
 
     <span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self, nome, especie=<span class="hljs-string">'humano'</span></span>):
         <span class="hljs-comment"># aqui, declaramos que, ao criar um animal, podemos passar um nome e espécie pra ele</span>
         <span class="hljs-comment"># se não passarmos uma espécie, por padrão, ela será 'humano'</span>
         <span class="hljs-comment"># 'self' se comporta parecido com o 'this', mas sem toda a confusão de escopo</span>
         <span class="hljs-variable language_">self</span>.nome = nome
         <span class="hljs-variable language_">self</span>.especie = especie
         <span class="hljs-variable language_">self</span>.idade = <span class="hljs-variable language_">self</span>.idade_inicial
 
     <span class="hljs-keyword">def</span> <span class="hljs-title function_">comemorar_aniversario</span>(<span class="hljs-params">self</span>):
         <span class="hljs-comment"># ao comemorar aniversário, acrescentamos 1 à idade</span>
         <span class="hljs-variable language_">self</span>.idade += <span class="hljs-number">1</span>
 
     <span class="hljs-keyword">def</span> <span class="hljs-title function_">falar</span>(<span class="hljs-params">self</span>):
         <span class="hljs-comment"># se for um humano, ele fala besteira</span>
         <span class="hljs-keyword">if</span> <span class="hljs-variable language_">self</span>.especie == <span class="hljs-string">'humano'</span>:
             <span class="hljs-keyword">return</span> <span class="hljs-string">'blablablawhiskassachê'</span>
</code></pre>
<p>desse jeito, se inicializarmos um humano chamado Jorge e comemorarmos seu aniversário, teremos o seguinte:</p>
<pre><code class="hljs language-python"> jorge = Animal(<span class="hljs-string">'Jorge'</span>)
 jorge.idade
 <span class="hljs-comment"># 1</span>
 
 jorge.comemorar_aniversario()
 jorge.idade
 <span class="hljs-comment"># 2</span>
 
 jorge.falar()
 <span class="hljs-comment"># blablablawhiskassachê </span>
</code></pre>
<h3 id="herança"><a href="#herança">herança</a></h3>
<p>tendo como base nossa classe de animal, podemos, por exemplo, termos uma subclasse de animal chamada <code>Girafa</code>:</p>
<pre><code class="hljs language-python"> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Girafa</span>(<span class="hljs-title class_ inherited__">Animal</span>):
     <span class="hljs-string">"""
     ao passar Animal entre parênteses, herdamos tudo de Animal
     aqui, declaramos que girafas são da espécie 'girafa'
     e que não precisam de nome.
     pra isso, sobrescrevemos o __init__, que inicializa uma girafa.
     """</span>
     <span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self</span>):
         <span class="hljs-variable language_">self</span>.idade = <span class="hljs-variable language_">self</span>.idade_inicial
         <span class="hljs-variable language_">self</span>.especie = <span class="hljs-string">'girafa'</span>
</code></pre>
<p>assim, se inicializarmos uma girafa...</p>
<pre><code class="hljs language-python">girafa_nova = Girafa()
<span class="hljs-comment"># não precisamos mais passar nome</span>
girafa.idade
<span class="hljs-comment"># 1</span>
    
girafa.comemorar_aniversario()
girafa.idade
<span class="hljs-comment"># 2</span>
    
girafa.falar()
<span class="hljs-comment">#</span>
<span class="hljs-comment"># isso mesmo, girafa não fala,</span>
<span class="hljs-comment"># então se mandarmos ela falar, não sai nada :)</span>
</code></pre>
<hr>
<p>é claro que tem MUITO mais sobre python do que só isso, então se tiverem qualquer dúvida ou acharem que algo poderia ser explicado melhor, só falar nos comentários.</p>
<p>e lembrem que a melhor forma de aprender uma linguagem é meter a mão na massa e fazer um projetinho! se não souberem por onde começar, eu recomendo fortemente o <a href="https://tutorial.djangogirls.org/pt/">tutorial das pyladies do Django Girls</a>, mas se não quiser aprender com desenvolvimento web, tem sempre o <a href="https://www.pycursos.com/python-para-zumbis/">python para zumbis</a> do querido e fofíssimo Masanori.</p>
<p>abraços, e até a próxima!</p>]]></description>
            <link>https://www.ratamero.com/blog/python-para-desenvolvedores-javascript</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/python-para-desenvolvedores-javascript</guid>
            <pubDate>Thu, 08 Jun 2017 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Git e github parte 3 boas praticas de organizacao de branches]]></title>
            <description><![CDATA[<p></p>
<p>chegamos à parte 3 dos posts sobre git e github! nos <a href="https://www.ratamero.comhttps://ratamero.com/blog/git-e-github-parte-1-o-que-sao-e-como-usar/">outros</a> <a href="https://www.ratamero.comhttps://ratamero.com/blog/git-e-github-parte-2-conceitos-basicos-para-trabalhar-com-git/">dois</a>, falei sobre o que são o git e o github e slguns conceitos básicos pra começar a usar o git. hoje, vou falar mais sobre algumas boas práticas pra organização de branches, baseado nas sugestões do <a href="https://github.com/nvie/gitflow">git flow</a>.</p>
<hr>
<h3 id="o-que-é-o-git-flow"><a href="#o-que-é-o-git-flow">o que é o git flow?</a></h3>
<p>o <strong>git flow</strong> é uma extensão do git que permite uma maior organização e agilidade na hora de lidar com o git. ele segue uma série de convenções que caracterizam alguns tipos de branches com responsabilidades diferentes, próprias pra cada etapa do processo de desenvolvimento. vou detalhar melhor o papel de cada um dos tipos de branch.</p>
<p><strong>lembre-se:</strong></p>
<p>essas são apenas <strong>sugestões</strong> minhas e das próprias convenções do git flow.</p>
<p>o uso dessas sugestões muda de projeto a projeto, apesar dessas sugestões funcionarem em grande parte dos casos.</p>
<h3 id="branch-mastermain"><a href="#branch-mastermain">branch <code>master/main</code></a></h3>
<p></p>
<p>o branch <code>master</code> (ou, preferivelmente, <code>main</code>) é o branch no qual está o código que está em <strong>produção</strong>, ou seja, que está sendo <strong>diretamente usado pelos clientes</strong>. ele é caracterizado por sua grande quantidade de <strong>tags</strong>, que refletem cada versão do projeto que foi pra uso corrente. nele, não se deve ter commits soltos; devemos apenas adicionar commits nele através de merges de branches de <code>release</code> e de <code>hotfix</code>.</p>
<h3 id="branch-develop"><a href="#branch-develop">branch <code>develop</code></a></h3>
<p></p>
<p>o branch <code>develop</code> é o que contém o código previsto para a próxima <code>release</code>, ou seja, o próximo código que irá pro ar. nele, também não devemos commitar diretamente, deixando que seu código seja fornecido pelos branches de <code>feature</code> e <code>hotfix</code>, mas essa regra é um pouco mais flexível que a do <code>master</code>. uma boa prática é sempre deixá-lo estável, pronto para ir para o ar a qualquer momento, para evitar que uma funcionalidade não vá pro ar por causa de instabilidade de outras.</p>
<h3 id="branches-de-release"><a href="#branches-de-release">branches de <code>release</code></a></h3>
<p></p>
<p>os branches de <code>release</code> são aqueles que resumem o que uma nova versão do seu projeto terá. ele tem a responsabilidade de sair do <code>develop</code>, se mergear no <code>master</code> e no <code>develop</code> e, ao mergear no <code>master</code>, criar uma <code>tag</code> com o número da nova versão. geralmente, recebem o nome <code>release/[numero-da-versao]</code>. na minha experiência, acho uma má ideia commitar em branches de <code>release</code>, pelo simples motivo que, assim, temos certeza de que todo o código veio dos <code>hotfixes</code> e das <code>features</code>. dessa forma, os branches de <code>release</code> servem <strong>apenas como um ritual</strong> para que você tenha <strong>certeza</strong> do que está colocando no ar e qual é a versão desejada. é uma burocracia que já salvou minha vida algumas vezes. ;)</p>
<h3 id="branches-de-hotfix"><a href="#branches-de-hotfix">branches de <code>hotfix</code></a></h3>
<p></p>
<p>os branches de <code>hotfix</code> são os que são abertos na hora que algo em produção dá problema. são branches criados a partir do <code>master</code> e que se mergeiam novamente no <code>master</code> e no <code>develop</code>, já que precisamos das correções também no código que está sendo desenvolvido. geralmente, recebem o nome <code>hotfix/[numero-da-versao]</code>. eles também recebem suas próprias <code>tags</code>, que servem para dizer que, nesta versão, o problema x foi corrigido.</p>
<h3 id="branches-de-feature"><a href="#branches-de-feature">branches de <code>feature</code></a></h3>
<p></p>
<p>os branches de <code>feature</code> servem para, bem, features, né. eles partem do <code>develop</code> e mergeiam também no <code>develop</code>. geralmente, recebem o nome <code>feature/[descricao-da-funcionalidade]</code>. neles, commitamos o que é necessário para novas funcionalidades ficarem prontas, apesar de que eu, novamente, não recomendo que sejam feitos commits diretamente nele. o motivo disso é que, ao meu ver, features têm a tendência de terem muitos commits, o que deixaria difícil a revisão do código em um <em>pull request</em>. recomendo que, a partir dos branches de <code>feature</code>, sejam criados branches de <code>topic</code>, que terão o conteúdo de uma parte da funcionalidade, em um tamanho que permita a fácil revisão do código por outras pessoas.</p>
<h3 id="branches-de-topic"><a href="#branches-de-topic">branches de <code>topic</code></a></h3>
<p></p>
<p>os branches de <code>topic</code> são os coringas. geralmente, recebem o nome <code>topic/[nome-do-topico-abordado]</code>. são usados em qualquer lugar em que seja legal ter mais de um tópico, para facilitar a revisão de código. na real, uso os branches de <code>topic</code> saindo dos de <code>feature</code> e mergeando nos mesmos, ou partindo de um branch de <code>hotfix</code> e mergeando nos mesmos. são os menores branches, feitos para serem lidos e revisados rapidamente.</p>
<h3 id="e-o-que-o-git-flow-tem-a-ver-com-isso-tudo"><a href="#e-o-que-o-git-flow-tem-a-ver-com-isso-tudo">e o que o git flow tem a ver com isso tudo?</a></h3>
<p>o git flow, como eu disse, é uma extensão do git. ele cria comandos que servem de atalhos para os processos descritos acima. ele tem comandos para abrir e fechar <code>releases</code>, <code>features</code> e <code>hotfixes</code>, e é facilmente configurável. se essa organização de branches te interessou, acho que vale a pena dar uma olhada no <a href="https://github.com/nvie/gitflow">repositório deles</a> e ler o <a href="https://nvie.com/posts/a-successful-git-branching-model/">post sobre o workflow deles</a>. nesse post, eles detalham melhor o que é realmente necessário ser feito pra realizar essa proposta de organização.</p>
<p>como sempre, qualquer dúvida ou sugestão, é só falar nos comentários. espero que tenham gostado dessa série de posts e que tenha sido útil :D</p>
<p>eu fico por aqui, até a próxima! o/</p>]]></description>
            <link>https://www.ratamero.com/blog/git-e-github-parte-3-boas-praticas-de-organizacao-de-branches</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/git-e-github-parte-3-boas-praticas-de-organizacao-de-branches</guid>
            <pubDate>Fri, 19 Feb 2016 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Git e github parte 2 conceitos basicos para trabalhar com git]]></title>
            <description><![CDATA[<p></p>
<p>eis que voltamos para a parte 2 dos posts sobre git e github! dessa vez, vou discutir alguns conceitos básicos necessários para quem quer trabalhar com git. se ainda não leu o primeiro post, <a href="https://www.ratamero.comhttps://ratamero.com/blog/git-e-github-parte-1-o-que-sao-e-como-usar/">façam o favor</a>, porque não vou explicar de novo (#ranzinza). então vamos lá!</p>
<hr>
<h3 id="merge-e-conflitos"><a href="#merge-e-conflitos">merge e conflitos</a></h3>
<p>a última coisa que discutimos no último post foi a questão de termos branchs diferentes para commits e tarefas diferentes. ter múltiplos branchs é importante para que uma tarefa não influencie na outra, mas o que importa no final das contas é que todas as tarefas estejam prontas, juntas, entregues.</p>
<p></p>
<p>pra isso, os branchs paralelos precisam ser misturados novamente em um só, usando o processo que chamamos de <strong>merge</strong>. <strong>merge</strong> significa, ao pé da letra, <strong>convergir</strong>. essa convergência é necessária para que saibamos que tudo funciona em conjunto e para que possamos criar uma nova versão do projeto que está sendo desenvolvido.</p>
<p>isso se complica na hora que pensamos que, em branchs diferentes, os desenvolvedores podem mudar o mesmo arquivo, na mesma linha. quando isso acontece, ocorre o que chamamos de <strong>conflito</strong>. na hora do merge, o git tenta misturar o código (e geralmente é bem inteligente em se resolver sozinho), mas quando conflitos acontecem, é necessária intervenção manual no código para que tudo funcione bonitinho, então fiquem ligados pra que seu processo se adapte visando evitar conflitos.</p>
<h3 id="cherry-pick"><a href="#cherry-pick">cherry-pick</a></h3>
<p>digamos que no branch 1 temos uma tarefa e no 2, outra. pode acontecer o caso de que o branch 2 desenvolva algo que seria importante para o desenvolvimento do 1, mas, obviamente, temos o código de um separado do outro. nessas horas, podemos usar o <strong>cherry-pick</strong>.</p>
<p></p>
<p><strong>cherry-pick</strong> é o processo de pegar um commit específico, ou uma série de commits, e copiá-lo(s) para outro branch. pode ficar tranquilo, isso não vai interferir na hora do merge (mas pode dar a ilusão de que mais coisas foram mudadas na hora de gerar um pull request). use o cherry-pick com <strong>muita</strong> parcimônia.</p>
<h3 id="rebase"><a href="#rebase">rebase</a></h3>
<p>muitas vezes acontece de você criar um branch a partir de outro, mas perceber que devia ter esperado mais, porque foi feita alguma nova alteração importante no branch base. nessas horas, você pode usar o <strong>rebase</strong>.</p>
<p></p>
<p><strong>rebase</strong> é o ato de mudar o commit base de uma série de commits. ele é útil em alguns momentos, mas deve ser <strong>evitado</strong>, já que ele <strong>altera o histórico do git e pode gerar inconsistências de dados</strong> quando mais de uma pessoa está trabalhando no mesmo branch.</p>
<p>a maior utilidade que vejo no rebase é na hora em que você faz um commit local e, nesse meio tempo, alguém enviou um novo commit no repositório. nesse momento, para evitar um commit de merge na hora de sicronizar o código, você pode simplesmente usar o comando <code>git pull --rebase</code> pra pegar seu commit e colocar logo em seguida do que estava no repositório remoto.</p>
<h3 id="remotes"><a href="#remotes">remotes</a></h3>
<p>uma das coisas mais interessantes do git é a possibilidade de configurar múltiplas origens pra um mesmo projeto. assim, podemos enviar código de um projeto para múltiplos repositórios, e isso é feito a partir da configurações de <strong>remotes</strong>.</p>
<p></p>
<p>geralmente, só temos uma origem remota pra cada projeto, mas podemos ter, por exemplo, um outro repositório remoto configurado para fazer o deploy da aplicação. esse processo é usado por alguns serviços de hospedagem de site, como o <a href="https://heroku.com/">heroku</a>.</p>
<h3 id="tag"><a href="#tag">tag</a></h3>
<p>quando você tem vários commits com várias funcionalidades diferentes, você tende a não saber mais muito bem em qual commit que tal feature ficou pronta. para que você possa nomear o estado do projeto em um commit específico, você pode usar uma <strong>tag</strong>.</p>
<p></p>
<p>uma <strong>tag</strong> nada mais é do que um atalho a um commit específico, que descreve um estado do seu projeto. você pode, por exemplo, nomear de 1.0 a versão inicial de seu projeto e ir criando novas tags pra cada nova versão de produção.</p>
<hr>
<p>por hoje, acho que é isso, pessoal. no próximo, e último post, vou discutir um pouco sobre boas práticas para desenvolvimento usando git. caso tenham alguma dúvida ou sugestão, só mandarem ver nos comentários, sim? abraços, e até a próxima! o/</p>]]></description>
            <link>https://www.ratamero.com/blog/git-e-github-parte-2-conceitos-basicos-para-trabalhar-com-git</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/git-e-github-parte-2-conceitos-basicos-para-trabalhar-com-git</guid>
            <pubDate>Thu, 18 Feb 2016 00:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Git e github parte 1: o que são e como usar]]></title>
            <description><![CDATA[<p></p>
<p>hoje eu tava conversando com uns amigos sobre git e github e percebemos um problema: não temos atualmente um lugar com conteúdo sobre os dois em português, principalmente para leigos ou iniciantes. depois de pegar com o pessoal uns pontos importantes, decidi fazer alguns posts sobre o assunto, para servir de referência. aí vamos nós o/</p>
<hr>
<h3 id="o-que-é-o-git"><a href="#o-que-é-o-git">o que é o git?</a></h3>
<p></p>
<p><a href="https://git-scm.com/">git</a> é uma <strong>ferramenta para versionamento de arquivos</strong>.</p>
<p>um exemplo: digamos que você queira escrever um poema pro seu amorzinho e tenha várias ideias. você escreve um verso, escreve outro e pronto, taí seu poema, o <code>amorzinho.txt</code>. você manda o arquivo pro seu amorzinho, que fica apaixonado. depois de alguns dias, você tem uma ideia nova, volta no texto, reescreve um verso e manda pro seu amorzinho de novo, esperando coraçõezinhos de carinho. mas seu amorzinho diz "a versão antiga era tão mais bonita... tem como me mandar a antiga?". mas, oh!, você esqueceu como o texto era e não tem mais salvo em lugar nenhum! aí que entra o git.</p>
<p>o git serve para que você possa criar uma linha do tempo com diferentes pontos das alterações feitas. assim, você consegue manter o histórico das alterações de um mesmo arquivo ou arquivos ao longo do tempo.</p>
<p>nem preciso dizer o quanto isso é <strong>crucial</strong> para projetos de software, já que esses projetos exigem que você e sua equipe criem novas funcionalidades nos mesmos arquivos, com uma versão antiga salva pro caso da nova dar problema. vou explicar melhor <strong>como</strong> ele funciona daqui a pouco, mas, antes, tenho que explicar o que é o github.</p>
<h3 id="o-que-é-o-github"><a href="#o-que-é-o-github">o que é o github?</a></h3>
<p></p>
<p><a href="https://github.com/">github</a> é só um <strong>site</strong> no qual você pode fazer <strong>upload de projetos git</strong>.</p>
<p>o github (palavra que seria traduzida como "agregador de gits") é o site mais conhecido de hospedagem de projetos git. ele serve para que você e sua equipe possam manter as versões do projeto em que trabalham em um lugar centralizado, na internet, acessível a quem pertence ao projeto.</p>
<p>além de hospedar projetos git, o github dá visibilidade da linha do tempo de diferentes versões do projeto, provê ferramentas de métricas (como quais usuários alteraram mais o projeto, quando alteraram, o que alteraram, etc), gerência de problemas relatados (<em>tickets</em> ou <em>issues</em>), dentre outras. vou detalhar um pouco melhor daqui a pouco.</p>
<p><strong>lembrem-se:</strong></p>
<p>a diferença entre git e github é que <strong>o git é só uma ferramenta para versionar projetos</strong>, enquanto <strong>o github é o site no qual você colocará esses projetos versionados</strong>. uma analogia válida seria que o git é seu pincel e tintas enquanto o github é um museu.</p>
<h3 id="beleza-mas-como-o-git-funciona"><a href="#beleza-mas-como-o-git-funciona">beleza, mas como o git funciona?</a></h3>
<p>vou tentar explicar conceitos básicos, mas não vou fazer um tutorial de como usar a ferramenta, porque <a href="https://www.atlassian.com/git/tutorials/">tem</a> <a href="https://try.github.io/levels/1/challenges/1">vários</a> <a href="https://rogerdudler.github.io/git-guide/">por</a> <a href="https://git-scm.com/book/pt-br/v1/Primeiros-passos-No%C3%A7%C3%B5es-B%C3%A1sicas-de-Git">aí</a>.</p>
<p>bem, digamos que você tenha uma pasta com seus textos, ok? seria muito legal saber, ao longo do tempo, como foi sua evolução como escritor, ou seja, quais textos foram adicionados, removidos ou alterados. você decide começar a usar o git na pasta de textos e quer salvar o estado atual da pasta.</p>
<p>pra isso, você cria um <strong>commit</strong> inicial.</p>
<p>um <strong>commit</strong> é um documento que descreve uma alteração, um ponto na linha do tempo do projeto. ele é como um registro de uma alteração no projeto. essa alteração é salva com seu nome, seu email, data da alteração, suas alterações na pasta e uma descrição da alteração, que você mesmo escreve.</p>
<p>
então, na hora que você coloca os textos na pasta pela primeira vez, você cria um commit com a descrição "adiciona os textos que tenho agora", seleciona todos os arquivos e pronto, você tem um ponto na linha do tempo!</p>
<h3 id="ok-mas-agora-quero-usar-o-github-pra-salvar-meus-textos-na-nuvem-comofas"><a href="#ok-mas-agora-quero-usar-o-github-pra-salvar-meus-textos-na-nuvem-comofas">ok, mas agora quero usar o github pra salvar meus textos na nuvem? comofas</a></h3>
<p>pra isso, você cria uma conta no github e cria o que chamamos de um <strong>repositório</strong>.</p>
<p>na linguagem do povo de computação, <strong>repositórios</strong> são <strong>locais nos quais colocamos arquivos na internet</strong>. eles servem para que qualquer um consiga <strong>repor</strong> o código de um projeto no seu computador, caso você não tenha ele salvo. isso significa que, quando você for colocar seu projeto no github, você primeiro precisa criar um repositório lá.</p>
<p>com o repositório criado no github, você só precisa configurar <strong>onde</strong> está seu repositório e <strong>empurrar</strong> as <strong>alterações</strong> pra lá. ou seja, você define a <strong>origem</strong> do repositório e faz um <strong>push</strong> dos <strong>commits</strong> pra lá.</p>
<p></p>
<h3 id="legal-agora-tenho-os-meus-textos-salvos-no-github-que-que-eu-faço-com-isso"><a href="#legal-agora-tenho-os-meus-textos-salvos-no-github-que-que-eu-faço-com-isso">legal, agora tenho os meus textos salvos no github. que que eu faço com isso?</a></h3>
<p>agora, com os textos lá, você pode fazer várias coisas. vou enumerar algumas, as mais básicas e úteis. :)</p>
<h4 id="clonagem-de-repositórios"><a href="#clonagem-de-repositórios">clonagem de repositórios</a></h4>
<p>digamos que você foi passar o fim de ano na casa dos seus pais e você quer alterar algum texto. você sabe que tem todos eles no seu computador, mas você (sua anta) esqueceu de trazê-lo. você até pode copiar os textos direto do site do github pro computador da sua mãe, mas isso significa que, se você quiser salvar a nova versão lá, você vai ter que criar <strong>outro</strong> repositório. relaxa, pra isso serve a clonagem de repositórios.</p>
<p></p>
<p><strong>clonar</strong> um repositório significa <strong>baixar o projeto git inteiro, direto da origem, pro seu computador</strong>. isso quer dizer que <strong>todas as alterações</strong>, de <strong>toda a linha do tempo</strong>, estão agora no seu computador. assim, ao você clonar um repositório, você pode simplesmente <strong>criar novos commits</strong> e <strong>dar push</strong> das novas alterações.</p>
<p>isso permite que uma equipe possa fazer alterações no projeto, cada um em seu computador, e possa sincronizar essas alterações através de <strong>pushs (empurrões)</strong> e <strong>pulls (puxadas)</strong> de <strong>commits (alterações)</strong> de um mesmo <strong>repositório (projeto)</strong>. é assim que uma equipe de software trabalha hoje em dia. :)</p>
<h4 id="forks-de-repositórios"><a href="#forks-de-repositórios">forks de repositórios</a></h4>
<p>ok, digamos que seu amigo tem um amorzinho também e quer escrever aquele poema lindo, mas não tem muita criatividade. você diz pra ele "cara, pode usar o amorzinho.txt, mas tem que dar uma alterada, senão vai pegar mal". você não quer, no entanto, que seu amiguinho use seu repositório, porque, né, é seu, com seus textos. o que seu amigo pode fazer pra ter a versão dele dos seus textos é criar o que chamamos de <strong>fork</strong>.</p>
<p></p>
<p>um <strong>fork</strong> é um repositório criado a partir de outro. tudo nele é literalmente igual, desde o conteúdo dos arquivos até os commits salvos; a única diferença é que <strong>pertence a um usuário diferente</strong>.</p>
<p>no entanto, a utilidade de um fork só se revela totalmente quando começamos a falar sobre <strong>issues e pull requests</strong>.</p>
<h4 id="issues-e-pull-requests"><a href="#issues-e-pull-requests">issues e pull requests</a></h4>
<p>seu amigo, ao ler o seu poema <code>amorzinho.txt</code>, percebe que você escreveu errado o nome do seu amorzinho. ele quer te avisar que isso precisa ser corrigido, porque isso é um <strong>problema</strong>, uma <strong>issue</strong>.</p>
<p>uma <strong>issue</strong> é um relatório de um problema que precisa ser corrigido. imaginemos que seu site, por exemplo, tem um link quebrado. qualquer um pode <strong>abrir uma issue</strong> no seu <strong>repositório no github</strong> dizendo que o link da página tal está quebrado.</p>
<p>o problema é que você, mantenedor do projeto, tá extremamente ocupado dando aulas pro seu amigo de como escrever um poema romântico. você vai lá e responde pro cara, na própria issue, que você tá enrolado demais, mas que ficaria muito agradecido caso o cara pudesse corrigir esse problema pra você.</p>
<p>o cara é esperto: ele cria um <strong>fork</strong> do repositório, localiza o arquivo problemático, corrige o link, salva, <strong>cria um commit</strong>, <strong>faz um push</strong> das alterações <strong>pro fork dele</strong>, tudo certo. só um detalhe: a correção <strong>precisa ser misturada com o seu</strong> repositório**. pra isso, ele cria um** pull request**, ou seja, um** pedido de empurrão de alterações**.</p>
<p>nesse pull request, constam os <strong>commits</strong> feitos, os <strong>arquivos alterados</strong> e uma descrição da correção. mas digamos que o cara esqueceu de alterar em outro lugar; você comenta no pull request dizendo que precisa alterar no outro lugar.</p>
<p></p>
<p>esse detalhe deixa claro que <strong>pull requests também são issues</strong>. ambos são <strong>discussões sobre um problema</strong>. mas, claro, <strong>issues não são necessariamente pull requests</strong>, porque <strong>pull requests têm como objetivo a correção de uma ou mais issues</strong>.</p>
<h3 id="ufa-tá-tenso-mas-ok-vamo-lá-mais-alguma-coisa"><a href="#ufa-tá-tenso-mas-ok-vamo-lá-mais-alguma-coisa">ufa. tá tenso. mas ok, vamo lá, mais alguma coisa?</a></h3>
<p>só mais uma, juro, tá acabando! digamos que você e seu amigo querem fazer diferentes versões de um mesmo poema num mesmo repositório. se você alterar e fizer um commit, seu amigo vai acabar fazendo outro commit por cima do seu, e isso não é legal. o que você pode fazer é <strong>criar uma bifurcação no repositório</strong> e dizer pro seu amigo que o seu branch é o seu e o dele é o dele. assim, enquanto você faz commits em uma bifurcação, seu amigo faz em outra, sem que uma interfira na outra. isso significa que, agora, seu projeto tem <strong>dois branchs</strong> (tecnicamente, três, porque tem o branch base, né).</p>
<p></p>
<p><strong>branchs</strong> são <strong>bifurcações ou ramificações</strong> dentro de um projeto git. eles servem para que tenhamos diferentes versões baseadas em um mesmo ponto do tempo. são usados para que a equipe se organize, para que um desenvolvedor faça a correção do link em um branch, enquanto outro desenvolvedor continua commitando em outro branch, sem interferirem um no processo do outro.</p>
<h3 id="tldr-resumo"><a href="#tldr-resumo">tl;dr (resumo)</a></h3>
<p>bem, falei até demais, mas acho que valeu a pena. vamos resumir alguns termos então.</p>
<h4 id="git"><a href="#git">git</a></h4>
<p><strong>git</strong> é um <strong>programa</strong>, uma <strong>ferramenta</strong> para versionamento de arquivos. serve para que você tenha uma linha do tempo de alterações de uma pasta, de um projeto.</p>
<h4 id="commit"><a href="#commit">commit</a></h4>
<p>um <strong>commit</strong> é um ponto da linha do tempo de um projeto git. ele descreve as alterações feitas num ponto do tempo, criando um <strong>snapshot</strong> do projeto.</p>
<h4 id="repositório"><a href="#repositório">repositório</a></h4>
<p>um <strong>repositório</strong> é um <strong>local na internet</strong> onde podemos colocar nosso projeto git.</p>
<h4 id="github"><a href="#github">github</a></h4>
<p>o <strong>github</strong> é o site mais famoso de hospedagem de repositórios.</p>
<h4 id="clonagem"><a href="#clonagem">clonagem</a></h4>
<p>a <strong>clonagem</strong> de repositórios é a ação que cria no seu computador local uma cópia de um projeto git ligada diretamente a um repositório. permite que você possa rapidamente criar um novo commit e empurrar as alterações diretamente para seu repositório.</p>
<h4 id="push-e-pull"><a href="#push-e-pull">push e pull</a></h4>
<p><strong>push</strong> e <strong>pull</strong> são as ações mais feitas para se sincronizar o estado de um projeto git. com o <strong>push</strong> você <strong>empurra</strong> os commits feitos localmente e com o <strong>pull</strong> você pega as alterações que estão no repositório.</p>
<h4 id="forks"><a href="#forks">forks</a></h4>
<p><strong>forks</strong> são repositórios criados a partir de outro. servem para que um usuário possa ter sua própria cópia de um repositório, para que faça suas próprias alterações.</p>
<h4 id="issues"><a href="#issues">issues</a></h4>
<p><strong>issues</strong> são tickets, relatos de problemas de um projeto. permitem discutir um bug, propor uma nova funcionalidade, etc.</p>
<h4 id="pull-requests"><a href="#pull-requests">pull requests</a></h4>
<p><strong>pull requests</strong> são <strong>issues* que contém</strong> commits<strong>que solucionam</strong> issues<strong>ou</strong> adicionam funcionalidades**. também servem para discutir problemas, soluções e também para revisar alterações feitas.</p>
<h4 id="branchs"><a href="#branchs">branchs</a></h4>
<p><strong>branchs</strong> são <strong>bifurcações</strong> em um projeto git. servem para que pessoas possam trabalhar em paralelo em um mesmo projeto sem medo de sobrescrever ou alterar algo que outra pessoa está fazendo.</p>
<h3 id="acho-que-é-isso-então"><a href="#acho-que-é-isso-então">acho que é isso então</a></h3>
<p>é, falei aqui sobre alguns aspectos básicos do git, mas muita, <strong>muita</strong> coisa ficou de fora. pra quem é leigo, acho que tá tranquilo parar por aqui, mas pros programadores iniciantes, pessoas que querem se envolver na área ou curiosos, tô preparando uma parte 2, com conceitos um pouco mais avançados.</p>
<p>enquanto isso, discutam nos comentários sobre o que ficou confuso ou o que pode melhorar! é isso aí, pessoal. até mais o/</p>]]></description>
            <link>https://www.ratamero.com/blog/git-e-github-parte-1-o-que-sao-e-como-usar</link>
            <guid isPermaLink="true">https://www.ratamero.com/blog/git-e-github-parte-1-o-que-sao-e-como-usar</guid>
            <pubDate>Sun, 14 Feb 2016 00:00:00 GMT</pubDate>
        </item>
    </channel>
</rss>