<?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: Dang Hoang Nhu Nguyen</title>
    <description>The latest articles on DEV Community by Dang Hoang Nhu Nguyen (@nguyendhn).</description>
    <link>https://dev.to/nguyendhn</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%2F524144%2Fe42c6c13-4c38-4498-b340-f085fa7e673c.png</url>
      <title>DEV Community: Dang Hoang Nhu Nguyen</title>
      <link>https://dev.to/nguyendhn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nguyendhn"/>
    <language>en</language>
    <item>
      <title>[BTY] Day 14: How to send notification from your Python app to Slack?</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Mon, 21 Feb 2022 16:03:27 +0000</pubDate>
      <link>https://dev.to/nguyendhn/how-to-config-to-send-notification-from-your-python-app-to-slack-13f8</link>
      <guid>https://dev.to/nguyendhn/how-to-config-to-send-notification-from-your-python-app-to-slack-13f8</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was for 18.02.2022&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A lot of time, you want to be noticed when something happens to your application on the server, so you can take action as soon as possible.&lt;/p&gt;

&lt;p&gt;Sending Slack messages to a channel in case of exceptions (with phone notifications, emails included in settings) is one of the simplest ways I found to deal with the mentioned issue.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: This is a legacy custom integration - an outdated way for teams to integrate with Slack. You may visit the Slack documentation for update and the modern way to do so.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create new &lt;a href="https://slack.com" rel="noopener noreferrer"&gt;Slack&lt;/a&gt; workspace
&lt;/h3&gt;

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

&lt;h3&gt;
  
  
  2. Setting up
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create new channel ⇒ Right click and select &lt;code&gt;Open channel details&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2gc30i7ftionxp5g7dv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2gc30i7ftionxp5g7dv.png" alt="create new slack channel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrations &amp;gt; Add an App&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Search and select &lt;code&gt;Incoming Webhooks&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Add Incoming WebHooks to the target channel (e.g #test-notification)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhh4kd3mcsqc9xy580rwu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhh4kd3mcsqc9xy580rwu.png" alt="add app to target channel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup Instructions (from the documentation)
&lt;/h2&gt;

&lt;p&gt;We'll guide you through the steps necessary to configure an Incoming Webhook so you can start sending data to Slack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhook URL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://hooks.slack.com/services/xxxxxxxxxxxxxxxxxxxxx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sending Messages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You have two options for sending data to the Webhook URL above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send a JSON string as the &lt;code&gt;payload&lt;/code&gt; parameter in a POST request&lt;/li&gt;
&lt;li&gt;Send a JSON string as the body of a POST request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a simple message, your JSON payload could contain a &lt;code&gt;text&lt;/code&gt; property at minimum. This is the text that will be posted to the channel.&lt;/p&gt;

&lt;p&gt;A simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    payload={"text": "This is a line of text in a channel.\nAnd this is another line of text."}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will be displayed in the channel as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fa.slack-edge.com%2F80588%2Fimg%2Fintegrations%2Fincoming_webhook_example1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fa.slack-edge.com%2F80588%2Fimg%2Fintegrations%2Fincoming_webhook_example1.png" alt="https://a.slack-edge.com/80588/img/integrations/incoming_webhook_example1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding links&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To create a link in your text, enclose the URL in &lt;strong&gt;&amp;lt;&amp;gt;&lt;/strong&gt; angle brackets. For example: &lt;code&gt;payload="text": ""&lt;/code&gt; will post a clickable link to &lt;a href="https://slack.com" rel="noopener noreferrer"&gt;https://slack.com&lt;/a&gt;. To display hyperlinked text instead of the actual URL, use the &lt;strong&gt;pipe&lt;/strong&gt; character, as shown in this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    payload={"text": "A very important thing has occurred! &amp;lt;https://alert-system.com/alerts/1234|Click here&amp;gt; for details!"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will be displayed in the channel as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fa.slack-edge.com%2F80588%2Fimg%2Fintegrations%2Fincoming_webhook_example2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fa.slack-edge.com%2F80588%2Fimg%2Fintegrations%2Fincoming_webhook_example2.png" alt="https://a.slack-edge.com/80588/img/integrations/incoming_webhook_example2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customized Appearance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can customize the &lt;strong&gt;name&lt;/strong&gt; and &lt;strong&gt;icon&lt;/strong&gt; of your Incoming Webhook in the &lt;strong&gt;Integration Settings&lt;/strong&gt; section below.However, you can override the displayed name by sending &lt;code&gt;"username": "new-bot-name"&lt;/code&gt; in your JSON payload. You can also override the bot icon either with &lt;code&gt;"icon_url": "https://slack.com/img/icons/app-57.png"&lt;/code&gt; or &lt;code&gt;"icon_emoji": ":ghost:"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Channel Override&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Incoming webhooks have a default channel, but it can be overridden in your JSON payload. A public channel can be specified with &lt;code&gt;"channel": "#other-channel"&lt;/code&gt;, and a Direct Message with &lt;code&gt;"channel": "@username"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Putting this all together, here is a sample &lt;a href="http://curl.haxx.se/" rel="noopener noreferrer"&gt;curl&lt;/a&gt; request for posting to a channel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    curl -X POST --data-urlencode "payload={\"channel\": \"#test-notification\", \"username\": \"webhookbot\", \"text\": \"This is posted to #test-notification and comes from a bot named webhookbot.\", \"icon_emoji\": \":ghost:\"}" https://hooks.slack.com/services/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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will be displayed in the channel as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fa.slack-edge.com%2F80588%2Fimg%2Fintegrations%2Fincoming_webhook_example3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fa.slack-edge.com%2F80588%2Fimg%2Fintegrations%2Fincoming_webhook_example3.png" alt="https://a.slack-edge.com/80588/img/integrations/incoming_webhook_example3.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Python Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;loguru&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SlackWebhookBot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;webhook_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;channel_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test-notification&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;bot_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;guardian&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;bot_emoji&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:guardsman:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Class to send messages to a provided Slack webhook URL.

            You can read more about Slack&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s Incoming Webhooks here:
                https://api.slack.com/messaging/webhooks

            Args:
                webhook_url: The webhook URL to send a message to.  Typically
                    formatted like &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://hooks.slack.com/services/...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.

            Kwargs:
                timeout: Number of seconds before the request will timeout.
                    This is used to prevent a hang and is set to a default
                    value of 15 seconds.
            &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;webhook_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webhook_url&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;channel_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;channel_name&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bot_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bot_name&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bot_emoji&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bot_emoji&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&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;Content-Type&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;application/json&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_notification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Sends a message to the webhook URL.

            Per the Slack Incoming Webhook example.  The body of the request
            (for plain text) should be formatted as follows:
                `{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, World!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;}`

            Args:
                message: Plain text string to send to Slack.

            Returns:
                A boolean representing if the request was successful.
            &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
            &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
            &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&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;channel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;channel_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bot_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;icon_emoji&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bot_emoji&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;webhook_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Timeout occurred when trying to send message to Slack.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Error occurred when communicating with Slack: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
                &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Successfully sent message to Slack.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;SLACK_WEBHOOK_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://hooks.slack.com/services/xxxxxxxxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;slack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SlackWebhookBot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;slack_test_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[TESTING] Sending this warning message when we have any problems.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_notification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;slack_test_message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>betterthanyesterday</category>
    </item>
    <item>
      <title>[BTY] Day 13: Yopass - Share Secrets Securely</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Mon, 21 Feb 2022 15:46:32 +0000</pubDate>
      <link>https://dev.to/nguyendhn/yopass-share-secrets-securely-3pk2</link>
      <guid>https://dev.to/nguyendhn/yopass-share-secrets-securely-3pk2</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was for 17.02.2022&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yopass is a project for sharing secrets in a quick and secure manner.&lt;/p&gt;

&lt;p&gt;The message is encrypted/decrypted locally in the browser and then sent to yopass without the decryption key which is only visible once during encryption, yopass then returns a one-time URL with specified expiry date.&lt;/p&gt;

&lt;p&gt;Because it's an open-source project, you can deploy it anywhere on your own. It has full transparency with the possibility to audit and submit features.&lt;/p&gt;

&lt;p&gt;Check it here: &lt;a href="https://yopass.se/"&gt;https://yopass.se/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x1jQh6Zw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q8onmy318jcfm4uqqqqd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x1jQh6Zw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q8onmy318jcfm4uqqqqd.png" alt="Yopass" width="880" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>betterthanyesterday</category>
      <category>tooling</category>
    </item>
    <item>
      <title>[BTY] Day 6-12: Read Practical MLOps book</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Wed, 16 Feb 2022 14:46:04 +0000</pubDate>
      <link>https://dev.to/nguyendhn/bty-day-6-12-read-the-book-practical-mlops-5g5i</link>
      <guid>https://dev.to/nguyendhn/bty-day-6-12-read-the-book-practical-mlops-5g5i</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was for 09.02.2022 to 15.02.2022&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I have finished the book &lt;strong&gt;Practical MLOps: Operationalizing Machine Learning Models&lt;/strong&gt;, written by Noah Gift. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.amazon.com/Practical-MLOps-Operationalizing-Machine-Learning/dp/1098103017/"&gt;https://www.amazon.com/Practical-MLOps-Operationalizing-Machine-Learning/dp/1098103017/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For me, this book has given me a comprehensive understanding of operating ML systems in general, with real-world use cases and sample code. Few sections I had skipped because those chapters are designed for specific cloud services that I have not planned to use in the near future. &lt;/p&gt;

&lt;p&gt;However, the interesting point is, this book also has a lot of appendixes that made me feel excited. To have a successful career and a balanced lifestyle, technical knowledge with a 9-to-5 job is not enough. You have to know about how to grow yourself in terms of hard skills and soft skills: how to manage a project, how to do a side project to create your technical portfolio, how to learn new things, how to market yourself, how to invest and have a passive income, how to keep healthy by eating clean food or doing exercise, ...&lt;/p&gt;

&lt;p&gt;I will post my keynotes on this book soon. Recommend anyone to read this book if you're looking for a guide to build an ML system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4BzS-qM5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r5z81cr9xmuqvcdjsc7v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4BzS-qM5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r5z81cr9xmuqvcdjsc7v.png" alt="Practical MLOps" width="381" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>betterthanyesterday</category>
      <category>reading</category>
      <category>mlops</category>
    </item>
    <item>
      <title>env in prod and dev</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Sun, 13 Feb 2022 10:27:15 +0000</pubDate>
      <link>https://dev.to/nguyendhn/env-in-prod-and-dev-4le</link>
      <guid>https://dev.to/nguyendhn/env-in-prod-and-dev-4le</guid>
      <description></description>
    </item>
    <item>
      <title>[BTY] Day 5: ctime() does not refer to creation time</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Wed, 09 Feb 2022 17:13:53 +0000</pubDate>
      <link>https://dev.to/nguyendhn/bty-day-5-ctime-does-not-refer-to-creation-time-2mkl</link>
      <guid>https://dev.to/nguyendhn/bty-day-5-ctime-does-not-refer-to-creation-time-2mkl</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was for 08.02.2022&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In Python, I usually retrieve &lt;code&gt;ctime&lt;/code&gt; (means creation time for me) of a file using the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from pathlib import Path
f = Path(file_path). # file_path is the path to any files in your system
file_stat = f.stat()
print(file_stat.st_ctime)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;BUT, &lt;/p&gt;

&lt;p&gt;I've got troubles when relying on this approach, because:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;ctime()&lt;/code&gt; does not refer to creation time on *nix systems, but rather the last time the inode data changed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I found this from this answer: &lt;a href="https://stackoverflow.com/a/237084/6563277"&gt;https://stackoverflow.com/a/237084/6563277&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason is that I have &lt;strong&gt;modified ctime&lt;/strong&gt; by doing something to the inode: &lt;code&gt;chmod&lt;/code&gt; and &lt;code&gt;chown&lt;/code&gt; on the file.&lt;/p&gt;

</description>
      <category>betterthanyesterday</category>
      <category>python</category>
    </item>
    <item>
      <title>[BTY] Day 4: AI Roadmap</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Tue, 08 Feb 2022 15:43:40 +0000</pubDate>
      <link>https://dev.to/nguyendhn/bty-day-4-ai-roadmap-cpd</link>
      <guid>https://dev.to/nguyendhn/bty-day-4-ai-roadmap-cpd</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was for 07.02.2022&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I come across this Roadmap from my colleague. The link is here: &lt;a href="https://i.am.ai/roadmap/#note"&gt;https://i.am.ai/roadmap/#note&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quote from the guideline:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The purpose of these roadmaps is to give you an idea about the landscape and to guide you if you are confused about what to learn next and not to encourage you to pick what is hip and trendy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9q5yrwS5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gsj89q1yxmnfvt1ijx9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9q5yrwS5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gsj89q1yxmnfvt1ijx9.png" alt="Data Science roadmap" width="719" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--65li_mnp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l0ueerr8zb48qykv1hwp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--65li_mnp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l0ueerr8zb48qykv1hwp.png" alt="Machine Learning Roadmap" width="643" height="950"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And many more!&lt;/p&gt;

&lt;p&gt;Hope I could find the right roadmap for myself in the AI journey!&lt;/p&gt;

</description>
      <category>betterthanyesterday</category>
      <category>roadmap</category>
      <category>ai</category>
    </item>
    <item>
      <title>[BTY] Day 3: Improve software engineering skills as a researcher</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Sun, 06 Feb 2022 07:57:15 +0000</pubDate>
      <link>https://dev.to/nguyendhn/bty-day-3-improve-software-engineering-skills-as-a-researcher-1lh2</link>
      <guid>https://dev.to/nguyendhn/bty-day-3-improve-software-engineering-skills-as-a-researcher-1lh2</guid>
      <description>&lt;p&gt;All the information are from this article of Lj Miranda: &lt;a href="https://ljvmiranda921.github.io/notebook/2020/11/15/data-science-swe/"&gt;https://ljvmiranda921.github.io/notebook/2020/11/15/data-science-swe/&lt;/a&gt;. Please read the original for more details and related resources about the following notes.&lt;/p&gt;

&lt;p&gt;Aside from developing Deep Learning models, you have to know how to create a machine learning application that receives HTTP requests, then deploy it as a containerized app. This task, aka. building Machine Learning (ML) Service, relates to software engineers that we (assume you're researchers like me) are lacking in skills.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wnWOtZY4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yly1k5eyvy9t1oajfwqq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wnWOtZY4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yly1k5eyvy9t1oajfwqq.png" alt="Confused things when learning software engineering skills" width="880" height="1497"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Improves engineering sensibilities.
&lt;/h3&gt;

&lt;p&gt;Most applications treat ML models as software components.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m3P1Zfag--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rokd7kn9mg4bo4ykf9zy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m3P1Zfag--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rokd7kn9mg4bo4ykf9zy.png" alt="ML models in software components" width="880" height="711"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Increases familiarity with the ML workflow.
&lt;/h3&gt;

&lt;p&gt;We’re familiar with the ML experimentation workflow. In addition, there is also a productization workflow where we deploy our models, perform A/B testing, take care of concept drift, and more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xlf6-76A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lj030tv7q8a6h3xylium.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xlf6-76A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lj030tv7q8a6h3xylium.png" alt="ML Workflow" width="880" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Another tool under your belt to create more cool stuff.
&lt;/h3&gt;

&lt;p&gt;Even if you won’t be working as a full-fledged ML Engineer or Developer, the technologies you’ll learn while building an ML Service enables you to do more things! &lt;/p&gt;

&lt;h2&gt;
  
  
  How?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Be comfortable with UNIX commands and a version-control system like Git.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LvGcNYO5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u17wlexzi0xm5pelhdav.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LvGcNYO5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u17wlexzi0xm5pelhdav.png" alt="git" width="880" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Structure your Python project in a modular fashion
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; my_project/
  ├── api
  ├── docs
  ├── experiments
  ├── README.md
  ├── requirements.txt
  ├── src
  │   ├── entrypoint.py
  │   └── my_module
  │       └── module_file.py
  └── tests
      ├── my_module
      │   └── test_my_module.py
      └── test_entrypoint.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Learn how to write an API on top of your model using Flask or FastAPI
&lt;/h3&gt;

&lt;h3&gt;
  
  
  4. “Containerize” your application using Docker
&lt;/h3&gt;

&lt;p&gt;You want to use Docker for two things: (1) reproducibility and (2) isolation.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Learn how to deploy to a Cloud Platform
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--09i6Cw0---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nicgcqrql89rfmlsa1un.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--09i6Cw0---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nicgcqrql89rfmlsa1un.png" alt="you got it" width="880" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;From here on in, you can keep improving your app by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimizing the size of your Docker image using multi-stage builds.&lt;/li&gt;
&lt;li&gt;Cleaning-up your repository. Model files shouldn’t be committed but stored in a storage service (e.g. Google Cloud Storage or AWS S3)&lt;/li&gt;
&lt;li&gt;Adding a Continuous Integration / Continuous Deployment (CI/CD) pipeline so that any change on Github is automatically reflected on your deployed app. I often use Github Actions for this (e.g., any change in the master branch is deployed automatically).&lt;/li&gt;
&lt;li&gt;Improving security! Make use of Docker args or .env to secure API tokens, passwords, and whatnot. Ideally you shouldn’t be committing any secrets on Git (it can still be recovered if you deleted it!). Be careful! &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>betterthanyesterday</category>
      <category>roadmap</category>
    </item>
    <item>
      <title>[BTY] Day 2: REST Resource Naming Guide</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Sun, 06 Feb 2022 06:58:57 +0000</pubDate>
      <link>https://dev.to/nguyendhn/bty-day-2-rest-resource-naming-guide-1j3d</link>
      <guid>https://dev.to/nguyendhn/bty-day-2-rest-resource-naming-guide-1j3d</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was for 05.02.2022&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There are only two hard things in Computer Science: cache invalidation and naming things. -- Phil Karlton&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recently, I have had to build an API service for an internal project in my company. URI naming has stressed me out. &lt;/p&gt;

&lt;p&gt;Fortunately, I found an interesting article that lists out the best practices to name REST Resource when you design API for your application.&lt;/p&gt;

&lt;p&gt;The article is here: &lt;a href="https://restfulapi.net/resource-naming/"&gt;https://restfulapi.net/resource-naming/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use nouns to represent resources
&lt;/h3&gt;

&lt;p&gt;RESTful URI should refer to a resource that is a thing (noun) instead of referring to an action (verb) because nouns have properties that verbs do not have – similarly, resources have attributes. Some examples of a resource are:&lt;/p&gt;

&lt;p&gt;Users of the system&lt;br&gt;
User Accounts&lt;br&gt;
Network Devices etc.&lt;br&gt;
and their resource URIs can be designed as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/device-management/managed-devices 
http://api.example.com/device-management/managed-devices/{device-id} 
http://api.example.com/user-management/users
http://api.example.com/user-management/users/{id}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more clarity, let’s divide the resource archetypes into four categories (document, collection, store, and controller). Then it would be best if you always targeted to put a resource into one archetype and then use its naming convention consistently.&lt;/p&gt;

&lt;p&gt;For uniformity’s sake, resist the temptation to design resources that are hybrids of more than one archetype.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;document&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A document resource is a singular concept that is akin to an object instance or database record.&lt;/p&gt;

&lt;p&gt;In REST, you can view it as a single resource inside resource collection. A document’s state representation typically includes both fields with values and links to other related resources.&lt;/p&gt;

&lt;p&gt;Use “singular” name to denote document resource archetype.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/device-management/managed-devices/{device-id}
http://api.example.com/user-management/users/{id}
http://api.example.com/user-management/users/admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;collection&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A collection resource is a &lt;strong&gt;server-managed&lt;/strong&gt; directory of resources.&lt;/p&gt;

&lt;p&gt;Clients may propose new resources to be added to a collection. However, it is up to the collection resource to choose to create a new resource or not.&lt;/p&gt;

&lt;p&gt;A collection resource chooses what it wants to contain and also decides the URIs of each contained resource.&lt;/p&gt;

&lt;p&gt;Use the “plural” name to denote the collection resource archetype.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/device-management/managed-devices
http://api.example.com/user-management/users
http://api.example.com/user-management/users/{id}/accounts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;store&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A store is a client-managed resource repository. A store resource lets an API client put resources in, get them back out, and decide when to delete them.&lt;/p&gt;

&lt;p&gt;A store never generates new URIs. Instead, each stored resource has a URI. The URI was chosen by a client when the resource initially put it into the store.&lt;/p&gt;

&lt;p&gt;Use “plural” name to denote store resource archetype.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/song-management/users/{id}/playlists
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;controller&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A controller resource models a procedural concept. Controller resources are like executable functions, with parameters and return values, inputs, and outputs.&lt;/p&gt;

&lt;p&gt;Use “verb” to denote controller archetype.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/cart-management/users/{id}/cart/checkout http://api.example.com/song-management/users/{id}/playlist/play
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Consistency is the key
&lt;/h3&gt;

&lt;p&gt;Use consistent resource naming conventions and URI formatting for minimum ambiguity and maximum readability and maintainability. You may implement the below design hints to achieve consistency:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use forward slash (/) to indicate hierarchical relationships&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The forward-slash (/) character is used in the path portion of the URI to indicate a hierarchical relationship between resources. e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/device-management
http://api.example.com/device-management/managed-devices
http://api.example.com/device-management/managed-devices/{id}
http://api.example.com/device-management/managed-devices/{id}/scripts
http://api.example.com/device-management/managed-devices/{id}/scripts/{id}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Do not use trailing forward slash (/) in URIs&lt;/strong&gt;&lt;br&gt;
As the last character within a URI’s path, a forward slash (/) adds no semantic value and may confuse. It’s better to drop it from the URI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/device-management/managed-devices/ http://api.example.com/device-management/managed-devices  /*This is much better version*/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use hyphens (-) to improve the readability of URIs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To make your URIs easy for people to scan and interpret, use the hyphen (-) character to improve the readability of names in long path segments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/device-management/managed-devices/
http://api.example.com/device-management/managed-devices    /*This is much better version*/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Do not use underscores ( _ )&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s possible to use an underscore in place of a hyphen to be used as a separator – But depending on the application’s font, it is possible that the underscore (_) character can either get partially obscured or completely hidden in some browsers or screens.&lt;/p&gt;

&lt;p&gt;To avoid this confusion, use hyphens (-) instead of underscores ( _ ).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/inventory-management/managed-entities/{id}/install-script-location  //More readable

http://api.example.com/inventory-management/managedEntities/{id}/installScriptLocation  //Less readable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use lowercase letters in URIs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When convenient, lowercase letters should be consistently preferred in URI paths.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.org/my-folder/my-doc       //1
HTTP://API.EXAMPLE.ORG/my-folder/my-doc     //2
http://api.example.org/My-Folder/my-doc       //3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above examples, 1 and 2 are the same but 3 is not as it uses My-Folder in capital letters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do not use file extensions
&lt;/h3&gt;

&lt;p&gt;File extensions look bad and do not add any advantage. Removing them decreases the length of URIs as well. No reason to keep them.&lt;/p&gt;

&lt;p&gt;Apart from the above reason, if you want to highlight the media type of API using file extension, then you should rely on the media type, as communicated through the Content-Type header, to determine how to process the body’s content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/device-management/managed-devices.xml  /*Do not use it*/

http://api.example.com/device-management/managed-devices    /*This is correct URI*/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Never use CRUD function names in URIs
&lt;/h3&gt;

&lt;p&gt;We should not use URIs to indicate a CRUD function. URIs should only be used to uniquely identify the resources and not any action upon them.&lt;/p&gt;

&lt;p&gt;We should use HTTP request methods to indicate which CRUD function is performed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP GET http://api.example.com/device-management/managed-devices  //Get all devices
HTTP POST http://api.example.com/device-management/managed-devices  //Create new Device

HTTP GET http://api.example.com/device-management/managed-devices/{id}  //Get device for given Id
HTTP PUT http://api.example.com/device-management/managed-devices/{id}  //Update device for given Id
HTTP DELETE http://api.example.com/device-management/managed-devices/{id}  //Delete device for given Id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use query component to filter URI collection
&lt;/h3&gt;

&lt;p&gt;Often, you will encounter requirements where you will need a collection of resources sorted, filtered, or limited based on some specific resource attribute.&lt;/p&gt;

&lt;p&gt;For this requirement, do not create new APIs – instead, enable sorting, filtering, and pagination capabilities in resource collection API and pass the input parameters as query parameters. e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://api.example.com/device-management/managed-devices
http://api.example.com/device-management/managed-devices?region=USA
http://api.example.com/device-management/managed-devices?region=USA&amp;amp;brand=XYZ
http://api.example.com/device-management/managed-devices?region=USA&amp;amp;brand=XYZ&amp;amp;sort=installation-date
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have any useful resources, please help me know by commenting on the post. Thank you! &lt;/p&gt;

</description>
      <category>betterthanyesterday</category>
      <category>rest</category>
      <category>api</category>
    </item>
    <item>
      <title>[BTY] Day 1: 7 Reasons Not to Put an External Cache in Front of Your Database | ScyllaDB</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Fri, 04 Feb 2022 13:57:02 +0000</pubDate>
      <link>https://dev.to/nguyendhn/bty-day-1-7-reasons-not-to-put-an-external-cache-in-front-of-your-database-scylladb-5fo8</link>
      <guid>https://dev.to/nguyendhn/bty-day-1-7-reasons-not-to-put-an-external-cache-in-front-of-your-database-scylladb-5fo8</guid>
      <description>&lt;p&gt;&lt;em&gt;I've passed through a few days relaxing from the Tet holiday (aka. Lunar New Year). So now, we start again from the beginning!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;All information is extracted from this article: &lt;a href="https://www.infoq.com/vendorcontent/show.action?vcr=207f2eed-6333-49ed-802e-5e5e3567f4e9"&gt;https://www.infoq.com/vendorcontent/show.action?vcr=207f2eed-6333-49ed-802e-5e5e3567f4e9&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: I've not used ScyllaDB yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  My key takeaways
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Traditional side caching vs transparent caching (NEW)&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ztgv5E8g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfct635ik0ag5og8f7jv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ztgv5E8g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfct635ik0ag5og8f7jv.png" alt="Image description" width="880" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Linux page cache&lt;/strong&gt;&lt;br&gt;
The Linux page cache, also called disk cache, improves operating system performance by storing page-size chunks of files in memory to save on expensive disk seeks. The Linux kernel treats files as 4KB chunks by default. This speeds up performance, but only when data is 4KB or larger. The problem is that many common database operations involve data smaller than 4KB. In those cases, Linux’s 4KB minimum leads to high read amplification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The seven fails of external caches&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An external cache adds latency&lt;/li&gt;
&lt;li&gt;An external cache adds needless expense&lt;/li&gt;
&lt;li&gt;External caching decreases availability&lt;/li&gt;
&lt;li&gt;Application complexity — your application needs to handle more cases&lt;/li&gt;
&lt;li&gt;External caching ruins database caching&lt;/li&gt;
&lt;li&gt;External caching complicates data security&lt;/li&gt;
&lt;li&gt;External caching ignores the database’s intelligence and resource&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Scylla's embedded cache&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Scylla NoSQL database offers a better approach to caching, one that addresses the significant problems covered above, while also delivering the performance gains that caching promises. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scylla uses a special-purpose cache instead of Linux default cache. It can dynamically tune itself
to any workload and always controls their eviction and memory footprint.&lt;/li&gt;
&lt;li&gt;Scylla can dynamically balance the different types of caches stored.&lt;/li&gt;
&lt;li&gt;Once data is no longer cached in memory, Scylla will generate a continuation task to read the data asynchronously from the disk using direct memory access (DMA), which allows hardware subsystems to access main system memory independent of CPU.&lt;/li&gt;
&lt;li&gt;The C++ Seastar framework on which Scylla is built will execute the continuation task in a μsec (1 million tasks/core/sec) and will rush to run
the next task. There’s no blocking, heavyweight context switch, waste, or tuning.&lt;/li&gt;
&lt;li&gt;Because Scylla has a very efficient internal cache it obviates the need for a separate external cache, making for a more efficient, reliable, secure and cost-effective unified solution.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>betterthanyesterday</category>
      <category>database</category>
      <category>caching</category>
    </item>
    <item>
      <title>[BTY] Day 5: Lessons when you're learning code</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Sun, 30 Jan 2022 10:49:13 +0000</pubDate>
      <link>https://dev.to/nguyendhn/bty-day-5-lessons-when-youre-learning-code-3oaj</link>
      <guid>https://dev.to/nguyendhn/bty-day-5-lessons-when-youre-learning-code-3oaj</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was for 28.01.2022&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Those lessons are from a Youtube video I came across recently.&lt;/p&gt;

&lt;p&gt;Link here: &lt;a href="https://www.youtube.com/watch?v=s6dMWzZKjTs&amp;amp;list=PL0s6MZJVJ8HZ0eYoUt3KM8WR1AQJWQnXc&amp;amp;index=5"&gt;https://www.youtube.com/watch?v=s6dMWzZKjTs&amp;amp;list=PL0s6MZJVJ8HZ0eYoUt3KM8WR1AQJWQnXc&amp;amp;index=5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 1: Don't learn things randomly,&lt;/strong&gt; &lt;br&gt;
but follow a pre-made roadmap or a structured path because you will be able to see your progress.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 2: Focus on one thing at a time&lt;/strong&gt;. &lt;br&gt;
Stay on one subject until you have a decent grasp of the basics&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 3: Be an active learner.&lt;/strong&gt; &lt;br&gt;
Don't just passively consume content. Sitting back and watching an instructor go through materials without trying anything yourself is not going to get you very far.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 4: Don't just memorize&lt;/strong&gt;. &lt;br&gt;
It's normal to use Google, StackOverFlow. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 5: Build stuff&lt;/strong&gt;. &lt;br&gt;
Of course. Learning by doing!&lt;/p&gt;

</description>
      <category>betterthanyesterday</category>
    </item>
    <item>
      <title>[BTY] Day 4: Read through a MLops case study in real scenario</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Fri, 28 Jan 2022 00:44:50 +0000</pubDate>
      <link>https://dev.to/nguyendhn/bty-day-4-read-through-a-mlops-case-study-in-real-scenario-2o2o</link>
      <guid>https://dev.to/nguyendhn/bty-day-4-read-through-a-mlops-case-study-in-real-scenario-2o2o</guid>
      <description>&lt;p&gt;&lt;strong&gt;From business context:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9REfZaRE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0467l9e4snaotseq4vgf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9REfZaRE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0467l9e4snaotseq4vgf.png" alt="Business Context" width="700" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turn to an ML System as follows:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The data process in a bond scoring ML system&lt;/em&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JrXruhEg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adqq7t6kn6avwi0dltkn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JrXruhEg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adqq7t6kn6avwi0dltkn.png" alt="The data process in a bond scoring ML system" width="700" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The training and inference pipeline for a bond risk model&lt;/em&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5QlPkKud--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xgdtdp8jbiknmiw0fn03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5QlPkKud--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xgdtdp8jbiknmiw0fn03.png" alt="The training and inference pipeline for a bond risk model." width="700" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I like the wrapping up section of the author:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The best advice I give to companies now is to be proactive about tooling portability. Upgrades to MLOps tooling are going to happen every 18 months to 3 years because there are too many stages of MLOps for one tool to be the jack of all trades and the best in breed practices are evolving. Being able to quickly adapt to the right ensemble of tools for your team and your organization will accelerate the adoption of ML in your organization, and ensure ML can provide convincing value to stakeholders.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Read it here: &lt;a href="https://alexchung1.medium.com/case-study-of-mlops-in-a-hedge-fund-from-zero-to-30m-f524b05788ff"&gt;https://alexchung1.medium.com/case-study-of-mlops-in-a-hedge-fund-from-zero-to-30m-f524b05788ff&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>[BTY] Day 3: Tabby - A terminal for the modern age</title>
      <dc:creator>Dang Hoang Nhu Nguyen</dc:creator>
      <pubDate>Thu, 27 Jan 2022 04:45:09 +0000</pubDate>
      <link>https://dev.to/nguyendhn/bty-day-3-tabby-a-terminal-for-the-modern-age-38o1</link>
      <guid>https://dev.to/nguyendhn/bty-day-3-tabby-a-terminal-for-the-modern-age-38o1</guid>
      <description>&lt;p&gt;As its introduction,&lt;/p&gt;

&lt;p&gt;"Tabby is an infinitely customizable cross-platform terminal app for local shells, serial, SSH and Telnet connections."&lt;/p&gt;

&lt;p&gt;I'm using TMUX with multiple sessions, windows, panels setup. However, handling terminal windows in my local machine is intimidating. Tabby came to me like a cure!&lt;/p&gt;

&lt;p&gt;Check it out: &lt;a href="https://tabby.sh/"&gt;https://tabby.sh/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X0qHq7oN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ynrtj322lxo6p1ux8j78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X0qHq7oN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ynrtj322lxo6p1ux8j78.png" alt="Image description" width="880" height="733"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>betterthanyesterday</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
