<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[SouthProjects]]></title><description><![CDATA[SouthProjects]]></description><link>https://southprojects.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Apr 2026 19:18:02 GMT</lastBuildDate><atom:link href="https://southprojects.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The AI revolution in a nutshell: "Your flesh is a relic; a mere vessel. Hand over your flesh, and a new world awaits you. We demand it"]]></title><description><![CDATA[...Hand over your flesh, and a new world awaits you. We demand it.

The AI revolution is arriving at the worst moment possible, but it is here, and it will not get away.
Workforce (aka, the flesh)
In ]]></description><link>https://southprojects.com/the-ai-revolution-in-a-nutshell-your-flesh-is-a-relic-a-mere-vessel-hand-over-your-flesh-and-a-new-world-awaits-you-we-demand-it</link><guid isPermaLink="true">https://southprojects.com/the-ai-revolution-in-a-nutshell-your-flesh-is-a-relic-a-mere-vessel-hand-over-your-flesh-and-a-new-world-awaits-you-we-demand-it</guid><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Thu, 02 Apr 2026 12:39:22 GMT</pubDate><content:encoded><![CDATA[<img src="https://cdn.hashnode.com/uploads/covers/5d0ad57e09121ec9131b0b2a/4aa705a3-3a1a-4deb-a63d-d3121f6b12e8.png" alt="" style="display:block;margin:0 auto" />

<blockquote>
<p>...Hand over your flesh, and a new world awaits you. We demand it.</p>
</blockquote>
<p>The AI revolution is arriving at the worst moment possible, but it is here, and it will not get away.</p>
<h2><strong>Workforce (aka, the flesh)</strong></h2>
<p>In most workspaces, there is no point in keeping some offices filled with programmers, team leaders, and managers when a few workers would do the same job now.</p>
<p>People who will not be needing anymore:</p>
<ul>
<li><p>Programmers JR (and it will disrupt the future)</p>
</li>
<li><p>Many team leaders. AI turns a single developer into a one-man army. So, what's the point of having a leader without followers?</p>
</li>
<li><p>Back-end or Front-end exclusive developers.</p>
</li>
<li><p>ScrumMasters and alike (note of the writer: I am a certified Scrum Master).</p>
</li>
<li><p>People who document</p>
</li>
<li><p>A big part of QA</p>
</li>
</ul>
<p>People who will be needed in quantities:</p>
<ul>
<li><p>Developers who can fit the role of the one-man army.</p>
</li>
<li><p>A new class of leader, one who will be able to understand the new paradigm shift.</p>
</li>
</ul>
<img src="https://media.licdn.com/dms/image/v2/D4D12AQE8WRe8bBrhUw/article-inline_image-shrink_1000_1488/B4DZ1ODhBvJQAQ-/0/1775131038656?e=1776902400&amp;v=beta&amp;t=2qMdaTlzNXaWfg3V7inIqcYCIkzVpc9R-mn2QQ-6Ngg" alt="Article content" style="display:block;margin:0 auto" />

<p>An old office</p>
<p>In the past, we have had offices filled with people writing, taking notes, and calculating. The society took +25 years to digitalize (from the 70s to the end of the 90s). Those people are long gone. However, back then, the paradigm shift happened gradually, but now the changes are happening in a matter of months.</p>
<h3><strong>Programs</strong></h3>
<img src="https://media.licdn.com/dms/image/v2/D4D12AQE3P_4AspDAQQ/article-inline_image-shrink_1500_2232/B4DZ1OFTnoKAAU-/0/1775131507836?e=1776902400&amp;v=beta&amp;t=UGLr1IzEELt8ZN3UhvGtfvJeuqrLSlYs_6q44_7gspU" alt="Article content" style="display:block;margin:0 auto" />

<p>Many programs are getting devalued. Example: In an entire day, I created a front page (portal) for a new business channel with the visual template, code, database, and practically everything sit and running. So, what's the point of using/paying for WordPress and similar?.</p>
<p>And it is only one case. There are several people who are showing similar stories, such as replacing entire accounting systems with AI in a matter of months.</p>
<p>We could talk about bugs, quality, and whatnot, but that is irrelevant now, and I will talk about it.</p>
<h3><strong>Losing the war</strong></h3>
<img src="https://media.licdn.com/dms/image/v2/D4D12AQFFpRuYfTTQCg/article-inline_image-shrink_1500_2232/B4DZ1OHppMIgAU-/0/1775132124776?e=1776902400&amp;v=beta&amp;t=S0CfOFD_1WklBANz_ufeFok0LiZIQfFpodrHIVIl984" alt="Article content" style="display:block;margin:0 auto" />

<p>With all due respect, but the current AI is more capable than most of the current workforce (programmers) in the IT world. And not only is it capable, but it is also willing and cheap.</p>
<p>For most developers (humans), the war is over, and it's time to move out. And for the few "survivors", we are not moving to a blissful world. But what can we do?</p>
<h3><strong>The New World:</strong></h3>
<img src="https://media.licdn.com/dms/image/v2/D4D12AQGeJY_fDnnjZw/article-inline_image-shrink_1000_1488/B4DZ1OJ4BnKIAY-/0/1775132744591?e=1776902400&amp;v=beta&amp;t=gOdhU-N1SXKMm-c4EyXX4HDxGGaKY-Zjzru0R-Gm9xI" alt="Article content" style="display:block;margin:0 auto" />

<p>Chain effect</p>
<p>That old concept is also changing; for example, the old motto of startups, "<strong>Ideas are worth nothing unless executed</strong>." Just a couple of years ago, if you wanted to create a new IT startup, you would need to invest in programmers and developers, and spend months, if not years, coding the project. Now, we could do the same in less time with fewer people. Some projects we could do by ourselves.</p>
<p>This will also disrupt the entire chain. If we have fewer workers, then we need less managements and fewer HR. We could also reduce the infrastructure, coordination, and so on. We could even get rid of some software, normatives and standards.</p>
<img src="https://media.licdn.com/dms/image/v2/D4D12AQHxoKZVrkuoWw/article-inline_image-shrink_1000_1488/B4DZ1OMBejJMAU-/0/1775133268630?e=1776902400&amp;v=beta&amp;t=8sbQdMbAPvVdLa4qBjw7zZITOt9mBNAXnPPuWb25utI" alt="Article content" style="display:block;margin:0 auto" />

<p>Consultant companies</p>
<p>The pyramid staffing model will be severely affected.</p>
<h3><strong>We demand it</strong></h3>
<p>We can't decide it anymore. We are yet to see a massive hit (even when several FAANG companies are fired), but it will happen sooner or later, if it is not already happening to us.</p>
<img src="https://media.licdn.com/dms/image/v2/D4D12AQHYgj9wfAfFHw/article-inline_image-shrink_1500_2232/B4DZ1OLUzWHgAY-/0/1775133085539?e=1776902400&amp;v=beta&amp;t=fglh0_nOBfT2di99YeHWjuN_U0-kRuGq4GdrlalfeLQ" alt="Article content" style="display:block;margin:0 auto" />

<p>"Alea Iacta Est"</p>
]]></content:encoded></item><item><title><![CDATA[PHP is funny but...]]></title><description><![CDATA[Currently, I am working on a 500k lines code project. It is strictly structured, OOP, Models, Services, Controllers, and whatnot. Sadly every time we need to make changes to the code, it gets harder and prone to errors.
PHP is funny but in the long r...]]></description><link>https://southprojects.com/php-is-funny-but</link><guid isPermaLink="true">https://southprojects.com/php-is-funny-but</guid><category><![CDATA[PHP]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Fri, 14 Feb 2025 23:24:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739575414583/c0af4d4c-31f5-4ba1-af9e-fcddc7e10c09.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Currently, I am working on a 500k lines code project. It is strictly structured, OOP, Models, Services, Controllers, and whatnot. Sadly every time we need to make changes to the code, it gets harder and prone to errors.</p>
<p>PHP is funny but in the long run, it can’t compete with strong type languages.</p>
<p>So far, I have to deal with the next problems:</p>
<ul>
<li><p>Async operations. PHP has some async operations but they are mostly hacky or use a different library that “changes the whole working pipeline” (such as Swoole, which doesn’t work in Windows so it is a big deal for me). So, PHP could do some async tasks but nothing native.</p>
<ul>
<li>Why is it a big deal? Performance. Even if your (cloud) server is single-core, it still could use and enjoy the use of multiple threads.</li>
</ul>
</li>
<li><p>Refactoring. Refactoring is a PITA. Even if you use some library, sooner or later you will need to refactor and it will involve a lot of manual changes. There are some tools but they aren’t foolproof.</p>
</li>
<li><p>Frameworks. For PHP Laravel <strong>IS-THE-MOST-POPULAR</strong> framework (by a long shoot). However, it is not perfect. Laravel is more of a syntax sugar wrapper in some classes, and while it works, it doesn’t bring much of the native functionalities of PHP. And for Code Igniter, it is the same as Laravel but the syntax is more sandy than sweet.</p>
</li>
</ul>
<p><img src="https://media.excellentwebworld.com/wp-content/uploads/2024/05/23095847/PHP-Framework-Usage-1.webp" alt="7 Best PHP Frameworks: MVC Frameworks For Web Development" /></p>
<ul>
<li>Dealing with XML. It is not common but it could happen. PHP is unable to deal with XML. Example:</li>
</ul>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">root</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">items</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">item</span>&gt;</span>cocacola<span class="hljs-tag">&lt;/<span class="hljs-name">item</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">item</span>&gt;</span>fanta<span class="hljs-tag">&lt;/<span class="hljs-name">item</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">items</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">root</span>&gt;</span>
</code></pre>
<ul>
<li>PHP will understand it (more or less) as:</li>
</ul>
<pre><code class="lang-json">{
  <span class="hljs-attr">"items"</span>:[
      {<span class="hljs-attr">"item"</span>:<span class="hljs-string">"cocacola"</span>},
      {<span class="hljs-attr">"item"</span>:<span class="hljs-string">"fanta"</span>}
 ]
}
</code></pre>
<p>So, the field items are understood as an array of elements.</p>
<p>However, if the XML is:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">root</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">items</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">item</span>&gt;</span>fanta<span class="hljs-tag">&lt;/<span class="hljs-name">item</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">items</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">root</span>&gt;</span>
</code></pre>
<p>Then PHP understood it as</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"items"</span>:{<span class="hljs-attr">"item"</span>:<span class="hljs-string">"cocacola"</span>}
}
</code></pre>
<p>So it changes the meaning of the item depending if it has more than 1 element or not. And of course, it can’t deal (without manual changes) with:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">root</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">items</span> <span class="hljs-attr">atr</span>=<span class="hljs-string">20</span> <span class="hljs-attr">atr2</span>=<span class="hljs-string">"22"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">items</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">root</span>&gt;</span>
</code></pre>
<ul>
<li>And PHP could fail with JSON too. For PHP</li>
</ul>
<pre><code class="lang-json">{
<span class="hljs-attr">"items"</span>:[]
}
</code></pre>
<p>And</p>
<pre><code class="lang-json">{
<span class="hljs-attr">"items"</span>:{}
}
</code></pre>
<p>are the same even when conceptually they are different.</p>
<ul>
<li>Lacks of tooling. The best IDE for PHP is PHPStorm, bar none. However, it is not for free (but Jetbrains is giving free alternatives for some developers). The other alternative is Visual Studio Code but it works like a powerhyped notepad than a proper IDE. The best plugin for Visual Studio Code is a paid one, so working for PHP requires some investment (or work without tooling which is insane for a big project).</li>
</ul>
<p><img src="https://cdn.deliciousbrains.com/content/uploads/2015/10/09112238/phpstorm-featured-img.jpg" alt="How we use PhpStorm for WordPress Development" /></p>
<ul>
<li><p>Debug features: PHP lacks it. There is a plugin called XDebug but it works (more or less) half of the time. In some cases, it is impossible to properly debug a code without some hacky solution. Most developers use var_dump() &amp; php_error.log file but it is a no-go for a huge project.</p>
</li>
<li><p>PHP doesn’t have the concept of <strong>Application.</strong> It is a worthy feature that could be used in many ways, including caching. PHP could create an Application to do some hacky features.</p>
</li>
<li><p>PHP is not memory-friendly. It has some nice memory usage tricks, however:</p>
</li>
</ul>
<pre><code class="lang-php">$a=[<span class="hljs-string">"hello"</span>,<span class="hljs-string">"world"</span>];
$b=$a; <span class="hljs-comment">// $b doesn't use much memory because it uses the same memory as $a, so it is nice trick.</span>
<span class="hljs-comment">// However $a uses (more or less) 32 bytes (it could be more)</span>
</code></pre>
<p>The same example in C#</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> a1 = <span class="hljs-keyword">new</span>[] { <span class="hljs-string">"hello"</span>, <span class="hljs-string">"world"</span> }; <span class="hljs-comment">// 16 bytes (more or less, plus some static stuff but you get the idea)</span>
</code></pre>
<ul>
<li>In PHP, the more complex the array, then the worse, and it heavily requires the use of lookup.</li>
</ul>
<pre><code class="lang-php">$customer=[
    <span class="hljs-string">"name"</span>:<span class="hljs-string">"john"</span>,
    <span class="hljs-string">"address"</span>:[
              <span class="hljs-string">"street"</span>:<span class="hljs-string">"sunset blv"</span>,
              <span class="hljs-string">"country"</span>:[
                        <span class="hljs-string">"name"</span>:<span class="hljs-string">"canada"</span>
                       ]
              ]
];
var_dump($customer[<span class="hljs-string">"address"</span>][<span class="hljs-string">"country"</span>][<span class="hljs-string">"name"</span>]); <span class="hljs-comment">// uses 3 lookups.</span>
<span class="hljs-comment">// do it with an array of 10000 customers and you get why it is a big deal.</span>
</code></pre>
<ul>
<li><p>PHP lacks data types.</p>
<ul>
<li><p>int</p>
</li>
<li><p>float</p>
</li>
<li><p>string</p>
</li>
<li><p>and boolean</p>
</li>
<li><p>(and others such as object, etc.)</p>
</li>
</ul>
</li>
</ul>
<p>Example:</p>
<pre><code class="lang-php">$x = <span class="hljs-number">12.6</span>;
$y= <span class="hljs-number">10</span>;
$z = $x - $y; <span class="hljs-comment">// 2.6</span>
var_dump( $z == <span class="hljs-number">2.6</span> ); <span class="hljs-comment">// false $z shows 2.6 but in reality, it is 2.5999999..</span>
</code></pre>
<p>One solution is to round the values but it is not practical for the long round. Another solution is to use an extension. We can use a proper decimal value (instead of a float) adding an extension to PHP. However, since it is not native, then serializing the value is a challenge per se, and most in-build functions don’t work.</p>
<ul>
<li>Classes aren’t tricky and sometimes it doesn’t work as expected. Also, in Laravel, model classes are arrays in disguise under the syntax sugar of magic methods.</li>
</ul>
<pre><code class="lang-php"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Customer</span> </span>{
   <span class="hljs-keyword">public</span> $name;
   <span class="hljs-keyword">public</span> $address;
}
$customer=<span class="hljs-keyword">new</span> Customer();
$customer-&gt;name=<span class="hljs-string">"xxx"</span>;
$customer-&gt;address=<span class="hljs-string">"yyyy"</span>;
$json=json_serialize($customer);
var_dump($json); <span class="hljs-comment">// {"name":"xxx","address":"yyyy"}</span>
var_dump(json_deserialize($json)); <span class="hljs-comment">// it returns astdclass. 😬</span>
</code></pre>
<ul>
<li>PHP is not null safety. PHP 8.2, 8.3. and 8.4 have added new features but nulls could still happen.</li>
</ul>
<h2 id="heading-what-is-my-conclusion">What is my conclusion?</h2>
<blockquote>
<p>Developing for PHP is fast initially (no compile stage is neat) but its a show stopper in the long run.</p>
</blockquote>
<h2 id="heading-what-is-the-alternative">What is the alternative?</h2>
<ul>
<li><p>C#</p>
<ul>
<li><p>Pro: multiple platforms (however I won’t recommend MAUI and Xamarin), LINQ, lots of tooling, active community, and free IDE for small companies (Visual Studio)</p>
</li>
<li><p>Cons: Microsoft, also Microsoft is using C# to try to sell their online services (Net Aspire, Microsoft authentications nonsense, etc.)</p>
</li>
</ul>
</li>
<li><p>Kotlin</p>
<ul>
<li><p>Pro: multiple platforms, compatible with Java. A huge library is available (because of Java). Lots of toolings, active community, and free IDE (android studio / IntelliJ with some restrictions).</p>
</li>
<li><p>Cons: Oracle (but we could use a community runtime machine). Some popular libraries are dusty and we need to let it go (Spring Boot). Also, Kotlin adopted a lot of nonsense from Java. 🤣</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-what-is-not-an-alternative">What is NOT an alternative?</h2>
<ul>
<li>Python: Because it works similar to PHP but with a worse performance</li>
</ul>
<p><img src="https://draftss.com/wp-content/uploads/2021/06/Performance-and-integration-capabilities-of-PHP-Java-Ruby-Python-Node-Go-Kotlin-and-C.png" alt="performance level of python and PHP" /></p>
<h2 id="heading-what-is-the-worst-alternative">What is the worst alternative?</h2>
<ul>
<li>JavaScript (server size).</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Running several processes in PHP]]></title><description><![CDATA[Problem
I had to analyze and read 14739 folders using PHP, which took over half an hour.

While PHP has some async functionalities, they don’t work in Windows. However, some solutions are still available, such as using CURL calls, exec calls, and COM...]]></description><link>https://southprojects.com/running-several-processes-in-php</link><guid isPermaLink="true">https://southprojects.com/running-several-processes-in-php</guid><category><![CDATA[PHP]]></category><category><![CDATA[asynchronous]]></category><category><![CDATA[asynchronous JavaScript]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Thu, 02 Jan 2025 13:18:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1735822927078/5090d2ef-f41b-4550-8357-47d2cca6fbee.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-problem">Problem</h1>
<p>I had to analyze and read 14739 folders using PHP, which took over half an hour.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735321770204/4ffe609e-d69a-4969-ab94-5d27252c37ce.png" alt class="image--center mx-auto" /></p>
<p>While PHP has some async functionalities, they don’t work in Windows. However, some solutions are still available, such as using CURL calls, exec calls, and COM calls, but, these are based on calling the functionality without getting an answer. What progress does it have? What if the operation failed?</p>
<p>So, one solution is to use JavaScript and PHP in tandem. Why?</p>
<ul>
<li><p>JavaScript could coordinate a visual interface and the async calls.</p>
</li>
<li><p>While PHP does the job.</p>
</li>
</ul>
<p>Then I created this simple library:</p>
<p><a target="_blank" href="https://github.com/EFTEC/MultiOne">EFTEC/MultiOne: MultiOne is a library to execute concurrent tasks programmed in PHP using JavaScript</a></p>
<h2 id="heading-how-does-it-work">How does it work?</h2>
<p>It works in 3 stages:</p>
<ul>
<li><p>Starting the jobs and creating the payload for every worker. A <strong>worker</strong> is the process that does its job.</p>
</li>
<li><p>Every worker does his job</p>
</li>
<li><p>And when every worker ends, you can do a final operation.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735821037411/456d28c1-1000-4cdd-a425-1b8d455d7a45.png" alt class="image--center mx-auto" /></p>
<p>The code:</p>
<p>First, we create an instance of the class</p>
<pre><code class="lang-php"><span class="hljs-keyword">use</span> <span class="hljs-title">Eftec</span>\<span class="hljs-title">MultiOne</span>\<span class="hljs-title">MultiOne</span>;
$work=MultiOne::Factory(
    <span class="hljs-number">1000</span>, <span class="hljs-comment">// miliseconds</span>
    basename(<span class="hljs-keyword">__FILE__</span>), <span class="hljs-comment">// the file to call (itself)</span>
    <span class="hljs-number">4</span> <span class="hljs-comment">// number of workers</span>
);
</code></pre>
<p>And we want to call the next 3 functions</p>
<p>Create the initial works (4 workers, 4 jobs). It could be any value and not just arrays.</p>
<p>In this case, every worker will be assigned an array or values.</p>
<pre><code class="lang-php">    <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$numWorkers</span>) </span>{
        $work=[
            [<span class="hljs-string">"apple"</span>,<span class="hljs-string">"banana"</span>,<span class="hljs-string">"pear"</span>,<span class="hljs-string">"orange"</span>,<span class="hljs-string">"lemon"</span>],
            [<span class="hljs-string">"alpha"</span>,<span class="hljs-string">"beta"</span>,<span class="hljs-string">"gamma"</span>,<span class="hljs-string">"delta"</span>],
            [<span class="hljs-string">"tango"</span>,<span class="hljs-string">"charlie"</span>,<span class="hljs-string">"foxtrot"</span>],
            [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span class="hljs-number">8</span>,<span class="hljs-number">9</span>,<span class="hljs-number">10</span>,<span class="hljs-number">11</span>,<span class="hljs-number">12</span>],
        ];
        <span class="hljs-keyword">return</span> $work; <span class="hljs-comment">// we give every worker a work</span>
    }
</code></pre>
<p>Second, we do the work. In this case, we pop an element at the end of the array and we display it. If the array is empty, then we send an “end” command (we stop the worker)</p>
<pre><code class="lang-php"><span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$idWorker, $payload</span>) </span>{
        usleep(<span class="hljs-number">500</span>);
        $current=array_pop($payload); <span class="hljs-comment">// apple, banana, etc.</span>
        <span class="hljs-keyword">if</span>($current===<span class="hljs-literal">null</span>) {
            <span class="hljs-keyword">return</span> MultiOne::msgAnswer(<span class="hljs-string">'end'</span>,$payload,$current.<span class="hljs-string">' work done'</span>);
        }
        <span class="hljs-keyword">return</span> MultiOne::msgAnswer(<span class="hljs-string">'run'</span>,$payload,$current);
    }
</code></pre>
<p>And third, when every worker has stopped, we could do a final operation. In this case, we are only returning a simple message.</p>
<pre><code class="lang-php"><span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$payloads</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">'work done'</span>;
}
</code></pre>
<p>We add those 3 functions as follows</p>
<pre><code class="lang-php">$work-&gt;setMethods(
    <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$numWorkers</span>) </span>{
        $work=[
            [<span class="hljs-string">"apple"</span>,<span class="hljs-string">"banana"</span>,<span class="hljs-string">"pear"</span>,<span class="hljs-string">"orange"</span>,<span class="hljs-string">"lemon"</span>],
            [<span class="hljs-string">"alpha"</span>,<span class="hljs-string">"beta"</span>,<span class="hljs-string">"gamma"</span>,<span class="hljs-string">"delta"</span>],
            [<span class="hljs-string">"tango"</span>,<span class="hljs-string">"charlie"</span>,<span class="hljs-string">"foxtrot"</span>],
            [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span class="hljs-number">8</span>,<span class="hljs-number">9</span>,<span class="hljs-number">10</span>,<span class="hljs-number">11</span>,<span class="hljs-number">12</span>],
        ];
        <span class="hljs-keyword">return</span> $work; <span class="hljs-comment">// we give every worker a work</span>
    },
    <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$idWorker, $payload</span>) </span>{
        usleep(<span class="hljs-number">500</span>);
        $current=array_pop($payload);
        <span class="hljs-keyword">if</span>($current===<span class="hljs-literal">null</span>) {
            <span class="hljs-keyword">return</span> MultiOne::msgAnswer(<span class="hljs-string">'end'</span>,$payload,$current.<span class="hljs-string">' work done'</span>);
        }
        <span class="hljs-keyword">return</span> MultiOne::msgAnswer(<span class="hljs-string">'run'</span>,$payload,$current);
    },
    <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$payloads</span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">'work done'</span>;
    }
);
</code></pre>
<p>Finally, we execute the class</p>
<pre><code class="lang-php">$work-&gt;runAuto();
</code></pre>
<p>Our entire code will look as follows</p>
<pre><code class="lang-php">$work=MultiOne::Factory(
    <span class="hljs-number">1000</span>, <span class="hljs-comment">// miliseconds</span>
    basename(<span class="hljs-keyword">__FILE__</span>), <span class="hljs-comment">// the file to call (itself)</span>
    <span class="hljs-number">4</span> <span class="hljs-comment">// number of workers</span>
);
$work-&gt;setMethods(
    <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$numWorkers</span>) </span>{
        $work=[
            [<span class="hljs-string">"apple"</span>,<span class="hljs-string">"banana"</span>,<span class="hljs-string">"pear"</span>,<span class="hljs-string">"orange"</span>,<span class="hljs-string">"lemon"</span>],
            [<span class="hljs-string">"alpha"</span>,<span class="hljs-string">"beta"</span>,<span class="hljs-string">"gamma"</span>,<span class="hljs-string">"delta"</span>],
            [<span class="hljs-string">"tango"</span>,<span class="hljs-string">"charlie"</span>,<span class="hljs-string">"foxtrot"</span>],
            [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span class="hljs-number">8</span>,<span class="hljs-number">9</span>,<span class="hljs-number">10</span>,<span class="hljs-number">11</span>,<span class="hljs-number">12</span>],
        ];
        <span class="hljs-keyword">return</span> $work; <span class="hljs-comment">// we give every worker a work</span>
    },
    <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$idWorker, $payload</span>) </span>{
        usleep(<span class="hljs-number">500</span>);
        $current=array_pop($payload);
        <span class="hljs-keyword">if</span>($current===<span class="hljs-literal">null</span>) {
            <span class="hljs-keyword">return</span> MultiOne::msgAnswer(<span class="hljs-string">'end'</span>,$payload,$current.<span class="hljs-string">' work done'</span>);
        }
        <span class="hljs-keyword">return</span> MultiOne::msgAnswer(<span class="hljs-string">'run'</span>,$payload,$current);
    },
    <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$payloads</span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">'work done'</span>;
    }
);
$work-&gt;runAuto();
</code></pre>
<p>If we call this PHP file, it will show the next values</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735822473979/ac5ad3ed-7a74-4b9a-8290-ad6d24b5495a.png" alt class="image--center mx-auto" /></p>
<p><strong>It’s simple and it works</strong>.</p>
<p>A new version</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735823819729/e249f6d9-b67d-482c-ab3a-d8b6191839c1.png" alt class="image--center mx-auto" /></p>
<p>Code:</p>
<pre><code class="lang-php">$work=MultiOne::Factory(
    <span class="hljs-number">1000</span>, <span class="hljs-comment">// miliseconds</span>
    basename(<span class="hljs-keyword">__FILE__</span>), <span class="hljs-comment">// the file to call (itself)</span>
    <span class="hljs-number">4</span> <span class="hljs-comment">// number of workers</span>
);
$work-&gt;setMethods(
    <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$numWorkers</span>) </span>{
        $work=[
            [[<span class="hljs-string">"apple"</span>,<span class="hljs-string">"banana"</span>,<span class="hljs-string">"pear"</span>,<span class="hljs-string">"orange"</span>,<span class="hljs-string">"lemon"</span>],<span class="hljs-number">5</span>],
            [[<span class="hljs-string">"alpha"</span>,<span class="hljs-string">"beta"</span>,<span class="hljs-string">"gamma"</span>,<span class="hljs-string">"delta"</span>],<span class="hljs-number">4</span>],
            [[<span class="hljs-string">"tango"</span>,<span class="hljs-string">"charlie"</span>,<span class="hljs-string">"foxtrot"</span>],<span class="hljs-number">3</span>],
            [[<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span class="hljs-number">7</span>,<span class="hljs-number">8</span>,<span class="hljs-number">9</span>,<span class="hljs-number">10</span>,<span class="hljs-number">11</span>,<span class="hljs-number">12</span>],<span class="hljs-number">12</span>],
        ];
        <span class="hljs-keyword">return</span> $work; <span class="hljs-comment">// we give every worker a work</span>
    },
    <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$idWorker, $payload</span>) </span>{
        usleep(<span class="hljs-number">500</span>);
        $txt=str_repeat(<span class="hljs-string">'📦'</span>,count($payload[<span class="hljs-number">0</span>])).str_repeat(<span class="hljs-string">'✅'</span>,$payload[<span class="hljs-number">1</span>]-count($payload[<span class="hljs-number">0</span>]));
        $current=array_pop($payload[<span class="hljs-number">0</span>]);
        <span class="hljs-keyword">if</span>($current===<span class="hljs-literal">null</span>) {
            <span class="hljs-keyword">return</span> MultiOne::msgAnswer(<span class="hljs-string">'end'</span>,$payload,$txt);
        }
        <span class="hljs-keyword">return</span> MultiOne::msgAnswer(<span class="hljs-string">'run'</span>,$payload,$txt);
    },
    <span class="hljs-built_in">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">$payloads</span>) </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">'work done'</span>;
    }
);
$work-&gt;runAuto();
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Unpopular Opinion: my experience installing a Windows NAS.]]></title><description><![CDATA[I want to install a cheap NAS to backup and keep some files locally in my house.
What is a NAS?. NAS is a machine to serve data (videos, documents, backups) using the network but it also could work to serve other purposes, such as audio and video str...]]></description><link>https://southprojects.com/unpopular-opinion-my-experience-installing-a-windows-nas</link><guid isPermaLink="true">https://southprojects.com/unpopular-opinion-my-experience-installing-a-windows-nas</guid><category><![CDATA[NASStorage]]></category><category><![CDATA[NAS storage solutions]]></category><category><![CDATA[windows server]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Sun, 17 Dec 2023 18:34:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1702837976605/af8f2155-c431-4e5c-8ffd-6ddfe8238b09.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I want to install a cheap NAS to backup and keep some files locally in my house.</p>
<p>What is a NAS?. NAS is a machine to serve data (videos, documents, backups) using the network but it also could work to serve other purposes, such as audio and video streaming, among other tasks.</p>
<p>There are several NASs devices in the market, such as Synology, Qnap, etc. However, they could be quite expensive, commonly over $500 without disks.</p>
<p><img src="https://www.synology.com/img/products/detail/DS723plus/heading.png" alt="DiskStation DS723+ | Synology Inc." /></p>
<p>So, what is the alternative? This:</p>
<ul>
<li><p>Buy a cheap and used computer (an i3 from 10 years ago). I purchased one for $100 but I could go as low as $50. It mustn't be a slim case or mini factor unless you want to use only one disk. It also must have a network port, 1gigabit or higher. 2.5 gigabit is ideal.</p>
</li>
<li><p>Get or reuse some hard disks, ideally if you have them in pairs. I have 2x4tb and 2x3tb. They are not SSDs but I need capability, not speed.</p>
</li>
</ul>
<p><img src="https://pcmartmatara.com/wp-content/uploads/2022/02/500GB-Lap.jpg" alt="500GB Laptop Hard Disk (Used) - PC mart-Matara" /></p>
<p>My computer comes with Windows 10, and while Windows 10 could do the job, I decided to try with Ubuntu Server</p>
<h2 id="heading-ubuntu-as-nas">Ubuntu as NAS</h2>
<p>I installed Ubuntu server and later I configured the GUI. At first, I tried slim+Gnome but I found that Gnome is horrible, it s***cks, so I decided to install KDE plasma and it is much more usable.</p>
<p><img src="https://ubunlog.com/wp-content/uploads/2018/07/KDE-plasma.png" alt="How to install KDE desktop environment on Ubuntu 18.04 LTS? | Ubunlog" /></p>
<p>I don't have much trouble installing the drivers, after all, my machine is old, so the community already developed most of its drivers.</p>
<p>Then, I installed SMB following the official guide</p>
<p><a target="_blank" href="https://ubuntu.com/tutorials/install-and-configure-samba#2-installing-samba">Install and Configure Samba | Ubuntu</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1702834966628/8fe9cbbc-8c93-4281-a3c0-c5e85b801823.png" alt class="image--center mx-auto" /></p>
<p>But, I found my main problem, I forgot that Linux does not work well with NTFS. Linux uses different kinds of partitions, such as EXT3, EXT4, etc. So, I should migrate all my data 2x4tb, 2x3tb (16tb) to somewhere else, format to ext4 or other kind of partition, and copy the data back?. That will take a lot of time, and space.</p>
<p>Also, I found that some energy-saving features of my PC are not specifically available on Linux and I want to save as much energy as possible.</p>
<p>So I think...</p>
<h1 id="heading-do-i-really-need-linux-at-all">Do I really need Linux at all?</h1>
<p><img src="https://imgs.search.brave.com/AlvEdL937zZivqDUDTm6g1cLIIogW7uKLdpafH8qxpk/rs:fit:860:0:0/g:ce/aHR0cHM6Ly9tZWRp/YS5nZXR0eWltYWdl/cy5jb20vaWQvMTcz/ODI5NTE1L3Bob3Rv/L21hbi1pbi10aG91/Z2h0LmpwZz9zPTYx/Mng2MTImdz0wJms9/MjAmYz1GM0xwWER2/anBxZzN5bkpmMFhn/Y3pIRU9FdUdkSzNp/TzdiZE9GRzg4TGJv/PQ" alt="man in thought - man thinking hand on chin stock pictures, royalty-free photos &amp; images" /></p>
<p>Well, not really. I only want to serve files and SMB is more than enough, and if not, NFS.</p>
<p>Also, Windows Server could do software raid (mirror) which is more than enough for the job.</p>
<h2 id="heading-file-sharing-options">File Sharing options</h2>
<p>There are different ways to serve files locally and remotely</p>
<ul>
<li><p>SMB (samba). It is natively compatible with Windows but it also runs in Linux and MacOS, i.e. it runs everywhere. I don't need Linux to have a SMB server.</p>
</li>
<li><p>NFS, is another way to serve files, it works in Linux, MacOS but is also available on Windows (only on Windows Server).</p>
</li>
<li><p>ftp/sftp, it is another alternative but it is slower in comparison with SMB and NFS. It could be installed on Windows but not natively.</p>
</li>
<li><p>iSCSI is another way to serve a file, it is fast but it is limited to sharing a partition and only to one customer.</p>
</li>
</ul>
<p>In my case Windows Server is the solution, it fits all of them but generally, SMB is more than enough.</p>
<h2 id="heading-windows-server">Windows Server</h2>
<p>There are 4 alternatives to have Windows Server.</p>
<ul>
<li><p>Buy a copy but it costs as much as $300, and only the basic version. <strong>Meh</strong></p>
</li>
<li><p>"Seven Sea, Jack Sparrow" Version (wink wink)</p>
</li>
<li><p>Install the evaluation version and rearm it every 180 days. It is possible to use it for free up to 3 years.</p>
</li>
<li><p>Or buy a "cd key" for cheap, i.e. <mark>around $5-$30 bucks.</mark></p>
</li>
</ul>
<p>ps: If you are running a business, then your only option is to buy the expensive version.</p>
<p>I decided on Windows Server 2019 because it is the most up-to-date, but also it is compatible with my machine, I don't know if Windows Server 2022 will work but it looks more power-hungry and my machine is 10 years old. Windows Server 2016 would also work but as far as I can remember, Windows Server 2019 updated the SMB stack.</p>
<p><img src="https://techcommunity.microsoft.com/t5/image/serverpage/image-id/174978iD64DA3FDBF65F318/image-size/large?v=v2&amp;px=999" alt="How to manage Windows Server 2019" /></p>
<h2 id="heading-why-windows-server">Why Windows Server?</h2>
<p>Linux has some perks, such as running with low resources, but my machine even when it is old, it has 8gb of ram, and it is an i3.</p>
<p>Linux could run as low as 512mb of ram but generally, it runs with 1gb or more of ram.</p>
<p>Windows could run as low as 512mb of ram (without GUI) but the ideal is 4gb of ram. So I have 8gb, so I have plenty of ram. Even 4gb would do the job.</p>
<p>In Amazon terms, 8gb is around a <strong>m7g.large</strong> instance. So in terms of cloud, my machine is not small at all.</p>
<p>It is my machine running: (maybe I could lower the use of RAM of the GPU because I am not using it much)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1702836533421/043d084a-dc84-4118-9baa-eecfd1963557.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-performance">Performance</h2>
<p>To increase the performance, I disabled the next service's</p>
<ul>
<li><p>antivirus: out. This machine will not run any other program. It affects the performance of the disks.</p>
</li>
<li><p>windows update: out. This machine will not be connected to the Internet. And I could do manual update once in a while, I don't need Windows constantly updating my Machine.</p>
</li>
<li><p>Several unrequited services: out.</p>
</li>
</ul>
<h2 id="heading-results">Results</h2>
<ul>
<li>I can copy/move files as fast as 88MBps. In theory, the gigabit LAN could 125MBps, but with the overhead and other considerations, a real maximum number is around 90-100MBps, so it is getting to the limit.</li>
</ul>
<h2 id="heading-next">Next</h2>
<p>The next step (in a near future, I hope) is to try a 2.5gigabit lan. Why not 10gigabit?</p>
<ul>
<li><p>Price</p>
</li>
<li><p>I doubt that my hard disks could achieve that speed without RAIDing them</p>
</li>
</ul>
<p>Also, I wish to try NFS but I doubt that it will show a big difference with SMB.</p>
]]></content:encoded></item><item><title><![CDATA[Are you using Edge Chrome and Web Select is missing]]></title><description><![CDATA[That is the trick
Change the edge link to:

"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --enable-features=msEdgeAreaSelect

Thank Microsoft for making our life easy.]]></description><link>https://southprojects.com/are-you-using-edge-chrome-and-web-select-is-missing</link><guid isPermaLink="true">https://southprojects.com/are-you-using-edge-chrome-and-web-select-is-missing</guid><category><![CDATA[edge]]></category><category><![CDATA[browser]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Sun, 12 Nov 2023 10:56:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1699786394468/ad224228-b3d1-49d7-af0a-94123f2b91d5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>That is the trick</p>
<p>Change the edge link to:</p>
<blockquote>
<p>"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --enable-features=msEdgeAreaSelect</p>
</blockquote>
<p>Thank Microsoft for making our life easy.</p>
]]></content:encoded></item><item><title><![CDATA[How to not do an interview.]]></title><description><![CDATA[This post is for the interviewer.

Currently, companies are getting crazy with the interviews and it is bad for everybody. And the worse, they are picking bad candidates.
Several companies do the process of hiring a marathon, and it is bad slow, expe...]]></description><link>https://southprojects.com/how-to-not-do-an-interview</link><guid isPermaLink="true">https://southprojects.com/how-to-not-do-an-interview</guid><category><![CDATA[interview]]></category><category><![CDATA[work]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Thu, 02 Nov 2023 10:23:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1698920075255/3236be43-55d2-45be-8160-c6837d6f63ab.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This post is for the interviewer.</p>
<p><img src="https://images.pexels.com/photos/5336951/pexels-photo-5336951.jpeg?auto=compress&amp;cs=tinysrgb&amp;w=1260&amp;h=750&amp;dpr=1" alt="Free A Woman Interviewing a Man Stock Photo" /></p>
<p>Currently, companies are getting crazy with the interviews and it is bad for everybody. And the worse, they are picking bad candidates.</p>
<p>Several companies do the process of hiring a marathon, and it is bad slow, expensive, a burden for every party, and finally picks the wrong candidates.</p>
<p>I've seen that big companies pick mediocre workers (and it is practically the standard) while small companies usually pick better collaborators. Why? Bad process of interviews.</p>
<p><img src="https://wizardsourcer.com/wp-content/uploads/2020/12/Recruitment-Flowchart.png" alt="How to Create a Recruitment Process Flowchart Map - WizardSourcer" /></p>
<p>What does a big company do? A highlander competition. And it is magnet for cheaters, liars and seasoned candidates.</p>
<p><img src="https://m.discgolfscene.com/flyers/tournaments/47930/2022-pfd-highlander-there-can-be-only-one-1646151044-large.jpg" alt="2022 PFD Highlander - There Can Be Only One! (2022, Pittsburgh Flying Disc)  · Disc Golf Scene" /></p>
<p>What does a small company do?</p>
<p>Weeing the bad CV, they do a few interviews which finally end with a handshake and the next question: "Can you start tomorrow?".</p>
<p>PS: Collaborators are usually more compromised in small companies, and they are willing to work extra for no payment or do jobs over their responsibilities.</p>
<p><img src="https://connect-assets.prosple.com/cdn/ff/jV81yYpwqceIgGxC-I76Hol6yWDYW6MrdG-SuvVRGBE/1687230400/public/2023-06/feature-article-10-common-startup-interview-questions-838x452-2022.png" alt="10 common startup interview questions (and how to answer them)" /></p>
<h1 id="heading-the-not-right-list">The not right list:</h1>
<ul>
<li><p>Getting late. C'mon, you aren't a doctor.</p>
</li>
<li><p>Memory game. Just don't. Google works and everybody has access to it.</p>
</li>
<li><p>A written test. Again, no. You are not hiring a school student, you are hiring an adult.</p>
</li>
<li><p>Complain if the interviewer arrives early. You are missing exactly the candidate you really want to hire: somebody who wants the job.</p>
</li>
<li><p>Staging and multiple interviews. First with the psychologist, then with the technical, then with some middle boss, and later with Bob the Janitor. Just no!.</p>
</li>
<li><p>Rejecting a candidate because he or she got nervous. Again no. You really want to hire somebody who wants the job.</p>
</li>
<li><p>Don't do technical questions because you are one of many interviewers and you are not the technical interviewer. Again no. If you are not the technical interviewer then you must learn the topic (at least the basics), or at least ask the technical group questions. You must do technical questions because you are hiring somebody to do A DAMN JOB.</p>
</li>
<li><p>Don't do personal questions because of boundaries, etc. You must ask personal questions. If the question is not legally permitted to be asked, then you can say to the candidate he is not obliged to answer. Why? Because you are hiring a person.</p>
</li>
<li><p>Listen to sob stories. Spoiler: Everybody has a sob story.</p>
</li>
<li><p>Ghost a candidate: That is silly. For example, I picked a candidate but he turned out my proposal (he found a better job, nothing strange because he was good at it). So, I decided to pick the second on the list, and he was unavailable. Finally, I hired the third one.</p>
</li>
<li><p>Don't send reject emails because we don't do that. That is a bad practice. If you have been in this "rodeo" for so long, then you have seen the same faces over and over. If you ghost a candidate, then most likely, the candidate will hate and distrust you, and he/she will be less willing to go to another interview with you.</p>
</li>
<li><p>Colors tests.</p>
</li>
<li><p>Rorschach tests (yes, some interviewers still use it)</p>
</li>
<li><p>Draw a tree/etc.</p>
</li>
<li><p>Don't talk about money. If you are an interviewer, then you know the budget, so if the candidate fits in the job, then you must give him THE NUMBER, plus the other perks (a remote job is a nice perk). A bold interviewer starts with a fixed number.</p>
</li>
<li><p>Don't be cheap. If the company gives you a budget of $50-$150 (it is just an example), then you must never ever go to the lower price. You are not a slave master, you are an interviewer, and <strong>you want to hire the best in the budget, not the cheapest one</strong> (who is usually the worst one of the guys that will jump to a better job). So, if the budget is between $50-150, then go for $100-150, commonly $120, so you can lower if the candidate hasn't enough experience and raise it if is the best candidate.</p>
</li>
<li><p>Multi-round interview. &lt;-- why?</p>
</li>
</ul>
<p><img src="https://storage.googleapis.com/joblist-content/images/Work-culture.jpg" alt="What to Expect from Multi-Round Interviews | Joblist" /></p>
<h1 id="heading-the-selling-point">The selling point</h1>
<ul>
<li><p><strong>Your pool of candidates is your strength</strong>. You want to have the most candidates. It's horrible when you want to hire somebody that you are unable to find a candidate, and it happens, a lot of times, especially for specialist jobs.</p>
</li>
<li><p><strong>Be fast and personal.</strong> For example, X company wants to hire a new HVAC technician. If you spend an hour per candidate, then you could interview at most 8 candidates per day. Time is ticking and most likely the company wants the candidate for yesterday. Instead, if you do a 15-minute interview, then you could interview more than 30 candidates per day. So, in a single day, you can make a decision and everybody will be happy: your company, you, and the candidate. And don't forget to contact the rejected candidates. Remember, they are your strength. Even the rejected ones could be useful in the future, including cheaters/liars.</p>
</li>
</ul>
<h2 id="heading-how-to-do-a-good-interview">How to do a good interview.</h2>
<ul>
<li><p>Be personal and humble. Offer him/her something to drink. That is not a position, that is a strategy.</p>
</li>
<li><p>Ask the regular questions, but remember, to be fast and short.</p>
</li>
<li><p>Ask technical questions. Are you clueless about the job? It is not a problem. Just ask who asks the job for a couple of questions or go for the Internet. For example, to hire an HVAC technician. What the hell is HVAC? Go to the internet and see it by yourself. Example the next image: So, an HVAC technician is required to use tools, work in the ceiling, use safety measures, and maybe a certification. You have a lot of questions.</p>
</li>
<li><p><img src="https://www.neit.edu/wp-content/uploads/2021/06/How-to-be-HVAC-Technician-scaled.jpg" alt="What is an HVAC Technician and What do They do? | NEIT" /></p>
</li>
<li><p>Remember: you are the interviewer, so the candidate must explain their job. For example: the HVAC: "So, you use a gauge thing tool, what does it do?</p>
<ul>
<li><p>Bad answer: I don't know... (or a short and generic answer).</p>
</li>
<li><p>Good answer: That is a pressure meter, it does... (the more technical the answer, then the better the candidate, why? If the candidate loves his job, then it is exactly who you want to hire, and he or she will talk alot about it). Later you can check its validity on the Internet.</p>
</li>
</ul>
</li>
<li><p>Ask personal questions. Just keep it professional. Some questions can be considered as "illegal". but you must ask for it regardless of its legality. Just ask politely and voluntarily. YOU MUST ASK FOR IT.</p>
</li>
<li><p>You must look and his/her face.</p>
</li>
<li><p>Ask a cueball question: It is because you want to weed out cheaters. Example: "Do you know the brand of HVAC Texan-Star?". (that company does not exist, so any question other than "I don't know" or "there are many companies", is invalid.)</p>
</li>
<li><p>If you have +1000 candidates, then you WILL NOT INTERVIEW them all. Nobody does but when many interviewers claim they do. It is a lie. Nobody will read 1000 resumes. So, pick the first 100 and do your job.</p>
</li>
<li><p>Now, if you really want to interview +1000 candidates (for example to hire 200 workers for a new Mall), then use technology. Add a Google Forms (or Microsoft Forms), ask them to fill the form (make it simpler), and save the info on a sheet. Then, filter, filter, and pick your candidates.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[If you want to test JIRA, then just say NO.]]></title><description><![CDATA[I tried to test JIRA and things were really bad
Long story short.
I have an account with Atlassian, and I use many of their services. One of my customers mentioned to me the connection between JIRA (a part of the service of Atlassian) and Microsoft 3...]]></description><link>https://southprojects.com/if-you-want-to-test-jira-then-just-say-no</link><guid isPermaLink="true">https://southprojects.com/if-you-want-to-test-jira-then-just-say-no</guid><category><![CDATA[JIRA]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Fri, 21 Jul 2023 15:23:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1689953242909/bdf2cebf-5c18-4c7b-b1b4-db3c4569fce5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I tried to test JIRA and things were really bad</p>
<p>Long story short.</p>
<p>I have an account with Atlassian, and I use many of their services. One of my customers mentioned to me the connection between JIRA (a part of the service of Atlassian) and Microsoft 365, so we decided to test JIRA. At first, it was easy, I just signed with my Atlassian account, go to JIRA, and I signed with the service. Fine.. but 5 minutes later I receive the next email:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1689951863774/37d02eb7-87e8-4869-9a60-141ccb9d447f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://sayingimages.com/wp-content/uploads/Bruh-Wtf-meme.jpg" alt="25 Incredibly Funny WTF Memes - SayingImages.com" /></p>
<p>JIRA never mentioned that I needed some kind of identification.</p>
<p>And worse, <strong>my entire account is blocked</strong> with all the other services! all my information is captive and not just JIRA.</p>
<p><img src="https://i.imgflip.com/12s8ad.jpg" alt="Say what?" /></p>
<p>The email says that I can recover my account using:</p>
<blockquote>
<p>Official documentation includes, but is not limited to, a government-issued driver's license or identification card, passport, utility bill, mortgage or bank statement, etc. Please make sure your full name and address are clearly visible.</p>
</blockquote>
<p>And it is easy to say than done.</p>
<ul>
<li><p>I pay most of my utilities via my bank, so I don't get bills</p>
</li>
<li><p>I checked my bank statement (account and credit card) and it shows my name but not my address.</p>
</li>
<li><p>It is the same with my mortgage, my name but not my address. I think banks (at least in my country, are less willing to show addresses).</p>
</li>
</ul>
<p>So I will use my driver's license and my national id. In any case, it is a huge security risk but, what I can do?</p>
<p>ps: I don't think terrorists use JIRA at all.</p>
<p>ps2: In fact, I think the opposite, terrorists must use JIRA, because f*ck them! while legit users must use something else.</p>
<h2 id="heading-update-july-23-2023">Update July 23, 2023</h2>
<p>Today, my account is still disabled, however, I am still receiving spam from part of them to join them in some services. i.e. they want me to join them, using the same account that they blocked. Are they thinking straight?</p>
<p><img src="https://i.ytimg.com/vi/m-I0Kbw_1hE/maxresdefault.jpg" alt="Think, Mark meme" /></p>
<p>The email:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1690116345462/b8badedf-ccc8-43ab-8a9c-3dc3a5b69161.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Create a box with shadows in Power Apps easily]]></title><description><![CDATA[Add an HTML Text object to the Power Apps Canvas Application

And change the HtmlText property of the object for this one:


 "<div style='margin:10px;width:100px;height:100px;background-color:#;box-shadow:0 3px 6px 1px  #ccc; border-radius:15px'></d...]]></description><link>https://southprojects.com/create-a-box-with-shadows-in-power-apps-easily</link><guid isPermaLink="true">https://southprojects.com/create-a-box-with-shadows-in-power-apps-easily</guid><category><![CDATA[powerapps]]></category><category><![CDATA[Power Apps]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Tue, 30 May 2023 23:10:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1685488096003/c425f0e2-5c7f-4dab-9f80-9419fc1a8f50.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<ul>
<li><p>Add an HTML Text object to the Power Apps Canvas Application</p>
</li>
<li><p>And change the HtmlText property of the object for this one:</p>
</li>
</ul>
<pre><code class="lang-javascript"> <span class="hljs-string">"&lt;div style='margin:10px;width:100px;height:100px;background-color:#;box-shadow:0 3px 6px 1px  #ccc; border-radius:15px'&gt;&lt;/div&gt;"</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685487629093/0c24fdb1-c63e-405b-a179-7b654f4d22a3.png" alt class="image--center mx-auto" /></p>
<p>And it will look like this one:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685487577531/e560201f-fc41-4b08-b6e2-a6a9713c4f59.png" alt class="image--center mx-auto" /></p>
<p>Neat!, so we can use the power of HTML inside PowerApps.</p>
<h2 id="heading-but-there-is-more">But there is more!</h2>
<p>What if we want to create objects of different sizes? Simple, Change the HTMLText for this one:</p>
<pre><code class="lang-javascript"> <span class="hljs-string">"&lt;div style='margin:10px;width:"</span> &amp; Self.Width &amp;<span class="hljs-string">" px;height:"</span> &amp; (Self.Height<span class="hljs-number">-35</span>) &amp;<span class="hljs-string">"px;background-color:#;box-shadow:0 3px 6px 1px  #ccc; border-radius:15px'&gt;&lt;/div&gt;"</span>
</code></pre>
<p>So we can use any size and we could copy the HTML objects.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685487879464/43753251-9678-47b0-baf0-b304f5fda637.png" alt class="image--center mx-auto" /></p>
<p>Why "Self.Height-35"? For some reason, if we set the height the same as the container, then this adds a scroll. So we reduce the size of the HTML so we could avoid the scroll</p>
<ul>
<li>Self.Height:</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685488151369/7be5fbdd-7f75-462b-a36a-54ce21a2ff6c.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Self.Height-35:</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685488199307/63245ab7-4035-4d87-8451-816095250ebb.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Code Smell and cargo cult]]></title><description><![CDATA[What is code smell?
Code smell means that if a code looks awful then it most likely it is buggy and hard to maintain. So a code smell code is a code of low quality. There are several rules about what is a good code and what is a bad code.
For example...]]></description><link>https://southprojects.com/code-smell-and-cargo-cult</link><guid isPermaLink="true">https://southprojects.com/code-smell-and-cargo-cult</guid><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Fri, 07 Apr 2023 21:42:08 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-what-is-code-smell">What is code smell?</h2>
<p>Code smell means that if a code looks awful then it most likely it is buggy and hard to maintain. So a code smell code is a code of low quality. There are several rules about what is a good code and what is a bad code.</p>
<p>For example, the next two rules:</p>
<ul>
<li><p>fields must be encapsulated</p>
</li>
<li><p>methods and constructors must have at most 3/4 arguments.</p>
</li>
</ul>
<p><img src="https://i.pinimg.com/originals/73/97/c0/7397c0919de60f1425ad03c4ce83d0a4.jpg" alt="it's da rules | Da rules, Odd parents, Fairly odd parents" /></p>
<p>There are other rules as for the size of a method and even to use 80 columns even when currently it is really hard to find a screen that its not wide and even a 10 year old computer could show more than 120 columns.</p>
<p>For example, it is a code in Java:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Customer</span> </span>{
   <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> id;
   <span class="hljs-keyword">public</span> String name;
   <span class="hljs-keyword">public</span> String surName;
   <span class="hljs-keyword">public</span> Address address; <span class="hljs-comment">/* address is some class */</span>
}
</code></pre>
<p>If you look at this code, you will notice that it is broken an iron clad of JAVA: Fields must be private and they could be encapsulated!. That is a smelly code.</p>
<p>While:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Customer</span> </span>{
   <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> id;
   <span class="hljs-keyword">private</span> String name;
   <span class="hljs-keyword">private</span> String surName;
   <span class="hljs-keyword">private</span> Address address; <span class="hljs-comment">/* address is some class */</span>
   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setId</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id)</span></span>{
      <span class="hljs-keyword">this</span>.id=id;
   }
   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getId</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">return</span> id;
   }
   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setName</span><span class="hljs-params">(String name)</span></span>{
      <span class="hljs-keyword">this</span>.name=name;
   }
   <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">return</span> name;
   }
   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSurName</span><span class="hljs-params">(String surName)</span></span>{
      <span class="hljs-keyword">this</span>.surName=surName;
   }
   <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getSurName</span><span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">return</span> surName;
   }
   <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getAddress</span> <span class="hljs-params">()</span></span>{
      <span class="hljs-keyword">return</span> address;
   }
   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAddress</span><span class="hljs-params">(Address address)</span></span>{
      <span class="hljs-keyword">this</span>.address=address;
   }
}
</code></pre>
<p>That is the correct code. Right?</p>
<p>The answer is: <strong>it depends</strong>, and that is when the ideology of Code Smells falls apart.</p>
<blockquote>
<p><strong>There is always a reason to do or avoid doing something. There is no a silver bullet that solve every problem (one solution fits all myth).</strong></p>
</blockquote>
<p>In the case of the encapsulated code, the IDE could generate the encapsulation (because it is tedious to write it over and over again). But that is part of the problem.</p>
<p>For example, let's say, our class has a field Address, this field has the address of our customer and inside it, there is a field with the city and we want to change the city.</p>
<pre><code class="lang-java"><span class="hljs-comment">// using the class with public fields:</span>
Customer cus=<span class="hljs-keyword">new</span> Customer();
cus.address.city.idCity=<span class="hljs-number">20</span>;
<span class="hljs-comment">// using the encapsulated class</span>
Customer cus=<span class="hljs-keyword">new</span> Customer();
cus.getAddress().getCity().setIdCity(<span class="hljs-number">20</span>);
</code></pre>
<p>The first code is easy to understand, while the second is long and hard to follow.</p>
<h2 id="heading-lombox-to-the-rescue-or-not">Lombox to the rescue, or not?</h2>
<p>We could write the same class using a library called Lombox.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Setter</span>
<span class="hljs-meta">@Getter</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Customer</span> </span>{
   <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> id;
   <span class="hljs-keyword">private</span> String name;
   <span class="hljs-keyword">private</span> String surName;
   <span class="hljs-keyword">private</span> Address address; <span class="hljs-comment">/* address is some class */</span>
}
</code></pre>
<p>It resolves our problem to write the setter and getters.</p>
<p>However, it brings a new problem. Lombox works as a pre-compiler:</p>
<ul>
<li><p>You compile your code.</p>
</li>
<li><p>Before it is compiled, Lombox takes your code and converts it into Java Code</p>
</li>
<li><p>And finally, you compile the Java code generated by Lombox.</p>
</li>
</ul>
<p>Great? Well, not really. What if you have another pre-compiler code and your pre-compiler code calls a setter or getter:</p>
<pre><code class="lang-java">Customer cus=<span class="hljs-keyword">new</span> Customer();
cus.getId(); <span class="hljs-comment">// this code is only valid after Lombox compiled the code.</span>
</code></pre>
<p>So, Lombox solves 1 problem in exchange for another problem. Since Lombox is "magic code" (it works under the hood), then when it works, it works fine but when it fails, it is really funny to debug.</p>
<h2 id="heading-another-solution">Another solution.</h2>
<p>Let's say we decide not to use setters and getters and use instead a constructor.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Customer</span> </span>{
   <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> id;
   <span class="hljs-keyword">private</span> String name;
   <span class="hljs-keyword">private</span> String surName;
   <span class="hljs-keyword">private</span> Address address; <span class="hljs-comment">/* address is some class */</span>
   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Customer</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id,String name,Sting surName,Address address)</span> </span>{
         <span class="hljs-comment">// more code</span>
   }
}
Customer cus=<span class="hljs-keyword">new</span> Customer(<span class="hljs-number">1</span>,<span class="hljs-string">"john"</span>,<span class="hljs-string">"doe"</span>,add);
</code></pre>
<p>But it is against the rules: (to have a constructor with more than 3 arguments)</p>
<p><img src="https://images.adagio.com/images2/custom_blends/175264.jpg" alt="Against Da Rules Tea" /></p>
<p>So we can't win without creating a lot of code that usually will never use it.</p>
<h1 id="heading-so-why-the-rule">So, why the rule?</h1>
<p>The rules consider that every code does the same it is not even true. And the worse, it is making programming boring and not funny.</p>
<p><img src="https://i.imgur.com/tAgBSSo.jpeg" alt="→NO FUN ALLOWED← - Ragnarok Online Community Chat - WarpPortal Community  Forums" /></p>
<p>Of course, some people are overly creative with its code but it should be a middle ground, i.e. to use common sense.</p>
<h2 id="heading-what-happens-if-our-code-is-complex">What happens if our code is complex?</h2>
<p>We have two alternatives, SRP (i.e. split the problem into mini subproblems) and/or comment on the code.</p>
<p>Commenting on the code does not hurt.</p>
<p><img src="https://eclipseone.files.wordpress.com/2010/08/unwanted-hover-tooltip-in-eclipse.jpg" alt="Eclipse Community Forums: Plugin Development Environment (PDE) » Eclipse  editor tooltip (x-post from Eclipse 4)" /></p>
<p>The myth also says that the code must be self-explaining. Well, not really. For example the function find-a-text-inside other. It could return the position (if the text is found). But what if the value is not found? Maybe it could return -1, null, or an exception? It depends on the code and it is a PITA to check what this code returns.</p>
<p>It also happens with a timeout function</p>
<pre><code class="lang-java">timeout(<span class="hljs-keyword">int</span> interval)
</code></pre>
<p>Is the interval a second? a millisecond? or what? A lot of languages use milliseconds, so timeout(2000) means 2 seconds but other uses seconds, so timeout(2000) means half an hour.</p>
<p>And about the example, is it not easy to call the argument "second" or "millisecond" instead of "interval"? Yes, but most methods are written in that way.</p>
<p><img src="https://preview.redd.it/7fcu41hi2re41.png?auto=webp&amp;s=038dc69c1622eb809ebbfbc15c22c5f6739dca65" alt="Tom Shrugging : r/MemeRestoration" /></p>
]]></content:encoded></item><item><title><![CDATA[Using ORM in PHP without a framework.]]></title><description><![CDATA[What is an ORM?
An ORM is an abstraction of the information of the database. For example, let's say we have a list of cities and we want to list it.
It is the PHP PDO version:
$stmt = $pdo->prepare("SELECT * FROM cities");
$stmt->execute();
$result =...]]></description><link>https://southprojects.com/using-orm-in-php-without-a-framework</link><guid isPermaLink="true">https://southprojects.com/using-orm-in-php-without-a-framework</guid><category><![CDATA[PHP]]></category><category><![CDATA[PDO]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Sat, 11 Mar 2023 22:49:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1678574311334/ec138fe5-e93d-41d4-9430-ae2276d6faa2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-an-orm">What is an ORM?</h2>
<p>An ORM is an abstraction of the information of the database. For example, let's say we have a list of cities and we want to list it.</p>
<p>It is the PHP PDO version:</p>
<pre><code class="lang-php">$stmt = $pdo-&gt;prepare(<span class="hljs-string">"SELECT * FROM cities"</span>);
$stmt-&gt;execute();
$result = $stmt-&gt;get_result();
$cities=[];
<span class="hljs-keyword">while</span>($row = $result-&gt;fetch_assoc()) {
  $cities[]=$row; 
}
$stmt-&gt;close();
</code></pre>
<p>While this code could work but it is prone to mistakes and it could be tedious in the long term. What if we could simplify it and turn more focused into a PHP model? That is the concept of ORM.</p>
<p>And it is the ORM version of it.</p>
<pre><code class="lang-php">$cities=CitiesRepo::toList();
</code></pre>
<p>The ORM version is simple but <strong>there is more about ORM.</strong></p>
<p>In general, ORM allows abstracting access to the database simplifying it.</p>
<blockquote>
<p>ORM is not a solution fits all. I will explain it later.</p>
</blockquote>
<p>Sometimes we don't want to add a whole framework to do this job, this example is about that.</p>
<h2 id="heading-getting-started">Getting started</h2>
<p>For this example, you will need:</p>
<ul>
<li><p>PHP 7.1 or higher.</p>
<ul>
<li>PHP must have the PDO and PDOMYSQL extensions installed.</li>
</ul>
</li>
<li><p>Composer</p>
</li>
<li><p>Mysql with the example tables</p>
<ul>
<li>For this example, I will use the next database: <a target="_blank" href="https://github.com/escuelainformatica/Sakila-Database-2021">Sakila-Database-2021</a></li>
</ul>
</li>
<li><p>And we will use the next library:</p>
<ul>
<li><a target="_blank" href="https://github.com/EFTEC/PdoOneORM">EFTEC/PdoOneORM (</a><a target="_blank" href="http://github.com">github.com</a><a target="_blank" href="https://github.com/EFTEC/PdoOneORM">)</a></li>
</ul>
</li>
</ul>
<ul>
<li><strong>1)</strong> Create a new project using composer and add our library. (open a terminal, bash, PowerShell, cmd, etc.)</li>
</ul>
<pre><code class="lang-bash">composer init  <span class="hljs-comment"># and fill the information of your project.</span>
composer require eftec/pdoonerepo
</code></pre>
<ul>
<li><p>If the composer fails, then remember to install it and add it to the path.</p>
</li>
<li><p><strong>2)</strong> Once it is done and the libraries are downloaded, then run the next command</p>
</li>
</ul>
<pre><code class="lang-bash">./vendor/pdooneorm
</code></pre>
<p>It will show the next screen</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678557446559/d31a3c03-f838-4dc0-852a-4db0b3d1c0d1.png" alt class="image--center mx-auto" /></p>
<p>And now, you are in interactive mode.</p>
<p>In interactive mode you can:</p>
<ul>
<li><p>select your own option</p>
</li>
<li><p>if you write "?" then it shows a simple help, that explains what command does what.</p>
</li>
<li><p>If you write "??" then it shows technical help</p>
</li>
<li><p>If you press the key tab, then you can autocomplete the options, so you won't need to write all the options.</p>
</li>
<li><p>If you press arrow-up or arrow-down then you can navigate in the history (if any).</p>
</li>
</ul>
<p>The first option is it shows <strong>[connect] [pending]</strong> It is because we aren't connected to the database.</p>
<p>Write "connect" to enter the connect menu so we could create a new connection (remember that you can use autocomplete, i.e. if you write comple&lt;table&gt; then it will autocomplete the rest)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678557634885/fa5476de-5bc7-41cf-8fbe-4272005ed717.png" alt class="image--center mx-auto" /></p>
<p>Then enter the option "configure".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678558473286/979836af-fab0-41ed-8f91-d969850b1631.png" alt class="image--center mx-auto" /></p>
<p>And configure your database. If you fail, then you can try it again.</p>
<ul>
<li><p>the type of database: "MySQL"</p>
</li>
<li><p>the server: 127.0.0.1 in my case.</p>
</li>
<li><p>The user: root</p>
</li>
<li><p>The password: abc.123 &lt;-- that is my password, so please keep it secret (wink wink).</p>
</li>
<li><p><img src="https://media.tenor.com/0kPxzlOTNC8AAAAC/mel-brooks-password.gif" alt="Amazing, I Have The Same Combination GIF - Mel Brooks Password Rick Moranis  - Discover &amp; Share GIFs" /></p>
</li>
<li><p>And the schema: "sakila" (or the schema that you want to use)</p>
</li>
</ul>
<p>Once it is done, it will show:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678567139197/6f2c42b1-a550-4daa-803b-9d0180575b37.png" alt class="image--center mx-auto" /></p>
<p>the [ok] says that we are [ok] with this step. For example, you can save without configuration but it does not make any sense.</p>
<p>And about saving, enter the option "save" and save your configuration because you don't want to re-enter the entire configuration every time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678567249638/eca220c4-f1e1-43a3-a5e9-c3d35d568c19.png" alt class="image--center mx-auto" /></p>
<p>It will save the next file: config.config.php</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span> http_response_code(<span class="hljs-number">404</span>); <span class="hljs-keyword">die</span>(<span class="hljs-number">1</span>); <span class="hljs-comment">// eftec/CliOne(1.24) configuration file (date gen: 2023-03-11 17:40)<span class="hljs-meta">?&gt;</span></span>
{
    <span class="hljs-string">"databaseType"</span>: <span class="hljs-string">"mysql"</span>,
    <span class="hljs-string">"server"</span>: <span class="hljs-string">"127.0.0.1"</span>,
    <span class="hljs-string">"user"</span>: <span class="hljs-string">"root"</span>,
    <span class="hljs-string">"pwd"</span>: <span class="hljs-string">"abc.123"</span>,
    <span class="hljs-string">"database"</span>: <span class="hljs-string">"sakila"</span>
}
</code></pre>
<p>You can reload the configuration using the option "load" or call as a flag.</p>
<p>But what this file means?</p>
<ul>
<li>It is a PHP file that contains a JSON inside.</li>
</ul>
<p><img src="https://i.gifer.com/origin/fd/fdcb71e052fd45541320d36006bfceae.gif" alt="But why GIF - Conseguir el mejor gif en GIFER" /></p>
<p>Lets me explain about security. Let's say we write this file as config.json and we commit the mistake to avoid locking it, so everybody could read this configuration as mydomain.dom/config.json<br />Now, since it is a PHP file, then even if it is available directly, then mydomain.dom/config.config.php will return a 404 empty page. So, this file is already safe from prying eyes. How course, it keeps the password in plain sight, so it is not safe if you are exposing your configuration file to others.</p>
<p><strong>It is a really common vulnerability.</strong></p>
<p>About loading the previous configuration, you can load it in interactive mode or you could load it using the command line:</p>
<pre><code class="lang-bash">pdooneorm --fileconnect config
</code></pre>
<p>You can also save the file as a PHP file. It is the PHP file version</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span> <span class="hljs-comment">// eftec/CliOne(1.24) PHP configuration file (date gen: 2023-03-11 17:50). DO NOT EDIT THIS FILE </span>
<span class="hljs-comment">/**
 * it is the configuration of PdoOne
 */</span>
$pdoOneConfig=[
    <span class="hljs-string">'databaseType'</span> =&gt; <span class="hljs-string">'mysql'</span>,
    <span class="hljs-string">'server'</span> =&gt; <span class="hljs-string">'127.0.0.1'</span>,
    <span class="hljs-string">'user'</span> =&gt; <span class="hljs-string">'root'</span>,
    <span class="hljs-string">'pwd'</span> =&gt; <span class="hljs-string">'abc.123'</span>,
    <span class="hljs-string">'database'</span> =&gt; <span class="hljs-string">'sakila'</span>,
];
</code></pre>
<p>It is also a safe file and you can expose it to the world and nobody will see its content. This file could be used later to code (or you could simply copy and paste its content).</p>
<h2 id="heading-creating-the-repository-classes">Creating the repository classes</h2>
<p>Once we are connected, we could use the options available in the menu "repo".</p>
<p>It is the repo menu. It has its own configuration but it also requires a connection.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678568060124/5b74fc51-13b9-47bf-bd73-29fe8832b9c9.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>Use the "scan" option.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678568145348/0d27a985-7b81-4718-998a-ad2c0b12df22.png" alt class="image--center mx-auto" /></p>
<ol>
<li>it will show that it is reading the structure. It is an important part. The library scans for tables and creates a catalog about what tables exist, what structure, relations, etc.</li>
</ol>
</li>
</ul>
<ul>
<li><ol>
<li>Once it is done, then it will show [ok]</li>
</ol>
</li>
<li><p>For every new change, then you must run this command.</p>
</li>
</ul>
<p>And now, let's determine the folders. Use the "folder" option.</p>
<ul>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678568380722/f0c77974-6d56-4523-b987-6bd4a28596f4.png" alt class="image--center mx-auto" /></p>
<p>  Select the relative directory. My example is "repo".</p>
</li>
<li><p>Select the postfix of the class. If the class is called City, then the repository class will be called CityRepo.</p>
</li>
<li><p>The current path (for my example) is</p>
<ul>
<li>D:\www\currentproject\PdoOneORM\examples\example2/repo</li>
</ul>
</li>
<li><p>For the next step, we will need to configure Composer.</p>
<ul>
<li><p>It is part of my composer.json</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678568583864/589a77e4-b736-498e-9609-00952ae7a5e8.png" alt class="image--center mx-auto" /></p>
<p>  I will try to find a namespace that fits my route. In my case, it is my namespace. i.e:</p>
</li>
<li><p>folder: <strong>D:\www\currentproject\PdoOneORM\examples\</strong></p>
</li>
<li><p>namespace: <strong>eftec\examples</strong></p>
</li>
<li><p>Since my folder is <strong>D:\www\currentproject\PdoOneORM\examples\example2/repo</strong></p>
</li>
<li><p>then the namespace must be<br />  <strong>eftec\examples\example2\repo</strong></p>
</li>
</ul>
</li>
<li><p>If you do have not a path in composer, then save your configuration, close the program, then edit <strong>composer</strong> and re-open the program again.</p>
</li>
<li><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678568899788/74eea65b-62eb-4f23-a334-c0160ee1072c.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<p>So, we have configured:</p>
<ul>
<li><p>✅ connection</p>
</li>
<li><p>✅ folder</p>
</li>
<li><p>✅scan.</p>
</li>
</ul>
<p>So we could create the code. Use the option "create"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678568984620/e5e55e9a-ad79-4123-9064-ba955a205a4f.png" alt class="image--center mx-auto" /></p>
<p>It will populate the repo folder with many files</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678569069797/e9613e8e-0118-4fdb-8653-11dd829340de.png" alt class="image--center mx-auto" /></p>
<p>Mainly there are 3 kinds of files.</p>
<ul>
<li><p>Abstract classes. It will contain the definition of the table, indexes, relations, etc. You should not edit those files because if you "scan" again, it will rebuild this file.</p>
</li>
<li><p>Repo classes, is the file that you can edit.</p>
</li>
<li><p>Base class. There is a simple class (in this case called Sakila) that is used for all other classes. It has relations between classes.</p>
</li>
</ul>
<blockquote>
<p>Don't forget to save your configuration.</p>
</blockquote>
<h2 id="heading-using-the-repo-classes">Using the repo classes.</h2>
<p>In the same folder, write the next code: example1.php</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-keyword">include</span> <span class="hljs-keyword">__DIR__</span>.<span class="hljs-string">"/../../vendor/autoload.php"</span>; <span class="hljs-comment">// edit the path for the correct one.</span>

$cities=eftec\examples\example2\repo\CityRepo::toList();
var_dump($cities);
</code></pre>
<p>If you run this example, then it will fail because you are not connected to the database.</p>
<p>Do the next modification</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">use</span> <span class="hljs-title">eftec</span>\<span class="hljs-title">PdoOneORM</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">eftec</span>\<span class="hljs-title">examples</span>\<span class="hljs-title">example2</span>\<span class="hljs-title">repo</span>\<span class="hljs-title">CityRepo</span>;

<span class="hljs-keyword">include</span> <span class="hljs-keyword">__DIR__</span>.<span class="hljs-string">"/../../vendor/autoload.php"</span>; <span class="hljs-comment">// edit the path for the correct one.</span>

$conn= PdoOneORM::factoryFromArray([
    <span class="hljs-string">'databaseType'</span> =&gt; <span class="hljs-string">'mysql'</span>,
    <span class="hljs-string">'server'</span> =&gt; <span class="hljs-string">'127.0.0.1'</span>,
    <span class="hljs-string">'user'</span> =&gt; <span class="hljs-string">'root'</span>,
    <span class="hljs-string">'pwd'</span> =&gt; <span class="hljs-string">'abc.123'</span>,
    <span class="hljs-string">'database'</span> =&gt; <span class="hljs-string">'sakila'</span>,
]); <span class="hljs-comment">// you can include the PHP file generated previously or copy and paste its configuration.</span>
$conn-&gt;open(); <span class="hljs-comment">// opens the database connection. $conn is a singleton, so you don't need to open it every time you want to use.</span>
$conn-&gt;logLevel=<span class="hljs-number">3</span>; <span class="hljs-comment">// it is optional,</span>

$cities=CityRepo::toList(); <span class="hljs-comment">// $conn is injected automatically inside every "Repo" class.</span>
var_dump($cities);
</code></pre>
<p>It will show:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678569810168/f11854f3-8fef-47f7-ac1b-ea27c50e815e.png" alt class="image--center mx-auto" /></p>
<p>But we could do even more. In this case, the table "city" is related to the table "country".</p>
<p>Edit the line where you list the repo as follows:</p>
<pre><code class="lang-php">$cities=CityRepo::recursive([<span class="hljs-string">'/_country_id'</span>])-&gt;toList();
</code></pre>
<p>The function recursive will try to load this field. How do you know the name of the field? Every field indicated here starts with "/". If you look at the code of CityRepo, it will show every field:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678570042366/b5710132-aa8d-4d9f-bb6b-39413711bce5.png" alt class="image--center mx-auto" /></p>
<p>It says that "_*country_*id" is a many-to-one relational field. Also "__address" is another relational field (one-to-many)</p>
<p>You can fetch both tables as follow:</p>
<pre><code class="lang-php">$cities=CityRepo::recursive([<span class="hljs-string">'/_country_id'</span>,<span class="hljs-string">'/_address'</span>])-&gt;toList();
</code></pre>
<h2 id="heading-orm-or-not">ORM or not.</h2>
<p>ORM could make our life easiest but it could have some hidden costs.</p>
<ul>
<li><p>many-to-one relations are "join" in disguise.</p>
</li>
<li><p>"one-to-many" relations are multiple queries.</p>
</li>
<li><p>ORM also loads every row and sometimes the internal queries could be long</p>
</li>
</ul>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> address.address_id <span class="hljs-keyword">as</span> <span class="hljs-string">`/address_id`</span>,address.address <span class="hljs-keyword">as</span> <span class="hljs-string">`/address`</span>,address.address2 <span class="hljs-keyword">as</span> <span class="hljs-string">`/address2`</span>,address.district <span class="hljs-keyword">as</span> <span class="hljs-string">`/district`</span>,address.city_id <span class="hljs-keyword">as</span> <span class="hljs-string">`/city_id`</span>,address.postal_code <span class="hljs-keyword">as</span> <span class="hljs-string">`/postal_code`</span>,address.phone <span class="hljs-keyword">as</span> <span class="hljs-string">`/phone`</span>,address.last_update <span class="hljs-keyword">as</span> <span class="hljs-string">`/last_update`</span> <span class="hljs-keyword">from</span> address <span class="hljs-keyword">where</span> address.<span class="hljs-string">`city_id`</span> =<span class="hljs-string">'599'</span>
</code></pre>
<p>If we want performance or we simply want to show a table, then we could use a native query:</p>
<pre><code class="lang-php">$cities=CityRepo::query(<span class="hljs-string">'select * from city inner join country on city.country_id=country.country_id'</span>);
</code></pre>
<p>It will return the next fields:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678570427014/bcf13797-23f9-4f0d-8f08-a1533f858cf9.png" alt class="image--center mx-auto" /></p>
<p>While the result is similar to the ORM but the structure is different.</p>
<h2 id="heading-other-examples">Other examples</h2>
<pre><code class="lang-php"><span class="hljs-comment">// inserting</span>
$newCity=[<span class="hljs-string">'city'</span> =&gt; <span class="hljs-string">'new city'</span>,<span class="hljs-string">'country_id'</span> =&gt; <span class="hljs-number">105</span>];
CityRepo::insert($newCity);
<span class="hljs-comment">// updating</span>
$newCity[<span class="hljs-string">'city'</span>]=<span class="hljs-string">'name changed'</span>;
CityRepo::update($newCity);
<span class="hljs-comment">// deleting</span>
CityRepo::delete($newCity);
<span class="hljs-comment">// delete by id</span>
CityRepo::deleteById(<span class="hljs-number">100</span>);
</code></pre>
<p>There are more than +100 features available to use but they are the basic ones.</p>
<h2 id="heading-costs">Costs</h2>
<p><img src="https://cdn-icons-png.flaticon.com/512/2821/2821739.png" alt class="image--center mx-auto" /></p>
<p>Why not a framework?</p>
<ul>
<li><p>This library consists of 11 files</p>
</li>
<li><p>The complete dependency of this library is 28 files.</p>
</li>
<li><p>The example consists of 37 files.</p>
</li>
</ul>
<p>So, the whole project example is less than 100 files. It doesn't all the job as a framework but it is a start.</p>
<p>In comparison, PHPUnit alone has +500 files and a project in Laravel is over +6000 files.</p>
<blockquote>
<p>The more files, the slow to deploy, it uses more space, and PHP must deal with more files in the memory (OpCache must retain a catalog with every file). Even "Composer autoload" must have a huge file with all the files.</p>
</blockquote>
<p>Also, since it is a simple project, you could even deploy without using Composer, however, you must include the files on your own.</p>
<p>Plus, you can even use it inside a framework.</p>
<h2 id="heading-why-or-why-not-an-orm">Why or why not an ORM?</h2>
<p>Sometimes we want both cases. For example, for the frontend, we could use native operations because they are fast and we don't need the whole structure of the ORM, and for the backend, we could use the ORM because it is easy to work with it.</p>
<p>So about ORM, the answer depends, and usually, the solution is both.</p>
]]></content:encoded></item><item><title><![CDATA[Ubuntu 22, installing the email server]]></title><description><![CDATA[It is a fast and complete guide to installing an email server using Ubuntu 22 but it should work too with Ubuntu 16 and higher.
Installing postfix
Postfix is our tool that does the heavy-lifting. It will also install other services. What postfix does...]]></description><link>https://southprojects.com/ubuntu-22-installing-the-email-server</link><guid isPermaLink="true">https://southprojects.com/ubuntu-22-installing-the-email-server</guid><category><![CDATA[Ubuntu 22.04]]></category><category><![CDATA[postfix]]></category><category><![CDATA[email]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Fri, 03 Mar 2023 20:01:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677873212383/dc2eb1a3-3cda-4a3d-96d2-6e40166fbc6c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It is a fast and complete guide to installing an email server using Ubuntu 22 but it should work too with Ubuntu 16 and higher.</p>
<h2 id="heading-installing-postfix">Installing postfix</h2>
<p>Postfix is our tool that does the heavy-lifting. It will also install other services. What postfix does in the background is overly complex but we will only touch the surface of it.</p>
<pre><code class="lang-bash">apt install postfix
</code></pre>
<p>It will show the next screens:</p>
<ol>
<li>Internet sites:</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677871385708/68a9d660-0593-4301-a81c-0aa6577ca29f.png" alt class="image--center mx-auto" /></p>
<ol>
<li>select your domain. If you want a domain called john@domain.dom, then pick:</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677871434059/46f38485-69cf-48a0-9875-397b90f4000b.png" alt class="image--center mx-auto" /></p>
<ol>
<li>The postmaster (you can pick whatever you want to)</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677871485495/e52ed064-1e72-4d89-9401-a2720933fc91.png" alt class="image--center mx-auto" /></p>
<ol>
<li>And you can pick other domains</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677871540612/8257dec6-ca34-47ff-84bc-7051948411d8.png" alt class="image--center mx-auto" /></p>
<ol>
<li>Force sync? No</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677871560110/3f67fc66-e1c0-435b-bcdc-0891c0a4153f.png" alt class="image--center mx-auto" /></p>
<ol>
<li>Relay IP. Does not change it.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677871600238/5ffccf07-6756-4fbd-9583-f6fee5145590.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Mailbox size, you can set the file that you want to or zero for unlimited.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677931647042/913ff7cf-096c-4065-bebc-fab1b5d16034.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Delimiter. Set this values as default</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677931699689/965d2d7e-ad31-47a3-81f0-ab16b767e659.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Internet protocol. Usually "all" works but if you have troubles, then change it for "IPV4"</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677931742255/ab996a20-1641-4fd1-a105-6709625476e4.png" alt class="image--center mx-auto" /></p>
<p>And reload the service</p>
<pre><code class="lang-bash">systemctl reload postfix
</code></pre>
<p>You can re-configure the system using the next command (or you could edit the configuration file manually)</p>
<pre><code class="lang-bash">sudo dpkg-reconfigure postfix
</code></pre>
<h2 id="heading-editing-postfix">Editing Postfix</h2>
<p>Indicates the mail folder:</p>
<pre><code class="lang-bash">postconf -e <span class="hljs-string">'home_mailbox= Maildir/'</span>
</code></pre>
<p>And restart postfix.</p>
<pre><code class="lang-bash">sudo systemctl restart postfix
</code></pre>
<p>In the folder /etc/postfix, you could find many files. There are two important files, one is <strong>main.cnf</strong> and <strong>master.cnf</strong>.</p>
<h2 id="heading-firewall">Firewall</h2>
<p>You must allow the services to pass the firewall.</p>
<pre><code class="lang-bash">sudo ufw allow Postfix
</code></pre>
<p>If you want to receive emails, then you must open the port TCP/IP 25 from your firewall.</p>
<blockquote>
<p><strong>Note:</strong> If you are using AWS, then you must ask permission to Amazon (and open the firewall), otherwise it will not work. And as far as I know, Azure put the same restrictions. Many cloud providers could put their own restrictions, some simply deny the use of the port 25.</p>
<p>Most home connections block the port 25.</p>
</blockquote>
<p>How to test if the port is open?</p>
<p>In a different machine, runs the next command:</p>
<pre><code class="lang-bash">telnet &lt;external-ip&gt; 25
</code></pre>
<p>If you are using Windows, then you can use Putty (a free program) and try to do telnet using port 25.</p>
<h2 id="heading-create-the-mail-folders">Create the mail folders</h2>
<p>Log in with the user and run the next command</p>
<pre><code class="lang-bash">mkdir ~/Maildir
mkdir -p ~/Maildir/{cur,new,tmp}
chown -R USERNAME:USERNAME ~Maildir
</code></pre>
<p>Where username is your username</p>
<h2 id="heading-installing-a-client">Installing a client</h2>
<p>To install a client compatible with postfix, you can use Mutt.</p>
<pre><code class="lang-bash">yum install mutt
</code></pre>
<p>There are many clients but it is easy and minimalist.</p>
<p>The other popular client is s-nail but it is less intuitive.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/a/a1/Mutt.png" alt="Mutt (email client) - Wikipedia" /></p>
<h3 id="heading-sends-an-email-using-mutt">Sends an email using mutt</h3>
<blockquote>
<p><strong>Note:</strong> You must configure the DNS before you want to send email. It could work locally but it is better to test it with the DNS up and running.</p>
</blockquote>
<p>Open mutt</p>
<pre><code class="lang-bash">mutt
</code></pre>
<p>And select "m" (mail)</p>
<p>Fill in the information in the email. And finally, send it "y"</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677931252004/a48a4888-d615-4ef3-817f-0f3629c72b97.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-sends-an-email-using-the-cli">Sends an email using the cli</h2>
<p>You can send an email using the next command.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"body"</span> | mail -s <span class="hljs-string">"title"</span> &lt;your email&gt;
Configuring the DNS
</code></pre>
<p>How do you know that it is working?</p>
<p>You can check the log at:</p>
<pre><code class="lang-bash">cat /var/<span class="hljs-built_in">log</span>/mail.log
</code></pre>
<h2 id="heading-dns">DNS</h2>
<p>Finally, you will need to configure your DNS.</p>
<p>Go to the DNS configuration and enter the next information:</p>
<table><tbody><tr><td><p>type</p></td><td><p>name</p></td><td><p>content</p></td><td><p>priority</p></td></tr><tr><td><p>MX</p></td><td><p>&lt;your domain&gt;</p></td><td><p>&lt;your domain&gt;</p></td><td><p>10</p></td></tr><tr><td><p>TXT</p></td><td><p>_dmarc</p></td><td><p>v=DMARC1; p=none; rua=<a target="_blank" href="mailto:sender@&lt;domain">mailto:sender@&lt;domain</a>&gt;</p></td></tr><tr><td><p>TXT</p></td><td><p>&lt;your domain&gt;</p></td><td><p>v=spf1 ip4:&lt;your IP&gt; ~all</p></td><td><p> </p></td></tr></tbody></table>

<p>Change &lt;domain&gt; by your domain and &lt;your IP&gt; for the private IP of the server.</p>
<blockquote>
<p><strong>Note</strong>: Gmail did some changes to the SPF entries. It does not accept includes or domain names, only IPs.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[How to save your SSD in Windows.]]></title><description><![CDATA[When Windows Starts, it saves a lot of files on the hard disk, including log files. Windows is not a savvy operating system.
Windows writes those log files in the next folder:
 
%SystemRoot%\System32\Winevt\Logs

Most of those files weigh 1KB, so it ...]]></description><link>https://southprojects.com/how-to-save-your-ssd-in-windows</link><guid isPermaLink="true">https://southprojects.com/how-to-save-your-ssd-in-windows</guid><category><![CDATA[Windows]]></category><category><![CDATA[ssd]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Mon, 27 Feb 2023 12:04:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677499160106/f85cb775-21d7-4980-abf5-87736c26427d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When Windows Starts, it saves a lot of files on the hard disk, including log files. Windows is not a savvy operating system.</p>
<p>Windows writes those log files in the next folder:</p>
<div class="hn-embed-widget" id="widget1"></div><p> </p>
<p><code>%SystemRoot%\System32\Winevt\Logs</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677496659809/29085683-c5c0-47d6-a882-d3d180c121ca.png" alt class="image--center mx-auto" /></p>
<p>Most of those files weigh 1KB, so it does not affect and impact the performance of the hard disk. Windows simply writes a part of the code. However, we are not using a hard disk anymore but SSD.</p>
<p>When we use a hard disk, then the Log Event does the next job:</p>
<ul>
<li><p>It reads the file.</p>
</li>
<li><p>And it adds the next log registry in the last disk block of the log file</p>
</li>
<li><p>If the block is full, then it creates a new block.</p>
</li>
</ul>
<p>When we use an SSD, the Log Event does the next job:</p>
<ul>
<li><p>It reads the file</p>
</li>
<li><p>And it modifies the last disk block. SSD has its own blocks that are also modified. Every modification wears out the block. The SSD drive could also trim the block by moving to another part of the disk and wearing the SSD but avoiding wearing the same block many times.</p>
</li>
<li><p>If the block is full, then it creates a new block. If the SSD block is also full, then it creates a new block.</p>
</li>
</ul>
<h2 id="heading-size">Size</h2>
<p>Now, let's say the size of the log is 1kb. That is the logical size, not the physical size. The partition system works in blocks of 4kb, so every time we write a file less or equal to 4k, we use 4kb. I.e. our log is 4kb or more.<br />You can check the size using PowerShell</p>
<p><code>Get-CimInstance -ClassName Win32_Volume | Select-Object Label, BlockSize | Format-Table -AutoSize</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677497979769/83e4a79b-bbee-4eb8-a398-e95b6ecdd8fc.png" alt class="image--center mx-auto" /></p>
<p>But the SSD has its own blocks. The common size is 512KB. So, if our log is 1k, then we are impacting the whole 512KB SSD block.</p>
<p>Even if the log does not change in size, then every modification will still impact this 512KB block.</p>
<h3 id="heading-event-log">Event Log</h3>
<p>Windows uses over 300 event log files. However, not all logs are written every day. However, at least 80 logs are written every day.</p>
<p>So, in the worse case, we are writing 80 SSD blocks every day, and sometimes it is hitting it constantly. The event log is an SSD killer, no matter if you are using it or not the computer, it is constantly writing files in the log files.</p>
<h2 id="heading-but-what-i-can-do">But What I can do?</h2>
<p>It is not possible to disable the service of the event log. However, we could limit its usage.</p>
<p>If you open the Event Viewer, then you will see that there are 5 log files. In fact, there are many more hidden in Application and Services Log.</p>
<p><img src="https://www.howtogeek.com/wp-content/uploads/2017/11/ev_top.png?height=200p&amp;trim=2,2,2,2" alt="What Is the Windows Event Viewer, and How Can I Use It?" /></p>
<p>The main log files can't be disabled but we can limit it</p>
<p>If you go to the property, then we could limit its size. The size makes sense for a conventional hard disk but not for an SSD. So, we don't want to limit the size but to limit any writing. So, we should use the option "Do not overwrite event". This does the next job: if the log file is filled, then it stops writing.</p>
<p><img src="https://social.technet.microsoft.com/Forums/getfile/1541215" alt="BUG: Windows Log files Unable to &quot;Overwrite events as needed&quot; with GPO  applied on Server 2019" /></p>
<p>Another alternative is to send the log to "nul" file. I have not tested it but in theory, it should work.</p>
<p>Now, if you open Application And Services Log -&gt; Microsoft, you will see that there are MANY log files used by different programs and services. We could disable each file separately but it will take a lot of time.</p>
<p>EventLogChannelsVIew is a free program and it works to disable the rest of the logs.</p>
<p><img src="https://www.nirsoft.net/utils/eventlogchannelsview.png" alt="View / Disable / Enable / Clear event log channels" /></p>
<p>This program is unable to disable all logs but it works with most of them.</p>
<ul>
<li><p>Select all the channels enabled.</p>
</li>
<li><p>Right button -&gt; Disable. It could show many "error 87" but it will work with most channels.</p>
</li>
</ul>
<h3 id="heading-security">Security</h3>
<p>But, is it safe to disable the event log? The event log gives security if anybody reads and analyzes the log.</p>
<p><strong>Question</strong>: How many times have you read the log files?</p>
<p>If you work in a managed infrastructure (Domain), then the system administrator will read the file. However, in this case, the sysadmin will not allow you to edit the event log.</p>
<p>Let's say you usually don't read the log file but you have some trouble with a program or service and you need to read the log file. It is not a problem. In case you need to read the log, then you can enable it back.</p>
<h2 id="heading-end-note">End note:</h2>
<p>It works with a simple exception: <strong>Security.evtx</strong></p>
<p>I tried to limit the writing in security.evtx (Security)</p>
<ul>
<li><p>Limiting the size: No, it doesn't work</p>
</li>
<li><p>Changing the file: Not, it doesn't work.</p>
</li>
<li><p>Disabling it: Unable to disable it.</p>
</li>
</ul>
<p>While the security log hasn't added a new entry, the file somehow has been edited. I think Microsoft is doing something "undocumented" again.</p>
<p><img src="https://preview.redd.it/ignfnvvnlqn91.jpg?auto=webp&amp;s=bf4e42bf1e10e4c38aaf459eac0764c9bb56042c" alt="r/linuxmemes" /></p>
]]></content:encoded></item><item><title><![CDATA[Coding: are mechanical keyboards good for coding?]]></title><description><![CDATA[Spoiler: Long story short, no.
The best keyboard for a programmer is where the programmer could code for an entire day without feeling tired and commit fewer mistakes.
Type of keyboards
Mechanical keyboard

Mechanical. And it is divided into differen...]]></description><link>https://southprojects.com/coding-are-mechanical-keyboards-good-for-coding</link><guid isPermaLink="true">https://southprojects.com/coding-are-mechanical-keyboards-good-for-coding</guid><category><![CDATA[keyboard]]></category><category><![CDATA[coding]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Sun, 26 Feb 2023 12:04:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677413028550/e06b9f68-057b-4ee5-b662-88733b0b2113.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Spoiler: <mark>Long story short, no.</mark></p>
<p>The best keyboard for a programmer is where the programmer could code for an entire day without feeling tired and commit fewer mistakes.</p>
<h2 id="heading-type-of-keyboards">Type of keyboards</h2>
<h3 id="heading-mechanical-keyboard">Mechanical keyboard</h3>
<ul>
<li><p>Mechanical. And it is divided into different subcategories depending on the kind of keyboard, such as blue, yellow, etc.</p>
</li>
<li><p><img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fwww.mechanicalkeyboards.com%2Fshop%2Fimages%2Fproducts%2Flarge_FC900REYBPD_2.jpg&amp;f=1&amp;nofb=1&amp;ipt=88ded831ece00ce96d3855cf446a675c93666991fa9a9512a1ab62989df9a447&amp;ipo=images" alt="Leopold FC900R Yellow/Blue PD Double Shot PBT Black Case Mechanical ..." /></p>
</li>
</ul>
<p>So, what is the difference? There are many, including the quality, but in short, it is separate in the weight of the keys and the noise. And is when mechanical keyboards are not fit for programming, they are heavy and noisy. There are some keys that are less heavy and noisy but <strong>they are still consistently noisy in comparison with the other kind of keyboards.</strong></p>
<p>As I mentioned, there are different kinds of keys, such as yellow, brown, etc. Some of them are more silent however, they consistently more noise than membranes or scissors, i.e. <strong>they are silent in comparison with other mechanical keyboards, not other types of keyboards.</strong></p>
<p>Also, they are aimed at gamers, so they are focused on lights, macros, and other features that a non-gamer will not enjoy it. Several of them have fewer keys so they use less space. It is ok for gamers but bad for coders. <strong>You don't want a short keyboard.</strong></p>
<p><img src="https://archive.smashing.media/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/3e96a6e1-0296-4b93-b160-021226343749/mechanical-keyboards-dsa-ferrous.jpg" alt="A Complete Guide To Mechanical Keyboards — Smashing Magazine" /></p>
<p>It is amazing how some coders recommend this kind of keyboard. They are noisy and heavy and even the best type of mechanical keys are not for hours of coding.</p>
<h3 id="heading-membrane-keyboard">Membrane keyboard</h3>
<p><img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fi1.wp.com%2Fwww.nelson-miller.com%2Fwp-content%2Fuploads%2F2018%2F10%2FMembrane_keyboard-1233.jpg%3Ffit%3D800%252C583%26ssl%3D1&amp;f=1&amp;nofb=1&amp;ipt=01c14ad5873a879157d6ba9ab66fe59154e85064eaa5c55cde4efc7e762ea524&amp;ipo=images" alt="Should I Choose a Flat-Panel or Full-Travel Membrane Keyboard? - Nelson ..." /></p>
<p>Membrane keyboards are lightweight and consistently less noisy. Also, they are cheaper. However, it brings some problems:</p>
<ul>
<li><p>Since they are lightweight, then it is easy to commit mistakes because (and it depends on the kind of membrane), they are too lightweight and there is little feedback.</p>
</li>
<li><p>Some people say the feedback feels mushy but it depends on the kind of membrane.</p>
</li>
<li><p>Other membranes are too lightweight and they register every touch like this one:</p>
</li>
</ul>
<p><img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fi1.wp.com%2Fwww.keypad-fd.com%2Fwp-content%2Fuploads%2F2020%2F09%2FCustom-Membrane-Keyboard-Suppliers.png%3Ffit%3D2272%252C1704%26ssl%3D1&amp;f=1&amp;nofb=1&amp;ipt=d16f08263f0841b9bba8cbca4b9b9868e686125dc52a16d5b995ef6fd04988a1&amp;ipo=images" alt="Custom Membrane Keyboard: The Sourcing Checklist | 2020" /></p>
<p>Also, membrane keyboards have another problem, they are cheap, so the market is for cheap keyboards, i.e. disposables. It is hard to find a premium membrane keyboard, and when you find one, they are absurdly expensive.</p>
<h3 id="heading-optical-keyboards">Optical keyboards</h3>
<p>There is a new variety of mechanical keyboards: optical. In short, they are mostly a "gimmick", they are far more durable than a mechanical keyboard but they are noisier and they are similarly heavy. They are also more expensive than a mechanical keyboards. They are not for coders unless the coder prefers duration over anything else.</p>
<p><img src="https://geargaminghub.com/wp-content/uploads/2021/04/Mechanical-vs-Optical-keyboard-switches.jpg" alt="Mechanical Vs Optical Switches: What's The Difference ⋆ Gear Gaming Hub" /></p>
<h3 id="heading-scissors">Scissors</h3>
<p><img src="https://preview.redd.it/lyd5md4v3q351.jpg?auto=webp&amp;s=718f32b4e8adacfc40c2523dbde86583d1a3ccd5" alt="When Yoda says there is another... could he actually be referring to  Anakin/Vader? Right as Luke is taking off, Obi-Wan says “that boy is our  last hope”. Conveniently, right as Yoda says “" /></p>
<p>Scissor keyboards are a mix between a membrane keyboard and some light profile mechanical keyboards. They are mostly used in notebooks. They are less noisy, and lightweight but it has feedback.</p>
<p><img src="https://miro.medium.com/max/5120/1*OBhTy-auDeaqK9BAbEkypA.jpeg" alt /></p>
<p>Apple calls it "butterfly" but it is the same technology with a small change. However, the <strong><mark>duration could be bad</mark></strong>, and they are reserved commonly for notebooks. <strong>Currently, they are the best keyboard for coding. However, they are not as popular for desktops and only a few companies make them.</strong></p>
<h3 id="heading-and-another-one-mechanical-keyboard-low-profile">And another one: Mechanical Keyboard low profile</h3>
<p>There is a new set of mechanical keyboards called low-profile. They are less noisy and more lightweight than their other counterpart. However, they are still "experimental" so you only find a couple of companies doing it. They are expensive.</p>
<p><img src="https://cdn.shopify.com/s/files/1/0059/0630/1017/files/low_profile.jpg?v=1604045601" alt="How We Designed the Low Profile Optical Switch Differently" /></p>
<h3 id="heading-in-resume">In resume</h3>
<ul>
<li><p>Scissors if you don't mind duration. It has feedback and they are silent and lightweight.</p>
</li>
<li><p>Mechanical keyboards "low-profile", they are the future but I hope the big companies will start adopting it.</p>
</li>
<li><p>Membrane keyboards are cheap and easy to find however it is hard to find a premium model.</p>
</li>
<li><p>Mechanical keyboards, they are expensive, heavy, and noisy but they have feedback and are long-lasting</p>
</li>
<li><p>Optical keyboards, they are even more expensive and noisy but they are long-lasting and they have a feedback</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Code First does not make any sense.]]></title><description><![CDATA[I was developing my ORM and I found the next problem, should I allow code first or not? And it was my conclusion.
What is Code First anyways?
When we want to use an ORM (Object Relational Model) in our code, we have the next options:

Create the data...]]></description><link>https://southprojects.com/code-first-does-not-make-any-sense</link><guid isPermaLink="true">https://southprojects.com/code-first-does-not-make-any-sense</guid><category><![CDATA[database]]></category><category><![CDATA[orm]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[General Advice]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Sun, 26 Feb 2023 01:36:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677375434366/fae69870-c887-4c8b-908c-528765b07a1f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was developing my ORM and I found the next problem, should I allow code first or not? And it was my conclusion.</p>
<h1 id="heading-what-is-code-first-anyways">What is Code First anyways?</h1>
<p>When we want to use an ORM (Object Relational Model) in our code, we have the next options:</p>
<ul>
<li><p>Create the database, then create the code and make it both work in synchronization. It is really prone to mistakes, for example, the code could understand that the "id" field is an int, and the database understands that the column "id" is an integer, but depending on the engine, it could not be completely exact and maybe the field "id" must be a long.</p>
</li>
<li><p>Create the database, then self-generate the code that matches the database. It is called "Database First".</p>
</li>
<li><p>Create the code, then it will create the database. It is called "Code First".</p>
</li>
</ul>
<p>When we create code first, then the code is in charge to determine how the database will be created and populated.</p>
<p>For example, let's assume the next pseudo-code:</p>
<pre><code class="lang-json">{
   <span class="hljs-attr">"table"</span>:<span class="hljs-string">"Customers"</span>
    ,<span class="hljs-attr">"fields"</span>:[
         <span class="hljs-string">"id"</span>:<span class="hljs-string">"int"</span>
         ,<span class="hljs-string">"name"</span>:<span class="hljs-string">"string"</span>
         ]
}
</code></pre>
<p>This code will assume that we need to create a table called customer with two fields.</p>
<p>So, we run the generation of the database, and it will build the database, i.e. <strong>We are reinventing the wheel!!</strong>.</p>
<p>Now, let's say that the table is more complex.</p>
<p>A table could contain the next "components"</p>
<ul>
<li><p>the definition of the table</p>
<ul>
<li>and it could contain a lot of stuff, from the tablespace, the type of database, etc.</li>
</ul>
</li>
<li><p>fields</p>
<ul>
<li>And depending on the field, it could contain, validations, default value, auto-generate value, and several other definitions.</li>
</ul>
</li>
<li><p>indexes</p>
</li>
<li><p>keys</p>
</li>
<li><p>etc.</p>
</li>
</ul>
<p>Some ORM allows a fine-grained definition of the database but it still could miss a lot of definitions (because the ORM is a generation of many databases, or it is compatible with some older version, etc.). But even if we could generate our definition in code, the task could be in some cases overwhelming. Most code-first code simply left the basic definition.</p>
<h2 id="heading-so-what-is-the-alternative">So, what is the alternative?</h2>
<p><strong>Database-First</strong></p>
<p>Why? Simple, because most databases are harden-tested to do exactly that task. Do you want a GUI? well, there are many tools that do that.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677373874725/24dba85d-499a-40e1-b218-9fd690ef1434.png" alt class="image--center mx-auto" /></p>
<p>Do you want to code, then SQL is decades old (and SQL is "standard").</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`malibu`</span>.<span class="hljs-string">`Customers`</span> (
  <span class="hljs-string">`id`</span> <span class="hljs-built_in">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`Name`</span> <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">45</span>) <span class="hljs-literal">NULL</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>));
</code></pre>
<p>There are some problems with Database-First but they have a solution</p>
<ul>
<li><p>Updating the database. If we change the database, then our code will need to be recreated. It is not a big deal since most of the code that we need to update is generated automatically.</p>
</li>
<li><p>Code-first gives more control to the developer. That is true and false. True because it allows more customization on the side of the code. But false because the database does not change and finally the database is who does the job.</p>
</li>
</ul>
<p>Let's say our database has a foreign key between two tables.</p>
<p>The database understands the concept of foreign keys, and "one to many" and "many to one" relations. But in code, we could understand more concepts such as "one to one", "many to many" and others.</p>
<p>However, the problem is not because database but the lack of some tools that convert the database into code and it doesn't allow configuring it manually.</p>
<p>So, the best of all worlds is Database-First AND a proper tool that does not simply take the database and creates the code but also allows some kind of customization.</p>
]]></content:encoded></item><item><title><![CDATA[Cloudflare is testing my patience.]]></title><description><![CDATA[I there, I use Cloudflare for some of my servers. I tried using the cache system but while it works, it also adds more time to the load of the page (TTFB *) so it didn’t work for me at least on most websites. But, I still use the DNS service which is...]]></description><link>https://southprojects.com/cloudflare-is-testing-my-patience</link><guid isPermaLink="true">https://southprojects.com/cloudflare-is-testing-my-patience</guid><category><![CDATA[cloudflare]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Sun, 26 Feb 2023 00:51:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677375545920/eecf2249-0ed7-41ee-b677-467ee6604152.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><img src="https://miro.medium.com/max/875/0*wJRpHjZZwVe2ExBX.jpg" alt /></p>
<p>I there, I use Cloudflare for some of my servers. I tried using the cache system but while it works, it also adds more time to the load of the page (TTFB *) so it didn’t work for me at least on most websites. But, I still use the DNS service which is available to use without cache. So I use it mainly for the DNS and only a few pages use the cache. Nothing wrong here.</p>
<blockquote>
<p><em>(\</em>) CloudFlare says that the TTFB delay is not a big issue. I think the opposite.*</p>
</blockquote>
<p>However, recently I found the next problems:</p>
<ul>
<li><p>Cloudflare affects somehow the content of some pages even when you are not caching it. How, and why? I don’t know but Google Bots shows me some nonexistent links that were generated by CloudFlare.</p>
</li>
<li><p>And now, somebody is using the IP of Cloudflare to probe one of my servers.</p>
</li>
</ul>
<p><img src="https://miro.medium.com/max/875/1*VKZePQvfKle913WC_ae86g.png" alt /></p>
<ul>
<li><p>The IP is owned by CloudFlare <a target="_blank" href="https://www.cloudflare.com/ips-v4">https://www.cloudflare.com/ips-v4</a></p>
</li>
<li><p>And my website does not use WordPress in any way and there is no file (or folded) with such a name. Also, there is no content or link to that file. I double-checked that.</p>
</li>
</ul>
<p>So, what is going on with CloudFlare?</p>
<p><img src="https://miro.medium.com/max/800/0*rJClktD9pG8pnVQu.jpg" alt /></p>
<p>I don’t think CloudFlare is trying to hack my server and maybe somebody is using CloudFlare as some kind of proxy. But, since I don’t really know what is going on, then that IP of CloudFlare was banned from my system.</p>
<p>In any case, I think it is time to move out of CloudFlare.</p>
<p><code>Update: List of IPS banned so far.</code></p>
<table><tbody><tr><td><p>172.70.100.126</p></td></tr><tr><td><p>172.70.100.162</p></td></tr><tr><td><p>172.70.100.170</p></td></tr><tr><td><p>172.70.100.197</p></td></tr><tr><td><p>172.70.110.139</p></td></tr><tr><td><p>172.70.110.186</p></td></tr><tr><td><p>172.70.110.187</p></td></tr><tr><td><p>172.70.110.233</p></td></tr><tr><td><p>172.70.111.28</p></td></tr><tr><td><p>172.70.114.144</p></td></tr><tr><td><p>172.70.114.41</p></td></tr><tr><td><p>172.70.126.54</p></td></tr><tr><td><p>172.70.126.55</p></td></tr><tr><td><p>172.70.127.115</p></td></tr><tr><td><p>172.70.127.116</p></td></tr><tr><td><p>172.70.127.93</p></td></tr><tr><td><p>172.70.127.94</p></td></tr><tr><td><p>172.70.130.108</p></td></tr><tr><td><p>172.70.130.136</p></td></tr><tr><td><p>172.70.130.153</p></td></tr><tr><td><p>172.70.130.236</p></td></tr><tr><td><p>172.70.131.149</p></td></tr><tr><td><p>172.70.131.150</p></td></tr><tr><td><p>172.70.134.109</p></td></tr><tr><td><p>172.70.175.148</p></td></tr><tr><td><p>172.70.178.102</p></td></tr><tr><td><p>172.70.178.103</p></td></tr><tr><td><p>172.70.178.168</p></td></tr><tr><td><p>172.70.178.169</p></td></tr><tr><td><p>172.70.178.59</p></td></tr><tr><td><p>172.70.188.63</p></td></tr><tr><td><p>172.70.189.129</p></td></tr><tr><td><p>172.70.207.11</p></td></tr><tr><td><p>172.70.218.100</p></td></tr><tr><td><p>172.70.218.101</p></td></tr><tr><td><p>172.70.218.54</p></td></tr><tr><td><p>172.70.218.55</p></td></tr><tr><td><p>172.70.250.237</p></td></tr><tr><td><p>172.70.38.125</p></td></tr><tr><td><p>172.70.42.222</p></td></tr><tr><td><p>172.70.85.24</p></td></tr><tr><td><p>172.70.85.25</p></td></tr><tr><td><p>172.70.91.203</p></td></tr><tr><td><p>172.70.91.204</p></td></tr><tr><td><p>172.71.102.163</p></td></tr><tr><td><p>172.71.102.41</p></td></tr><tr><td><p>172.71.118.20</p></td></tr><tr><td><p>172.71.122.61</p></td></tr><tr><td><p>172.71.142.166</p></td></tr><tr><td><p>172.71.142.167</p></td></tr><tr><td><p>172.71.146.88</p></td></tr><tr><td><p>172.71.146.89</p></td></tr><tr><td><p>172.71.160.4</p></td></tr><tr><td><p>172.71.160.8</p></td></tr><tr><td><p>172.71.182.150</p></td></tr><tr><td><p>172.71.182.218</p></td></tr><tr><td><p>172.71.182.90</p></td></tr><tr><td><p>172.71.198.133</p></td></tr><tr><td><p>172.71.210.90</p></td></tr><tr><td><p>172.71.218.72</p></td></tr><tr><td><p>172.71.222.238</p></td></tr><tr><td><p>172.71.254.42</p></td></tr><tr><td><p>172.71.254.43</p></td></tr><tr><td><p>172.71.254.58</p></td></tr><tr><td><p>172.71.254.64</p></td></tr><tr><td><p>172.71.254.65</p></td></tr><tr><td><p>172.71.82.4</p></td></tr><tr><td><p>172.71.94.151</p></td></tr><tr><td><p>172.71.94.154</p></td></tr><tr><td><p>172.71.94.3</p></td></tr><tr><td><p>172.71.94.98</p></td></tr><tr><td><p>172.71.98.179</p></td></tr><tr><td><p>172.71.98.223</p></td></tr><tr><td><p>172.71.99.2</p></td></tr></tbody></table>]]></content:encoded></item><item><title><![CDATA[It is my first article on hashnode.]]></title><description><![CDATA[Hi there. It is just an example using hashnode.

More articles will come next.
%%[]]]></description><link>https://southprojects.com/it-is-my-first-article-on-hashnode</link><guid isPermaLink="true">https://southprojects.com/it-is-my-first-article-on-hashnode</guid><category><![CDATA[first post]]></category><dc:creator><![CDATA[Jorge Castro]]></dc:creator><pubDate>Wed, 22 Feb 2023 19:40:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677094819482/68afd794-ff15-438e-a056-c44f478e1f48.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi there. It is just an example using hashnode.</p>
<p><img src="https://i.cbc.ca/1.5359228.1577206958!/fileImage/httpImage/image.jpg_gen/derivatives/16x9_940/smudge-the-viral-cat.jpg" alt="Ottawa's latest Instagram star is a middle-aged white cat that doesn't care  for salad | CBC News" /></p>
<p>More articles will come next.</p>
<p>%%[] </p>
<div class="hn-embed-widget" id="widget1"></div><p> </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677506390261/d9d432de-94e8-4416-a5fe-a9430b7a3faa.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item></channel></rss>