<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sonny Alves Dias</title>
    <description>The latest articles on DEV Community by Sonny Alves Dias (@sonny_ad).</description>
    <link>https://dev.to/sonny_ad</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F612697%2Fccdf14ab-4422-4d18-a71d-0fb92cf74179.jpg</url>
      <title>DEV Community: Sonny Alves Dias</title>
      <link>https://dev.to/sonny_ad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sonny_ad"/>
    <language>en</language>
    <item>
      <title>How to do a (serverless) web redirection in AWS Route53?</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Thu, 20 Apr 2023 09:41:41 +0000</pubDate>
      <link>https://dev.to/sonny_ad/how-to-do-a-serverless-web-redirection-in-aws-route53-2n93</link>
      <guid>https://dev.to/sonny_ad/how-to-do-a-serverless-web-redirection-in-aws-route53-2n93</guid>
      <description>&lt;p&gt;Imagine you are using a DNS provider and you have a domain example.com and example.net redirecting to example.com. It's pretty easy to set up. &lt;/p&gt;

&lt;p&gt;One day you migrate to AWS Route53 because you want geolocation, load balancing, or something of the sort. And disaster! There is no web redirection. &lt;/p&gt;

&lt;p&gt;With this article, you will know how to solve that and set up a serverless web redirection at a low cost and a little effort.&lt;/p&gt;

&lt;h1&gt;
  
  
  Steps
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Lambda
&lt;/h2&gt;

&lt;p&gt;Please find below an example of a NodeJS lambda:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and Python&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Location&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. API Gateway
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Select a &lt;code&gt;REST API&lt;/code&gt; (*&lt;em&gt;not Private *&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;In the next page, 

&lt;ul&gt;
&lt;li&gt;confirm &lt;code&gt;REST API&lt;/code&gt;, not Websocket&lt;/li&gt;
&lt;li&gt;create a &lt;code&gt;New API&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;give it a name like web-redirection&lt;/li&gt;
&lt;li&gt;endpoint type select &lt;code&gt;Edge Optimized&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;In the API detail page,

&lt;ul&gt;
&lt;li&gt;Click on &lt;code&gt;Actions&lt;/code&gt; and select &lt;code&gt;Create Method&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;GET&lt;/code&gt; method under the path / and confirm&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;In the / GET method details,

&lt;ul&gt;
&lt;li&gt;Select the lambda you created in the first section and save.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Finally, publish the API by clicking on &lt;code&gt;Actions&lt;/code&gt; &amp;gt; &lt;code&gt;Deploy API&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Enter a stage name for your deployment something like &lt;code&gt;production&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Custom Domain Name
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Still in the API Gateway service, click on &lt;code&gt; Custom Domain Names&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;For each domain you want to redirect, Create a Custom Domain Name

&lt;ul&gt;
&lt;li&gt;Select &lt;code&gt;Edge Optimized&lt;/code&gt; to match the API Gateway we created above&lt;/li&gt;
&lt;li&gt;And select (or create) a certificate that matches the domain &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Once created, setup API mapping to the API gateway we created before with no path required&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. CloudFront
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Go to CloudFront and create a distribution&lt;/li&gt;
&lt;li&gt;Do not define any alternate domain, and no certificate&lt;/li&gt;
&lt;li&gt;For the origin enter the API gateway endpoint and specify for the origin path &lt;code&gt;/prod&lt;/code&gt; as the stage name you defined earlier&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Route53
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add a Route53 record on the domain&lt;/li&gt;
&lt;li&gt;And point at the CloudFront from the previous section&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Go to your domain example.net and validate that the redirection to example.com is working!&lt;/p&gt;

</description>
      <category>route53</category>
      <category>migrate</category>
      <category>setup</category>
      <category>easy</category>
    </item>
    <item>
      <title>On how to write a technical blog</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Sat, 12 Feb 2022 07:13:42 +0000</pubDate>
      <link>https://dev.to/sonny_ad/on-how-to-write-a-technical-blog-28hh</link>
      <guid>https://dev.to/sonny_ad/on-how-to-write-a-technical-blog-28hh</guid>
      <description>&lt;h1&gt;
  
  
  On how to write a technical blog
&lt;/h1&gt;

&lt;h2&gt;
  
  
  How to pick a subject?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🐦🐦🪨 Kill two birds with one stone.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pick a subject related to something you are currently working on or something you are willing to learn. &lt;/p&gt;

&lt;p&gt;Or &lt;strong&gt;📰 Check the trending topics.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's ok to lack inspiration. So don't hesitate to look at the trends in your field and share your experience or point of view.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to take notes?
&lt;/h2&gt;

&lt;p&gt;There are plenty of solutions: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notion&lt;/li&gt;
&lt;li&gt;EverNote&lt;/li&gt;
&lt;li&gt;OneNote&lt;/li&gt;
&lt;li&gt;Simple text files&lt;/li&gt;
&lt;li&gt;Notebook&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You have to try and find the one that suits you the best. &lt;/p&gt;

&lt;p&gt;But: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Write your ideas as soon as you can&lt;/strong&gt;, you may forget them,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't elaborate on your writing yet&lt;/strong&gt;, you want to be quick and work on the writing quality in a later step, &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't hesitate to use mnemonics&lt;/strong&gt; that you know of or even create yours. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to write the article from my notes?
&lt;/h2&gt;

&lt;p&gt;Again, my suggestion is to 👇&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🐦🐦🐦🪨 Kill three birds with one stone.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="//bloggu.io"&gt;bloggu.io&lt;/a&gt;, because it allows you to publish on three different channels at once: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hashnode&lt;/li&gt;
&lt;li&gt;Dev.to&lt;/li&gt;
&lt;li&gt;Medium&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But anyway in general on most platforms nowadays you need to write in &lt;a href="https://www.markdownguide.org/"&gt;Markdown&lt;/a&gt; so get used to it. &lt;/p&gt;

&lt;p&gt;Then based on your notes, write the first draft on your platform of choice. &lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;don't spend hours on it&lt;/strong&gt;. Give you time constraints. Timebox the time you spend on it.&lt;/p&gt;

&lt;p&gt;While writing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If you realize you lack some matter for the content&lt;/strong&gt;, go get that matter and come back to your draft later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you realize you have too much to say on the subject&lt;/strong&gt;, don't hesitate to split your article into multiple ones. It'll be easier to read. Unless you are writing a complete guide on a subject, I would not recommend a long article. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ok I wrote my article, I click on publish now?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No, please don't do that, yet!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🧹It's time to clean up your article! Here is the recipe: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://hemingwayapp.com/"&gt;https://hemingwayapp.com/&lt;/a&gt; Copy-paste your contents and fix it according to the feedback. As a thumb rule at the same time, try to remove 15% of your writing. The shorter the better for your reader.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://app.grammarly.com/"&gt;https://app.grammarly.com/&lt;/a&gt; Copy-paste your article into a Grammarly document and fix all the left grammar issues. &lt;/li&gt;
&lt;li&gt;(Optional) Get a friend or colleague to read your article and give you feedback. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Alright, remember that &lt;strong&gt;you don't have to get the best score in hemingwayapp, but fixing all the grammar issues is a must.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  OK, I click publish now?
&lt;/h2&gt;

&lt;p&gt;Wait! do you have a cover image 🖼️? No? 🤦 &lt;/p&gt;

&lt;p&gt;My advice here is: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="//canva.com"&gt;canva.com&lt;/a&gt;, it's super easy and free to create a cover image with clear titles&lt;/li&gt;
&lt;li&gt;or &lt;a href="//unsplash.com"&gt;unsplash.com&lt;/a&gt;, it's a free website of stock photos so no titles over but good enough to illustrate an article. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So up to you, but obviously the more explicit is your picture about your article the better!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The last thing is the tags for your article.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I would suggest using a mix of trending tags and less trending ones. &lt;/p&gt;

&lt;p&gt;You will take profit from the visibility the trending ones will offer you. And profit from the niche audience of the less trending ones. &lt;/p&gt;

&lt;h2&gt;
  
  
  Click on publish now!
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Congrats! You published an article to the community!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Time to share the word on social networks and the internet. &lt;/p&gt;

&lt;p&gt;Also, &lt;strong&gt;🪴 don't hesitate to garden your article&lt;/strong&gt;. Things may evolve, you may find better ways, change opinions, etc. So come back to your article and rework it. &lt;/p&gt;

</description>
      <category>writing</category>
      <category>blog</category>
    </item>
    <item>
      <title>Finding a job is easy!</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Tue, 01 Feb 2022 07:22:42 +0000</pubDate>
      <link>https://dev.to/sonny_ad/finding-a-job-is-easy-3km5</link>
      <guid>https://dev.to/sonny_ad/finding-a-job-is-easy-3km5</guid>
      <description>&lt;p&gt;Since childhood, I longed for working on video games. When we move to China with my wife, I thought it was a good time to try to land a job in the industry!&lt;/p&gt;

&lt;p&gt;So, 6 months before actually moving to China, I started my new job search. I sent CVs and application letters to tens of companies. I got only got very few responses and all negatives.&lt;/p&gt;

&lt;p&gt;By the time, we were actually moving to China, I still had no job. Meaning also not a long-stay visa for me... Time was clocking.&lt;/p&gt;

&lt;p&gt;Once in China, I continued to apply daily. I certainly felt hopeless several times and started to reconsider things.&lt;/p&gt;

&lt;p&gt;While I was starting to consider alimentary jobs, I scheduled a couple of interviews in Shanghai.&lt;/p&gt;

&lt;p&gt;This was somehow the last chance for me. If it was not working out, I would go for a backup plan, I was thinking. Time was clocking after all.&lt;/p&gt;

&lt;p&gt;I got a clean haircut, shaved, and we booked a cheap hotel in a Shanghai suburb close to the train station for a week. &lt;/p&gt;

&lt;p&gt;The first interviews went ok. But even if it was in the gaming industry, it definitely did not match my ambitions. And what I imagined.&lt;/p&gt;

&lt;p&gt;But thankfully, the last one went well. It went great, actually. I made a good impression and the company was fascinating. &lt;/p&gt;

&lt;p&gt;I got an offer right away that I accepted in the following hour, the interview, I believe. Ending 8 months of research. And allowing me to stay in China long-term!&lt;/p&gt;

&lt;p&gt;But after a month and a half or about so, one morning a company meeting was summoned. The suspense didn’t last long. &lt;/p&gt;

&lt;p&gt;The meeting was about the news: The game I was working on was canceled. And the team working on it was being laid off (including me).&lt;/p&gt;

&lt;p&gt;But somehow I took the news very neutrally. My career in the gaming industry was just starting. And within this short lapse of time, I felt I proved to myself that I was capable of it. &lt;/p&gt;

&lt;p&gt;I didn't want to give up on that career I was longing for and that I know I was capable of. &lt;/p&gt;

&lt;p&gt;I resumed my job search with that spirit. But one thing was different, I had a foot in the industry. I had an apartment in Shanghai, a related experience, and a network. &lt;/p&gt;

&lt;p&gt;Quickly I have been scheduling 7 to 8 interviews in the following week after the news. I was still very excited and formatted to do job research.&lt;/p&gt;

&lt;p&gt;After that week full of interviews, I got a couple of offers. At the same time, I grew my network a lot, and even if I were to be laid off again, I knew I could find something else.&lt;/p&gt;

&lt;p&gt;Finding a job is not easy! But to make it easier, here are some tips for you readers if you are currently looking for a job:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Be in the right mindset&lt;/strong&gt; &lt;br&gt;&lt;br&gt;
To maximize your luck, you need to show self-confidence, extraversion, energy, organization, and such. If you are introverted like me, that requires some work on yourself upfront.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If you are moving to a new location, do research on the local companies&lt;/strong&gt; &lt;br&gt; &lt;br&gt;
TBH, I lost quite some time just trying to apply to the companies I knew, or I could think of. While I could have tried to look for more local companies and understand the local ecosystem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use or grow your network&lt;/strong&gt; &lt;br&gt;&lt;br&gt;
LinkedIn is great for that, or the internet in general. But also with any interview, you get. You can keep in touch with the company and/or the interviewers. A no is rarely definitive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Come prepared to interview&lt;/strong&gt; &lt;br&gt; &lt;br&gt;
You need to be the best of yourself, be full of energy, and ambitions. But also research info on the company and the products you may be working on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Be patient&lt;/strong&gt; &lt;br&gt; &lt;br&gt;
Especially if you are trying to join a new industry like the gaming industry, you may have to prove yourself. Get related experience as much as you can and build a portfolio and/or list of references.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good luck to you in your job research!&lt;/p&gt;




&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@dylandgillis?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Dylan Gillis&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>jobsearch</category>
    </item>
    <item>
      <title>gRPC proto files Best Practices</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Fri, 21 Jan 2022 09:51:44 +0000</pubDate>
      <link>https://dev.to/sonny_ad/grpc-proto-files-best-practices-2aab</link>
      <guid>https://dev.to/sonny_ad/grpc-proto-files-best-practices-2aab</guid>
      <description>&lt;p&gt;This article is a mash-up of different sources cited in references and Pixelmatic guidelines aimed to serve as coding and style guides for proto files in the context of gRPC services definitions. &lt;/p&gt;

&lt;h2&gt;
  
  
  Coding and style guides
&lt;/h2&gt;

&lt;p&gt;In short, the philosophy of the guides is: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Be consistent&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reuse the well-known types from Google&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;But keep separation as needed to avoid breaking changes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Standard file formatting
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keep the line length to 80 characters.&lt;/li&gt;
&lt;li&gt;Prefer the use of double quotes for strings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  File structure
&lt;/h3&gt;

&lt;p&gt;Files should be named &lt;code&gt;lower_snake_case.proto&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;All files should be ordered in the following manner:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;License header (if applicable)&lt;/li&gt;
&lt;li&gt;File overview&lt;/li&gt;
&lt;li&gt;Syntax&lt;/li&gt;
&lt;li&gt;Package&lt;/li&gt;
&lt;li&gt;Imports (sorted)&lt;/li&gt;
&lt;li&gt;File options&lt;/li&gt;
&lt;li&gt;Service (1 service per file)&lt;/li&gt;
&lt;li&gt;Messages (sorted in the same order of the RPCs and grouped under a comment&lt;code&gt;// region $RPCNAME&lt;/code&gt;)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BarRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BarResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// region Bar&lt;/span&gt;
    &lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;BarRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;BarResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: &lt;code&gt;// region&lt;/code&gt; comments are collapsible in Visual Code.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Packages
&lt;/h3&gt;

&lt;p&gt;Package names should be in lowercase. Package names should have unique names based on the project name and possibly based on the path of the file containing the protocol buffer type definitions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Message and field names
&lt;/h3&gt;

&lt;p&gt;Use CamelCase (with an initial capital) for message names – for example, &lt;code&gt;SongServerRequest&lt;/code&gt;. Use underscore_separated_names for field names (including oneof field and extension names) – for example, &lt;code&gt;song_name&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;SongServerRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;optional&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;song_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this naming convention for field names gives you accessors like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C++:
  const string&amp;amp; song_name() { ... }
  void set_song_name(const string&amp;amp; x) { ... }

Java:
  public String getSongName() { ... }
  public Builder setSongName(String v) { ... }

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

&lt;/div&gt;



&lt;p&gt;If your field name contains a number, the number should appear after the letter instead of after the underscore. For example, use &lt;code&gt;song_name1&lt;/code&gt; instead of &lt;code&gt;song_name_1&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Optional fields&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Consider the following proto3 message which defines the field &lt;code&gt;bar&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="kt"&gt;int32&lt;/span&gt; &lt;span class="na"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this definition, it is impossible to check whether &lt;code&gt;bar&lt;/code&gt; has been set to 0 or if no value has been set since the default value of &lt;code&gt;int32&lt;/code&gt; fields is 0. &lt;/p&gt;

&lt;p&gt;To allow you to make the difference, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;optional&lt;/span&gt; &lt;span class="kt"&gt;int32&lt;/span&gt; &lt;span class="na"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This exposes &lt;code&gt;hasBar()&lt;/code&gt; and &lt;code&gt;clearBar()&lt;/code&gt; (depending on the language) methods in the generated code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repeated fields
&lt;/h3&gt;

&lt;p&gt;Use pluralized names for repeated fields.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;repeated&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;repeated&lt;/span&gt; &lt;span class="n"&gt;MyMessage&lt;/span&gt; &lt;span class="na"&gt;accounts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Oneof&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Oneof is a wonderful example where a protobuf language feature helps to make gRPC APIs more intuitive. As an example, imagine we have a service method where users are able to change their profile picture, either from an URL or by uploading their own (small) image. Instead of doing this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Either set image_url or image_data. Setting both will result in an error.&lt;/span&gt;
&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;ChangeProfilePictureRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;image_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;bytes&lt;/span&gt; &lt;span class="na"&gt;image_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we can define the desired behavior directly into the message with oneof&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;ChangeProfilePictureRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;oneof&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;bytes&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not only is that much clearer for API consumers, but it is also easier to check which field has been set in the generated code. Keep in mind that oneof also allows that none of the fields has been set, meaning there is no need to introduce a separate &lt;code&gt;none&lt;/code&gt; field if the oneof should be optional.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexible Data
&lt;/h3&gt;

&lt;p&gt;If you do not know in advance the nature of the data you are going to receive from your consumer, we suggest you use the well know type Struct. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;StructTest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;google.protobuf.Struct&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enums
&lt;/h3&gt;

&lt;p&gt;Use CamelCase (with an initial capital) for enum type names and CAPITALS_WITH_UNDERSCORES for value names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;FooBar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;FOO_BAR_UNSPECIFIED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;FOO_BAR_FIRST_VALUE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;FOO_BAR_SECOND_VALUE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Each enum value should end with a semicolon, not a comma. Prefer prefixing enum values instead of surrounding them in an enclosing message. The zero value enum should have the suffix &lt;code&gt;UNSPECIFIED&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Note that names of enum entries must be unique in the whole package. Defining a second completely unrelated enum with an entry existing in the first will result in an error message because of how enums in C and C++ are implemented. To avoid this, prefix the enum entries with the enum name. Some code generators (ex. for C#) will remove these prefixes automatically so that the resulting code looks "clean" again.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Services
&lt;/h3&gt;

&lt;p&gt;If your &lt;code&gt;.proto&lt;/code&gt; defines an RPC service, you should use CamelCase (with an initial capital) for both the service name and any RPC method names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;FooService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;GetSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetSomethingRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetSomethingResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;ListSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListSomethingRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListSomethingResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Separate request and response messages&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We recommend that you create a separate message for each request and response. Name them &lt;code&gt;{MethodName}Request&lt;/code&gt; and &lt;code&gt;{MethodName}Reponse&lt;/code&gt;. This allows you to modify request and response messages for a single service method without introducing accidental changes to other methods. It is tempting to re-use messages and simply ignore fields that aren't needed. With time, this will result in a mess, since it isn't obvious what the API expects. Exceptions to this rule are usually made when returning a single, well-defined entity or when returning an empty message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;BookService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;CreateBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// don't do this&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;CreateBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;google.protobuf.Empty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// instead do this&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;ListBooks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListBooksRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListBooksResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// this is OK&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;GetBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetBookRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// this is also OK&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;DeleteBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeleteBookRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;google.protobuf.Empty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// this is also OK&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use the error system
&lt;/h3&gt;

&lt;p&gt;Do not return a simple confirmation to an endpoint that does not need to return any other data,  use &lt;code&gt;google.protobuf.Empty&lt;/code&gt; and trigger an error if needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Don't&lt;/span&gt;
&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;BookService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;DeleteBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeleteBookRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeleteBookResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;DeleteBookResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="na"&gt;deleted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Do &lt;/span&gt;
&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;BookService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;DeleteBook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeleteBookRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;google.protobuf.Empty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Don’t reinvent the wheel
&lt;/h3&gt;

&lt;p&gt;Use and abuse of the well-known types: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/protocol-buffers/docs/reference/google.protobuf"&gt;https://developers.google.com/protocol-buffers/docs/reference/google.protobuf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The empty message is already defined as &lt;code&gt;google.protobuf.Empty&lt;/code&gt;, so it doesn't make sense to define yet another empty message.&lt;/li&gt;
&lt;li&gt;Don’t try to redefine timestamp, there’s an existing type for it: &lt;a href="https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#timestamp"&gt;https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#timestamp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Don’t have one field in a struct influence the meaning of another&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Protocol buffer messages usually have multiple fields. These fields should always be independent of each other — you shouldn’t have one field influence the semantic meaning of another.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="c1"&gt;// don't do this!&lt;/span&gt;
&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;timestampIsCreated&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true means timestamp is created time,&lt;/span&gt;
                           &lt;span class="c1"&gt;// false means that it is updated time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This causes confusion — the client now needs to have special logic to know how to interpret one field based on another. Instead, use multiple fields, or use the protobuf “oneof” feature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="c1"&gt;// better, but still not ideal because the fields are mutually&lt;/span&gt;
&lt;span class="c1"&gt;// exclusive - only one will be set&lt;/span&gt;
&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="n"&gt;createdTimestamp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="n"&gt;updatedTimestamp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="c1"&gt;// this is ideal; one will be set, and that is enforced by protobuf&lt;/span&gt;
&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;oneof&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="n"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Linting
&lt;/h3&gt;

&lt;p&gt;We use protolint to lint the proto files. Please download and install protolint from &lt;a href="https://github.com/yoheimuta/protolint/releases"&gt;https://github.com/yoheimuta/protolint/releases&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git pre-commit hook&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can also enforce protolint to execute automatically before committing code using &lt;a href="https://pre-commit.com/"&gt;pre-commit&lt;/a&gt;. Install pre-commit, add a file &lt;code&gt;.pre-commit-config.yaml&lt;/code&gt;, and add this content to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt; repos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/yoheimuta/protolint&lt;/span&gt;
    &lt;span class="na"&gt;rev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;
    &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;protolint&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run: &lt;code&gt;pre-commit install&lt;/code&gt; in the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra recommendations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use CI to automatically double-check if your proto files still compile without error/warnings.&lt;/li&gt;
&lt;li&gt;Avoid large messages. gRPC is not designed for that. Details: &lt;a href="https://kreya.app/blog/grpc-best-practices/#large-messages"&gt;https://kreya.app/blog/grpc-best-practices/#large-messages&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Reuse channels. Creating a gRPC channel is a costly process, as it creates a new HTTP/2 connection. Details: &lt;a href="https://kreya.app/blog/grpc-best-practices/#reuse-channels"&gt;https://kreya.app/blog/grpc-best-practices/#reuse-channels&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/protocol-buffers/docs/style"&gt;https://developers.google.com/protocol-buffers/docs/style&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kreya.app/blog/grpc-best-practices/"&gt;https://kreya.app/blog/grpc-best-practices/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@akhaku/protobuf-definition-best-practices-87f281576f31"&gt;https://medium.com/@akhaku/protobuf-definition-best-practices-87f281576f31&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>grpc</category>
    </item>
    <item>
      <title>CDN on top of your website to increase your core web vitals</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Mon, 22 Nov 2021 07:02:42 +0000</pubDate>
      <link>https://dev.to/sonny_ad/cdn-on-top-of-your-website-to-increase-your-core-web-vitals-2g8c</link>
      <guid>https://dev.to/sonny_ad/cdn-on-top-of-your-website-to-increase-your-core-web-vitals-2g8c</guid>
      <description>&lt;p&gt;This is a long title, but it is on the point. &lt;/p&gt;

&lt;p&gt;I am going to show you how to set up AWS Cloudfront, the CDN solution of Amazon, in front of your AWS website.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The solution works if your website is hosted on a single server or if you have multiple instances behind a load balancer. In the case you host your website in a Kubernetes cluster, I don't have a solution at the moment, but feel free to leave your solution in the comments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why would you do that first?
&lt;/h2&gt;

&lt;p&gt;Because you will take profit of the very distributed CDN network of AWS! That means your website will be faster and available to a bigger audience. That relies on the good connectivity that AWS maintains inside its internal network. &lt;/p&gt;

&lt;p&gt;It means for example instead of serving your website from a central location: a server or a load balancer located in Singapore to a Canadian visitor. You will serve your website from the closest point in the CDN of AWS in Canada. &lt;/p&gt;

&lt;p&gt;And why that works? Because of the internal AWS network which is a lot more optimized than the regular internet. Using the regular internet routing to reach out to a website on the other side of the planet would never be as optimized. Internet neutrality won't favor your communication, and your Canadian ISP does not control routing up to Singapore. &lt;/p&gt;

&lt;p&gt;On top of that, increasing performances means increasing your core web vitals and your SEO!&lt;/p&gt;

&lt;h2&gt;
  
  
  Ok sounds great! So how do I do that?
&lt;/h2&gt;

&lt;p&gt;First, let's set up the CDN. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Cloudfront in AWS&lt;/li&gt;
&lt;li&gt;Click on &lt;code&gt;Create distribution&lt;/code&gt; 
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xeLR3dUD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreif5yckuedwv66na7nm76stwcl6vhjspugnigljudysxngc5gy6pvi" alt="Create a distribution" width="800" height="134"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Enter your origin&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;If you have a unique server, use the &lt;code&gt;Public IPv4 DNS&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IiyHBmut--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreiamnzwcvcd6turo6bd2dphvd3c2wjljftiwumycgwozl4wtlzeiy4" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IiyHBmut--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreiamnzwcvcd6turo6bd2dphvd3c2wjljftiwumycgwozl4wtlzeiy4" alt="EC2" width="372" height="216"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you use a load balancer, use the &lt;code&gt;DNS name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cTMlokaF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreida7w6ewuyymizxb7nofj57vzmsqbwgwvjuzio5yqdv3qu2xnwhei" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cTMlokaF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreida7w6ewuyymizxb7nofj57vzmsqbwgwvjuzio5yqdv3qu2xnwhei" alt="LB" width="678" height="192"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;In the section &lt;code&gt;Default cache behavior&lt;/code&gt;, &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I suggest you set &lt;code&gt;Redirect HTTP to HTTPS&lt;/code&gt;,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BBH0GPI1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreibwy2oicqxbm3g3vfbsqsurs5nyslei7ksuzcqfvotuawhiyk45ji" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BBH0GPI1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreibwy2oicqxbm3g3vfbsqsurs5nyslei7ksuzcqfvotuawhiyk45ji" alt="Redirect to HTTPS" width="317" height="167"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;(Optional)&lt;/em&gt; Set &lt;code&gt;Allowed HTTP methods&lt;/code&gt; to &lt;code&gt;GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE&lt;/code&gt; if your website have interactions and forms,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kWF3sUfe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreigcpvka3p3lq6re2x4xjg2urbwddfphld5oyqhos5ax36tanhro2u" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kWF3sUfe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreigcpvka3p3lq6re2x4xjg2urbwddfphld5oyqhos5ax36tanhro2u" alt="Get" width="471" height="267"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check &lt;code&gt;Cache policy and origin request policy&lt;/code&gt;, select &lt;code&gt;CachingDisabled&lt;/code&gt; as &lt;code&gt;Cache policy&lt;/code&gt; (because your website is dynamic so you don't want to cache), and select &lt;code&gt;AllViewer&lt;/code&gt; as &lt;code&gt;Origin request policy&lt;/code&gt; (this will allow cookies and query parameters to be transferred to your website origin).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P9RRuH7---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreielfidfe5fkdhsumtligjos4ygtyfxn6hubp5tjx2iep7b36rpqfm" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P9RRuH7---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreielfidfe5fkdhsumtligjos4ygtyfxn6hubp5tjx2iep7b36rpqfm" alt="Cache policy" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;In the section &lt;code&gt;Settings&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Check &lt;code&gt;Use all edge locations (best performance)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vsGdkeBu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreievsxvmkctxknrshjfsqio3vkjsgqitmqyxbnyci7nyif7fls6gne" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vsGdkeBu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreievsxvmkctxknrshjfsqio3vkjsgqitmqyxbnyci7nyif7fls6gne" alt="Edges" width="503" height="107"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on &lt;code&gt;Add item&lt;/code&gt; in &lt;code&gt;Alternate domain name (CNAME)&lt;/code&gt;  to add your domain name&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you want to have your root domain and www subdomain behind the CDN do it twice&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BEJKTPSJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreic7uwnreqzkk4yuptvqtyeodqn3xqs3o7lcix7vg3o524fsqwlljm" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BEJKTPSJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreic7uwnreqzkk4yuptvqtyeodqn3xqs3o7lcix7vg3o524fsqwlljm" alt="Example with two domains" width="701" height="227"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Select or request a certificate for the domain you entered previously&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the recommended &lt;code&gt;Security policy&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V-BCXtM0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreiheosj6okmge6a2ulrk656f6ypx2q7u7fglcfrl5uwi3wcg7f5k3i" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V-BCXtM0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.bloggu.io/ipfs/bafkreiheosj6okmge6a2ulrk656f6ypx2q7u7fglcfrl5uwi3wcg7f5k3i" alt="Security policy" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;code&gt;Create distribution&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Second, update your DNS record. Once your distribution is ready copy the &lt;code&gt;Distribution domain name&lt;/code&gt; of it, it should start by d. Then update the domain you entered at step 5b. &lt;/p&gt;

&lt;p&gt;And voilà.&lt;/p&gt;

&lt;p&gt;If you encounter any issues implementing it, leave comments. If you are using Kubernetes and you found a solution to do that, let me know I am curious about it.&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>HNRNPH2</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Mon, 08 Nov 2021 06:39:09 +0000</pubDate>
      <link>https://dev.to/sonny_ad/hnrnph2-1p6i</link>
      <guid>https://dev.to/sonny_ad/hnrnph2-1p6i</guid>
      <description>&lt;p&gt;Well, I guess the title does not really mean anything to you... It didn't for me too until about a year ago. &lt;/p&gt;

&lt;p&gt;Weirdly enough, I instantaneously memorized that string of characters, the first time I saw it. &lt;/p&gt;

&lt;p&gt;It finally puts a name on something that did not have a name before...&lt;/p&gt;




&lt;p&gt;My first daughter is born in 2015, an era without COVID, without too many troubles. Our first child with my wife. &lt;/p&gt;

&lt;p&gt;The beginning was tough, as with any kid! A lot of new habits to form and tiredness did not help. Thankfully, babies sleep a lot generally.  &lt;/p&gt;

&lt;p&gt;After several months, it was time to realize that something was abnormal. She was too quiet and not moving a lot. Not like any other baby...&lt;/p&gt;

&lt;p&gt;She got diagnosed with hypotonia. Which means low muscle tone. But it's a symptom, not a cause. &lt;/p&gt;

&lt;p&gt;This is when we felt into the unknown. And...&lt;/p&gt;

&lt;p&gt;When you don't know the cause, it's easy to feel guilty. It can make you question your entire life choices. &lt;/p&gt;

&lt;p&gt;When you don't know the cause, it's difficult to answer to your friends, your family, or even a random curious in the street, asking you what's wrong with her. &lt;/p&gt;

&lt;p&gt;When you don't know the cause, you have no idea what can happen, and there's nothing you can do to prepare for the future.&lt;/p&gt;




&lt;p&gt;But then we got results! She has a very rare genetic disease due to a gene mutation. On the gene HNRNPH2. And there are about 120 cases currently known in the world.&lt;/p&gt;

&lt;p&gt;She's a mutant, a little X-men! Except that in her case, she, unfortunately, did not get laser eyes or psychic powers. But developmental delay, hypotonia, and several other NOT cool things. &lt;/p&gt;

&lt;p&gt;But at least now, we know the cause. &lt;/p&gt;

&lt;p&gt;After meeting with the other parents and the researchers working on this rare disease, we know she has a future. &lt;/p&gt;

&lt;p&gt;And we can prepare better!&lt;/p&gt;

&lt;p&gt;As any parent, it's tough to know that the day you will leave that world, you will let your child on his own somehow. It's even worse with a disabled child. &lt;/p&gt;

&lt;p&gt;But I am optimistic. The research on her disease is pretty active, and funds have even been raised by the community of parents through the Yellow Brick Road Project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://yellowbrickroadproject.org/"&gt;https://yellowbrickroadproject.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see a lot of progress in the genetic field with mRNA vaccines, genetic therapies (for example with SMA), etc. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mda.org/disease/spinal-muscular-atrophy"&gt;https://www.mda.org/disease/spinal-muscular-atrophy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see a lot of progress in AI, robotics like Tesla Bot, etc. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.inclusivecitymaker.com/artificial-intelligence-accessibility-examples-technology-serves-people-disabilities/"&gt;https://www.inclusivecitymaker.com/artificial-intelligence-accessibility-examples-technology-serves-people-disabilities/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.tesla.com/AI"&gt;https://www.tesla.com/AI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see a lot of progress in transhumanist technologies like Neuralink, exoskeleton, etc. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://neuralink.com/"&gt;https://neuralink.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://exoskeletonreport.com/2021/09/biomotum-spark-robotic-exoskeleton-now-available-to-investigators-for-clinical-trials/"&gt;https://exoskeletonreport.com/2021/09/biomotum-spark-robotic-exoskeleton-now-available-to-investigators-for-clinical-trials/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All these things will contribute to supporting the life of my child, your child, our children, and grandchildren. &lt;/p&gt;

&lt;p&gt;But aside from sharing with you my investment thesis, and my optimism for the future, I want to invite you! &lt;/p&gt;

&lt;p&gt;If you are in a similar position with a different child, contribute to research. And the first step is to participate in natural studies. It is the basics and most important. Also of course donate if you can. And even more, be optimistic and invest in the technologies that could make a difference. &lt;/p&gt;

</description>
      <category>children</category>
      <category>life</category>
      <category>genetic</category>
    </item>
    <item>
      <title>🎙️ Software Engineers Podcast 🎙️ Episode 3 with Maximiliano Contieri</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Tue, 22 Jun 2021 03:09:26 +0000</pubDate>
      <link>https://dev.to/sonny_ad/software-engineers-podcast-episode-3-with-maximiliano-contieri-31k9</link>
      <guid>https://dev.to/sonny_ad/software-engineers-podcast-episode-3-with-maximiliano-contieri-31k9</guid>
      <description>&lt;p&gt;For this episode of &lt;strong&gt;Software Engineers&lt;/strong&gt;, I invited Maximiliano Contieri, Hashnode ambassador, and software engineer with 25 years of experience working in Argentina. &lt;/p&gt;

&lt;p&gt;You likely know Maximiliano from his well-known series about Code Smells. Series which he ported to Twitter as well recently:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/mcsee" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8ut8CKTs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://media.dev.to/cdn-cgi/image/width%3D150%2Cheight%3D150%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Fuser%252Fprofile_image%252F366059%252F69feb7c3-ab01-4bcd-a6f5-ec38e9300da3.jpeg" alt="mcsee"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/mcsee/code-smell-01-anemic-models-4dg2" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Code Smell 01 - Anemic Models&lt;/h2&gt;
      &lt;h3&gt;Maxi Contieri ・ Oct 20 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#codenewbie&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#oop&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#computerscience&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Or perhaps you read his productivity tips:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/mcsee" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8ut8CKTs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://media.dev.to/cdn-cgi/image/width%3D150%2Cheight%3D150%2Cfit%3Dcover%2Cgravity%3Dauto%2Cformat%3Dauto/https%253A%252F%252Fdev-to-uploads.s3.amazonaws.com%252Fuploads%252Fuser%252Fprofile_image%252F366059%252F69feb7c3-ab01-4bcd-a6f5-ec38e9300da3.jpeg" alt="mcsee"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/mcsee/16-simple-tips-to-boost-your-productivity-x10-1bf3" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;16 Simple Tips to Boost Your Productivity x10&lt;/h2&gt;
      &lt;h3&gt;Maxi Contieri ・ Dec 29 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#codenewbie&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#lifehacks&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;It was a lot of fun to chat with Maximiliano. We went through his long career. We discussed computer science. Maximiliano gave us his take on what is the main problem in software engineering (listen to the podcast to know what it is ^^). And ended up discussing a lot about AI, singularity, and Fermi's paradox. &lt;/p&gt;

&lt;p&gt;Maximiliano also shared his experience teaching at the university. And obviously I couldn't ask him about blogging and the reasons which brought him to start in the first place. &lt;/p&gt;

&lt;h2&gt;
  
  
  Time to listen now🎧
&lt;/h2&gt;

&lt;p&gt;Click below 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://shows.acast.com/software-engineers/episodes/maximiliano-contieri"&gt;https://shows.acast.com/software-engineers/episodes/maximiliano-contieri&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 If you liked the episode, follow Maximiliano on &lt;a href="https://twitter.com/mcsee1"&gt;Twitter&lt;/a&gt; and bookmark his blog: &lt;a href="https://maximilianocontieri.com"&gt;https://maximilianocontieri.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next episode on July 22nd!
&lt;/h2&gt;

</description>
      <category>podcast</category>
      <category>computerscience</category>
      <category>career</category>
    </item>
    <item>
      <title>How I set up a wiki for "Game of Rôles", the French better "Critical Role"</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Tue, 15 Jun 2021 04:58:53 +0000</pubDate>
      <link>https://dev.to/sonny_ad/how-i-set-up-a-wiki-for-game-of-roles-the-french-better-critical-role-4nmj</link>
      <guid>https://dev.to/sonny_ad/how-i-set-up-a-wiki-for-game-of-roles-the-french-better-critical-role-4nmj</guid>
      <description>&lt;p&gt;There is a show I love on Twitch on the channel of &lt;a href="https://www.twitch.tv/mistermv"&gt;MisterMV&lt;/a&gt;: Game of Rôles. It is an actual play of an original table RPG created by &lt;a href="https://www.fibretigre.com/"&gt;FibreTigre&lt;/a&gt;. To help the show, I decided at the time to create a wiki for it: &lt;a href="https://gameofroles.wiki"&gt;https://gameofroles.wiki&lt;/a&gt;. And here is how I did it.&lt;/p&gt;

&lt;p&gt;Prerequisites: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;A server with yourdomain.com already pointing at it&lt;/li&gt;
&lt;li&gt;5-10 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everybody knows Wikipedia. But few know that Wikipedia is actually running on open-source software. The Wikimedia Foundation develops its own wiki engine. And they use it for all their projects, including Wikipedia, Wiktionary, and others. This wiki engine is named &lt;a href="https://en.wikipedia.org/wiki/MediaWiki"&gt;MediaWiki&lt;/a&gt;. That being said now, that's what we are going to use here to set up our own wiki :-)&lt;/p&gt;

&lt;p&gt;First, you need a server with Docker installed on it. So obviously I would recommend a Linux server for that matter. For example, Digital Ocean proposes a Droplet image with Docker preinstalled on Ubuntu. With a couple of clicks, you can get a Droplet setup with Ubuntu and Docker ready to go. AWS and others have likely similar images in their inventory too. &lt;/p&gt;

&lt;p&gt;In Docker Hub, you can find this Docker image: &lt;a href="https://hub.docker.com/mediawiki/"&gt;https://hub.docker.com/mediawiki/&lt;/a&gt;. This is the official docker image from the Wikimedia Foundation itself. This is definitely what we want to use. &lt;/p&gt;

&lt;p&gt;Then, considering your wiki project, decide whether you need a MySQL-like database or the default embedded SQLite. In my case, I decided to use SQLite. Why? I knew the community watching the show was not huge. Hence, I did not need the database to scalable, and a simple SQLite is pretty enough. The show had regularly 2-4K viewers at the time I created the wiki in 2018. Actually nowadays in 2021, it has 16-20K viewers. And the wiki is still standing pretty well. &lt;/p&gt;

&lt;p&gt;Now to warn you, there's a little trick to deploy your MediaWiki with Docker. First, create a folder wherever you want to store all the files related to the wiki. Then, start the wiki. Visit your wiki at &lt;a href="http://yourdomain.com"&gt;http://yourdomain.com&lt;/a&gt;. Do the setup. And download the &lt;code&gt;LocalSettings.php&lt;/code&gt; generated for you. &lt;/p&gt;

&lt;p&gt;Here is the code I used to start the wiki:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create the folder&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;wiki&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;wiki
&lt;span class="c"&gt;# Start the wiki setup&lt;/span&gt;
docker run &lt;span class="nt"&gt;--name&lt;/span&gt; my-wiki &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; /wiki/data:/var/www/data &lt;span class="nt"&gt;-v&lt;/span&gt; /wiki/images:/var/www/html/images &lt;span class="nt"&gt;-v&lt;/span&gt; /wiki/extensions:/var/www/html/extensions  mediawiki
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have the file &lt;code&gt;LocalSettings.php&lt;/code&gt;, upload it into your wiki folder. Finally, delete the current container. And restart a new container with this &lt;code&gt;LocalSettings.php&lt;/code&gt; mounted, and you are ready to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; my-wiki
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"docker run --name my-wiki -d -v /wiki/data:/var/www/data -v /wiki/images:/var/www/html/images -v /wiki/extensions:/var/www/html/extensions -v /wiki/LocalSettings.php:/var/www/html/LocalSettings.php --restart=always mediawiki"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; start.sh
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x start.sh 
./start.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command to start the container is kinda long. So I suggest saving it in a &lt;code&gt;start.sh&lt;/code&gt; to avoid typing it ever again. &lt;/p&gt;

&lt;p&gt;Voilà, then visit yourdomain.com and your wiki is ready to use. &lt;/p&gt;

</description>
      <category>docker</category>
      <category>wiki</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Become a Software Engineer!</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Mon, 07 Jun 2021 04:03:44 +0000</pubDate>
      <link>https://dev.to/sonny_ad/how-to-become-a-software-engineer-3714</link>
      <guid>https://dev.to/sonny_ad/how-to-become-a-software-engineer-3714</guid>
      <description>&lt;p&gt;I wanted to share my point of view on the question based on my personal experience. But better be clear straight away, it will take time! &lt;/p&gt;

&lt;p&gt;Prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A computer&lt;/li&gt;
&lt;li&gt;Perseverance &lt;/li&gt;
&lt;li&gt;A lot of time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are the steps I went through and that you should also:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Learn how to use a computer&lt;/strong&gt;. It may sound easy or obvious to everybody nowadays. Yet, I still encounter people sometimes asking me advice on how to learn to program and they don't even know how to make a screenshot. Here is a list of what are the essential things you need to be able to do with your computer: 

&lt;ul&gt;
&lt;li&gt; Copy/Paste &lt;em&gt;Obviously&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; Make screenshots &lt;em&gt;and optionally make video screen captures&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; Use the webcam and the microphone &lt;em&gt;Essential for communicating with others&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; Create an empty text file &lt;em&gt;to take notes for example&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; Make space on your hard disk &lt;em&gt;by cleaning junk files or others or backing up files on other storage space&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; Install and uninstall an application &lt;em&gt;you need tools to code&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; Organize your Documents folder &lt;/li&gt;
&lt;li&gt; Use an Office-like suite &lt;em&gt;Excel and Word at least are a must&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt; Print and scan &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learn how to use the internet&lt;/strong&gt;. You absolutely need to know how to find information on the network. The internet is built by computer scientists. And they are everywhere discussing, sharing, and helping other computer scientists. So you must know how to take profits from that.

&lt;ul&gt;
&lt;li&gt;Use Google&lt;/li&gt;
&lt;li&gt;Send emails and filter spam&lt;/li&gt;
&lt;li&gt;Register to a service&lt;/li&gt;
&lt;li&gt;Connect to Wi-Fi network&lt;/li&gt;
&lt;li&gt;Learn Markdown, HTML, CSS&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Think of something you would like to do&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Really think about it twice&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start to research. Collect resources on how to realize this idea and how others implemented similar ideas&lt;/strong&gt;. For me, it was a dynamic website. I was part of online communities and wanted to contribute. I made research and at the time, the stack WAMP was pretty popular to build websites. Almost every website was running with PHP. So I found this website with a lot of tutorials and documentation on PHP. I basically printed all the pages and started reading line by line the code in the examples. I remember it was difficult. I often couldn't understand. But with perseverance and forcing me into actually achieving something, at some point... I started to feel more familiar and confident. Also, leave the most difficult concepts aside, start small. In my case, I remember deciding to leave PHP4 and OOP aside to focus on using PHP3 which was still popular, easier to use, and procedural only. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Do it&lt;/strong&gt;. Based on your research and collection of resources, do it. Do that thing you wanted to do. For me, as I mentioned it was a PHP website. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Release it&lt;/strong&gt;. I made a lot of websites, instead of doing my homework TBH haha. I learned two things from that. First, releasing early or at least getting feedback early is important. I abandoned several projects after spending a lot of time on them trying to make them perfect. Because after showing them I was not getting any traction or excitement from the client or users. Second, getting adoption and seeing users actually using your product is just amazing! On top of that, you will start to get recognition. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;While(true) repeat();&lt;/strong&gt; If you passed step 5 you know what I mean. you understand that now it's a matter of repeating the process. Learn, gather resources, experiment, develop, release, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;(Optional) Go to University or Training class&lt;/strong&gt;. As someone who has a Master of Computer Sciences, I can tell you that this is really &lt;em&gt;optional&lt;/em&gt;. You can be a software engineer without going to universities, as long as you are disciplined enough and practicing a lot. Practicing, not just making tutorials! Don't fall into the &lt;a href="https://dev.to/andrewlundydev/how-to-get-out-of-or-completely-avoid-the-tutorial-trap-m27"&gt;Tutorial Trap&lt;/a&gt;. What universities could bring you though is a network (people you may work with/for), the discipline you may lack, a greater general culture, and improvement of your soft skills. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are a software engineer, share your path in the comments! Your one piece of advice! &lt;br&gt;
If you are willing to be to become a software engineer, you know how now. Don't hesitate to share your work and difficulties in the comments below or the community in general! &lt;/p&gt;




&lt;p&gt;&lt;span&gt;Photo by &lt;a href="https://unsplash.com/@serge_k?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Serge Kutuzov&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/superhero?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>codenewbie</category>
      <category>computerscience</category>
      <category>learning</category>
    </item>
    <item>
      <title>Here is how I found my path as a software engineer</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Mon, 31 May 2021 04:58:57 +0000</pubDate>
      <link>https://dev.to/sonny_ad/here-is-how-i-found-my-path-as-a-software-engineer-29of</link>
      <guid>https://dev.to/sonny_ad/here-is-how-i-found-my-path-as-a-software-engineer-29of</guid>
      <description>&lt;p&gt;As a teenager in the 90s, I was living in a small and cold town in France. I was doing not much of my life: going to school, playing video games, watching TV, ... My family’s revenue was pretty modest, so I never had the latest fancy game consoles or toys. On top of that, I was not very confident, and I was going on a bad path in terms of weight which accentuated my lack of self-confidence.&lt;/p&gt;

&lt;p&gt;Early high school, both my parents went through depression. My mom got sick and had to stay in bed for months. It hit me too. I failed my year. Life was pretty pointless at the time. Everything was falling apart, and I couldn’t do anything. I felt lonely and powerless. I felt I was not belonging here.&lt;/p&gt;

&lt;p&gt;Then I got fed up with the situation, and I decided to change that. At that time the Internet has been my greatest companion. This window on the world allowed me to get in touch with people from all around the world. I started to be part of communities and bounded with several people remotely. This brought me to think that I could be part of that world. And that I started to feel that I wanted to contribute. This is where I decided to try to make websites for the communities I was part of.&lt;/p&gt;

&lt;p&gt;At the time, the easiest to make websites was with PHP. And this is what I just did. I started my journey by documenting myself. I gathered information and good resources. On a second step, I printed tutorials and documentation on paper, and I read them carefully. I tried to read everything, line by line, to understand the essence of each concept. But I still left some difficult concepts aside like object-oriented programming (OOP). On a third step, I started to experiment with all the theoretical knowledge I acquired.&lt;/p&gt;

&lt;p&gt;The last and final step that really got me into the rabbit hole of programming has been to contribute to the world. I made websites for online communities I participated in. And I started to get something amazing: recognition. I was not just a random name, a random loser. I was the programmer or the webmaster.&lt;/p&gt;

&lt;p&gt;Sometimes in life, you feel like you don’t belong here. Sometimes in life, you feel lost and the world around you is pulling you down even more. But don't forget, there are so many exciting things, and whenever you find one thing you really enjoy you should try to stick to it. It can be programming like me, it can be dancing, it can be writing, it can be anything. Go through the obstacles. Pull yourself up. Be the best of yourself. Contribute to that world. At some point, you will get recognition, and you will understand that you belong here. You just hadn’t realized it yet.&lt;/p&gt;




&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@stephenleo1982?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Stephen Leonardi&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/path?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blog</category>
      <category>career</category>
      <category>thoughts</category>
    </item>
    <item>
      <title>🎙️ Software Engineers Podcast 🎙️ Episode 2 with Sean Austin</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Mon, 24 May 2021 06:42:47 +0000</pubDate>
      <link>https://dev.to/sonny_ad/software-engineers-podcast-episode-2-with-sean-austin-56gf</link>
      <guid>https://dev.to/sonny_ad/software-engineers-podcast-episode-2-with-sean-austin-56gf</guid>
      <description>&lt;p&gt;For this episode of &lt;strong&gt;Software Engineers&lt;/strong&gt;, I invited Sean Austin, the VP of Engineering of  &lt;a href="https://www.superevilmegacorp.com/"&gt;Super Evil Megacorp&lt;/a&gt;, a AAA mobile-first indie game studio based in San Mateo, California. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6f05ND_L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gist.githubusercontent.com/PxSonny/b7a8d9d66af447513602ea2f13fcf8ec/raw/dc48ba1f0b59974b866351d764bc6c430ea74920/semc-games.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6f05ND_L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://gist.githubusercontent.com/PxSonny/b7a8d9d66af447513602ea2f13fcf8ec/raw/dc48ba1f0b59974b866351d764bc6c430ea74920/semc-games.svg" alt="Super Evil Megacorp Games" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To be transparent, I had the chance to work with Sean for several years. And I have always been very impressed by &lt;strong&gt;his great work ethics, dedication, and broad knowledge&lt;/strong&gt;. And he is one of the first person I thought of when preparing this podcast! &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sean was not destined to be in computer science at first. He originally wanted to pursue a career in physics, and willing to be a funny physics high-school teacher. But in our discussion, he explained what made him change his mind. Spoiler: it includes video games😉.&lt;/p&gt;

&lt;p&gt;We also go through his role and responsibilities at Super Evil Megacorp. "&lt;em&gt;Being the VP of Engineering is about creating the best home for engineering talent,&lt;/em&gt;" explained Sean. A role that is not tech-oriented, but people-oriented. &lt;/p&gt;

&lt;h3&gt;
  
  
  The E.V.I.L. Engine
&lt;/h3&gt;

&lt;p&gt;Super Evil Megacorp is using a custom game engine named E.V.I.L. engine. &lt;br&gt;
I was also curious to ask him questions about the origin and reasons for such a choice. &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Q8VPyAdPtAw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Sean emphasized by controlling the entire codebase, they can create a very tailored experience for their games. It is not possible with commercial engines which are often proprietary and generic to fit the most use cases possible. &lt;/p&gt;

&lt;p&gt;In short, we also talked about several others subjects like transition through COVID-19, managing remote teams, parenting and video games, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  But enough, time to listen now 👇
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://shows.acast.com/software-engineers/episodes/sean-austin"&gt;https://shows.acast.com/software-engineers/episodes/sean-austin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 If you liked the episode and are interested to work at Super Evil Megacorp with Sean! Check out their career page: &lt;a href="https://www.superevilmegacorp.com/careers/"&gt;https://www.superevilmegacorp.com/careers/&lt;/a&gt;. And if you want more info or play Catalyst Black, click here: &lt;a href="https://catalystblack.com/"&gt;https://catalystblack.com/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next episode on June 22nd!
&lt;/h2&gt;

</description>
      <category>podcast</category>
      <category>career</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Build an online store without dealing with WordPress unreliability</title>
      <dc:creator>Sonny Alves Dias</dc:creator>
      <pubDate>Mon, 17 May 2021 03:48:27 +0000</pubDate>
      <link>https://dev.to/sonny_ad/build-an-online-store-without-dealing-with-wordpress-unreliability-1ppm</link>
      <guid>https://dev.to/sonny_ad/build-an-online-store-without-dealing-with-wordpress-unreliability-1ppm</guid>
      <description>&lt;p&gt;The couple WordPress and WooCommerce have been for too long the favorite solution to deploy quickly an online shop and start making revenue. Now every developer who encountered WordPress knows its many drawbacks. In this article, we will explain how we overcame WordPress's unreliability by turning it basically into a backend service. &lt;/p&gt;

&lt;h2&gt;
  
  
  First of all why WordPress is so popular?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;WordPress is &lt;strong&gt;easy to deploy&lt;/strong&gt;, there are plenty of hosting solution that offers WordPress directly but also PHP hosting are still very commonly available, i.e. &lt;a href="//wordpress.com"&gt;wordpress.com&lt;/a&gt;, &lt;a href="https://www.dreamhost.com/wordpress/"&gt;DreamHost&lt;/a&gt;, &lt;a href="https://www.bluehost.com/wordpress/wordpress-hosting"&gt;BlueHost&lt;/a&gt;, etc.&lt;/li&gt;
&lt;li&gt;There are &lt;strong&gt;a lot of plugins available&lt;/strong&gt;, and you can develop your plugin as well.&lt;/li&gt;
&lt;li&gt;There are &lt;strong&gt;many pretty good looking themes&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It is &lt;strong&gt;user-friendly&lt;/strong&gt;, especially to non-technical people.&lt;/li&gt;
&lt;li&gt;It has a &lt;strong&gt;huge community&lt;/strong&gt; and numerous learning resources online.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Then what's the problem with WordPress?
&lt;/h2&gt;

&lt;p&gt;His popularity also brought weaknesses: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;His huge community, mostly composed of non-technical users, generated a &lt;strong&gt;huge amount&lt;/strong&gt; of non-official learning &lt;strong&gt;resources&lt;/strong&gt; that are either &lt;strong&gt;outdated or of poor quality&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It also attracted &lt;strong&gt;a lot of malicious and scammy developers&lt;/strong&gt; to make their own plugins polluting the plugins market. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A lot of security holes also because WordPress users are not often non-technical and likely not apply security patches to their setup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On a technical side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;WordPress is &lt;strong&gt;too flexible&lt;/strong&gt; in the sense that to implement something it can be done on different layers: in the PHP source code, in the WordPress page/post editor, or in the theme configuration. It leads non-technical users to not adopt clear conventions and let them try out different tricks here and there resulting in a very hacky usage of the CMS. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WordPress is also &lt;strong&gt;unreliable&lt;/strong&gt; because of how updates are conducted, plugins and themes are simply overwritten thus losing any local changes (generally tailored-changes made to customize plugins and themes).&lt;br&gt;
To be precise, WordPress has a child theme system that allows defining changes that will be applied on top of a parent that helps to prevent some of the local changes to be overwritten. But it is not well integrated or either user-friendly.&lt;br&gt;
For webmasters, especially amateur ones, it is too risky to update plugins, themes, and WordPress itself because they are afraid of losing their changes and/or even break their entire website. Hence WordPress websites are de facto never updated.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to overcome the unreliability of WordPress?
&lt;/h2&gt;

&lt;p&gt;Let's imagine we could use WordPress and WooCommerce for what they worth only which are a blog system and an online store system. &lt;br&gt;
The first thing we probably want to do is to remove the risks that are the plugins, and only install the minimum, WooCommerce. &lt;br&gt;
The second thing we want to do is to get rid of the themes too. To do that we started to look at Headless WordPress and found out about the WordPress API and the WooCommerce API. &lt;/p&gt;

&lt;h3&gt;
  
  
  WordPress API
&lt;/h3&gt;

&lt;p&gt;WordPress, since its version &lt;code&gt;4.7.0&lt;/code&gt; (released in December 2016), offers a RESTful API  that is to say 13 years after its first release in 2003 and only 3 years ago from the time of the writing of this article. &lt;/p&gt;

&lt;p&gt;The API allows interactions with WordPress using JSON (JavaScript Object Notation) format only. While for requesting data from it, it does not require authentication if you wish to edit, create, or delete information you will need to authenticate. It is worth noting that WordPress only supports Cookie Authentication natively, but some plugins allow for more types. &lt;/p&gt;

&lt;p&gt;The  consumption of the API is pretty straight-forward and allows you to retrieve any data pretty easily. The root endpoint is mounted on &lt;code&gt;/wp-json/&lt;/code&gt;. From there you will be able to see all the available sub-endpoints. &lt;br&gt;
But let's dig into some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To retrieve the list of posts (articles) on your blog you can run a GET request at the endpoint &lt;code&gt;/wp-json/wp/v2/posts/&lt;/code&gt; you will then receive the first page of the posts in JSON format. Complete example details are available here: &lt;a href="https://developer.wordpress.org/rest-api/reference/posts/#list-posts"&gt;https://developer.wordpress.org/rest-api/reference/posts/#list-posts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;To retrieve a media that was used in a post you can run a GET request against the endpoint &lt;code&gt;/wp-json/wp/v2/media/&amp;lt;id&amp;gt;&lt;/code&gt;, replace &lt;code&gt;&amp;lt;id&amp;gt;&lt;/code&gt; by the actual id of the media. Complete example details are available here: &lt;a href="https://developer.wordpress.org/rest-api/reference/media/#retrieve-a-media-item"&gt;https://developer.wordpress.org/rest-api/reference/media/#retrieve-a-media-item&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;For more examples and details, the official documentation for the WordPress REST API is available at that address: &lt;a href="https://developer.wordpress.org/rest-api/"&gt;https://developer.wordpress.org/rest-api/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  WooCommerce API
&lt;/h3&gt;

&lt;p&gt;WooCoomerce has been offering a RESTful API to its users for a longer time than WordPress. The first WooCommerce API was released with WooCommerce &lt;code&gt;2.1.0&lt;/code&gt; in February 2014 which is almost three years before WordPress' REST API.&lt;/p&gt;

&lt;p&gt;It is more commonly used. For example, when you set up your logistics with ShipBob they will use the API to retrieve your shop orders automatically. &lt;/p&gt;

&lt;p&gt;It is important to note that the original WooCommerce API after several updates has been deprecated and relabeled Legacy API. WooCommerce decided to fully rework their API to extend the WordPress API directly after the release of the latter. &lt;/p&gt;

&lt;p&gt;We recommend to use the latest version which is at the time of this article is the WooCommerce API v3 (not the Legacy one but the current one).&lt;/p&gt;

&lt;p&gt;When using the API whether the Legacy or the current one, you need to create first an API token in the settings of WooCommerce steps to follow are described here: &lt;a href="https://docs.woocommerce.com/document/woocommerce-rest-api/"&gt;https://docs.woocommerce.com/document/woocommerce-rest-api/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then to find out how to use the tokens to authenticate please go here: &lt;a href="https://woocommerce.github.io/woocommerce-rest-api-docs/#authentication"&gt;https://woocommerce.github.io/woocommerce-rest-api-docs/#authentication&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally here are some examples: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To create an order, you can run a POST request against that endpoint &lt;code&gt;/wp-json/wc/v3/orders&lt;/code&gt; with a JSON object describing your order. Complete example details are available here: &lt;a href="https://woocommerce.github.io/woocommerce-rest-api-docs/#create-an-order"&gt;https://woocommerce.github.io/woocommerce-rest-api-docs/#create-an-order&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;To retrieve the list of products, you can run a GET request against that endpoint &lt;code&gt;/wp-json/wc/v3/products&lt;/code&gt;. Complete example details are available here: &lt;a href="https://woocommerce.github.io/woocommerce-rest-api-docs/#list-all-products"&gt;https://woocommerce.github.io/woocommerce-rest-api-docs/#list-all-products&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;For more examples and details, the official documentation for the WooCommerce REST API is available at that address: &lt;a href="https://woocommerce.github.io/woocommerce-rest-api-docs/#introduction"&gt;https://woocommerce.github.io/woocommerce-rest-api-docs/#introduction&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The next step
&lt;/h3&gt;

&lt;p&gt;Now that we know how to use WordPress API and WooCommerce API, there are two things we need to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WooCommerce API needs authentication, so how are we going to keep our API tokens secret?&lt;/li&gt;
&lt;li&gt;And by using only the API, we are cutting ourselves from the payment process of WooCommerce. It means we will have to process payments ourselves outside of WordPress/WooCommerce.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why we went with the architecture below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jFEChFPX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://pixelmatic.github.io/assets/posts/muted-wordpress/architecture_wordpress_muted.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jFEChFPX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://pixelmatic.github.io/assets/posts/muted-wordpress/architecture_wordpress_muted.svg" alt="Muted Wordpress" width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The front-end is running an Angular app written in Typescript.&lt;/li&gt;
&lt;li&gt;The middleware is a Node.js app written in Typescript, it holds the API tokens and implements the necessary things for processing payments too, for example, we usually implement &lt;a href="https://stripe.com/docs/payments/accept-a-payment"&gt;Stripe&lt;/a&gt; and &lt;a href="https://globee.com/docs/payment-api/v1"&gt;GloBee&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The back-end and back-office is our WordPress.&lt;/li&gt;
&lt;li&gt;The CDN and storage are respectively running on AWS CloudFront and AWS S3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It means that with that architecture when we want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To post an article, we add a post in WordPress, and we retrieve it through the WordPress API via our middleware,&lt;/li&gt;
&lt;li&gt;To host a picture, we simply upload it into WordPress media, and retrieve it with the CDN link,&lt;/li&gt;
&lt;li&gt;To do some changes in some parts of our website, we edit a WordPress page and retrieve the content of the page dynamically through the WordPress API via our middleware,&lt;/li&gt;
&lt;li&gt;To add a product, we simply add it into WooCommerce, &lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that to automate the upload of the media to S3 in WordPress we installed the plugin &lt;a href="https://wordpress.org/plugins/amazon-s3-and-cloudfront/"&gt;WP Offload Media Lite&lt;/a&gt;. Making the total count of our plugins installed into WordPress to only two: &lt;em&gt;WooCommerce&lt;/em&gt; and &lt;em&gt;WP Offload Media Lite&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Difficulties Encountered
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The WordPress API is slow: &lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/45421976/wordpress-rest-api-slow-response-time/45425091#45425091"&gt;https://stackoverflow.com/questions/45421976/wordpress-rest-api-slow-response-time/45425091#45425091&lt;/a&gt;&lt;br&gt;
Though a plugin seems to help for that, by caching answers from the API:&lt;br&gt;
&lt;a href="https://wordpress.org/plugins/wp-rest-cache/"&gt;https://wordpress.org/plugins/wp-rest-cache/&lt;/a&gt; (We haven't tested it yet).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To keep WordPress fully hidden behind our middleware (and avoid curious eyes), we had to filter all the links returned by WordPress to make sure they either use the CDN, use a vetted domain, or simply don't appear in the API calls answers. For that, the plugin &lt;em&gt;WP Offload Media Lite&lt;/em&gt; helps a lot because it updates every media link to use the CDN. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;For the company I work, to be able to fully customize the front-end as we want, while also keeping our website more secure is a major win for us. Admittedly the infrastructure needs are bigger but the maintainability and stability in the long term are higher. &lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>webdev</category>
      <category>microservices</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
