<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: andersnicolai</title>
    <description>The latest articles on Forem by andersnicolai (@nicolaimagnussen).</description>
    <link>https://forem.com/nicolaimagnussen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F955740%2Ff198b189-9838-402c-91de-c8d471601c42.jpeg</url>
      <title>Forem: andersnicolai</title>
      <link>https://forem.com/nicolaimagnussen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nicolaimagnussen"/>
    <language>en</language>
    <item>
      <title>using traefik to your advantage</title>
      <dc:creator>andersnicolai</dc:creator>
      <pubDate>Tue, 24 Sep 2024 05:16:34 +0000</pubDate>
      <link>https://forem.com/nicolaimagnussen/using-traefik-to-your-advantage-3jfg</link>
      <guid>https://forem.com/nicolaimagnussen/using-traefik-to-your-advantage-3jfg</guid>
      <description></description>
      <category>webdev</category>
      <category>beginners</category>
      <category>marketing</category>
    </item>
    <item>
      <title>Why clean code matters!</title>
      <dc:creator>andersnicolai</dc:creator>
      <pubDate>Tue, 18 Jun 2024 16:08:41 +0000</pubDate>
      <link>https://forem.com/nicolaimagnussen/why-clean-code-matters-2fkn</link>
      <guid>https://forem.com/nicolaimagnussen/why-clean-code-matters-2fkn</guid>
      <description>&lt;p&gt;In various consultancy projects, I have noticed lately that the same thing keeps repeating itself: clustered code. What do I mean by that? Well, let me put it this way. When you code, you should think about clean code. Yes, I know, one more person out there talking about clean code. Why should you listen to me? Since I was 12 years old, I was interested in computers and how things work. When I became 15 years old, I started watching Pluralsight, a bunch of videos on how to do MVVM, MVC, architecture, etc. I watched tons of videos, but I did not know how to program yet. I followed along, but I remember not understanding a lot of what was going on.&lt;/p&gt;

&lt;p&gt;In the past years, I've been working as an architect and senior software developer for various companies. My background is in computer engineering and IT apprenticeship. And I try to share with you what I know, as you all know, to help people, but also to get exposure like all the people out there on LinkedIn. Yeah, they don't love writing as much as you think; it's purely a business model. But that doesn't matter, right? So here it goes. Hopefully, one day you'll buy one of my products. ;)&lt;/p&gt;

&lt;p&gt;Now, let me tell you what I have seen lately in different projects. I think that the reason clean code isn't always applied isn't necessarily because people don't have the knowledge. It's often about strict deadlines and pressure from different projects. If you're a software engineer like me or a project manager, you know there are certain constraints and time pressures needed for a project to be successful.&lt;/p&gt;

&lt;p&gt;In order to deliver to the client, and even when working in-house, you face deadlines and different stakeholders. Companies often operate on a subscription model where clients expect new features regularly. This creates a lot of challenges. Developers and project planners need to keep the project moving forward without falling into the trap of architectural debt because they didn't have enough time to think through the solution properly.&lt;/p&gt;

&lt;p&gt;Once that problem is there, it’s really hard to go back and fix it. From my experience, people don’t often go back to refactor their projects—at least not the people I know. Let me know if you’re different. There are various things you can do to refactor, and it helps a lot, but the problem is that it’s not prioritized. If the code is working and the client is happy, refactoring isn't on the top of the list. But let’s think two or three years ahead. What will happen once the code becomes more and more clustered?&lt;/p&gt;

&lt;p&gt;You might end up hiring a lot of developers to overhaul the monolithic architecture into a microservices architecture, which costs a lot of money. This is why you should think about clean code—not just when you start a project, not just when you wake up, but all the time. Because eventually, it will come back to bite you if you don't apply it.&lt;/p&gt;

&lt;p&gt;Practical Strategies for Clean Code&lt;/p&gt;

&lt;p&gt;Consistent Code Reviews&lt;br&gt;
Regular code reviews ensure adherence to coding standards and catch potential issues early.&lt;/p&gt;

&lt;p&gt;Automated Testing&lt;br&gt;
Implementing automated testing, including unit tests, integration tests, and end-to-end tests, helps identify problems before they make it into production.&lt;/p&gt;

&lt;p&gt;Refactoring Regularly&lt;br&gt;
Set aside time in your project schedule specifically for refactoring to prevent technical debt from accumulating and to keep your codebase maintainable.&lt;/p&gt;

&lt;p&gt;Adopting SOLID Principles&lt;br&gt;
The SOLID principles (Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion) provide a framework for writing clean and maintainable code.&lt;/p&gt;

&lt;p&gt;Clear Documentation&lt;br&gt;
Writing clear and concise documentation helps new developers understand the codebase more quickly and reduces the likelihood of introducing errors.&lt;/p&gt;

&lt;p&gt;Pair Programming&lt;br&gt;
Pair programming allows two developers to work together on the same code, catching mistakes early and sharing knowledge among team members.&lt;/p&gt;

&lt;p&gt;Long-Term Benefits of Clean Code&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Reduced Maintenance Costs&lt;/em&gt;&lt;br&gt;
Clean code is easier to maintain, reducing time and money spent on fixing bugs and implementing new features.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enhanced Readability and Understandability&lt;/em&gt;&lt;br&gt;
A clean codebase is easier to read and understand, crucial for onboarding new developers and for long-term project sustainability.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Improved Performance&lt;/em&gt;&lt;br&gt;
Well-structured code leads to better performance by avoiding unnecessary complexity and optimizing resource usage.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Greater Scalability&lt;/em&gt;&lt;br&gt;
Clean code allows for easier scaling of applications, simplifying the process of adding new features and adapting to changing requirements.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Increased Developer Satisfaction&lt;/em&gt;&lt;br&gt;
Working with clean code reduces frustration and increases job satisfaction for developers, leading to higher productivity and lower turnover rates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of Messy Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;security\Session&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;addSkill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Application&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$userInput&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$userInput&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;preg_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/[^0-9,.]/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$userInput&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'checkpoint'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;minimumRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'session'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
    &lt;span class="nv"&gt;$userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'profile'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'easyJobAddressId'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userInput&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'ok'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'dbs'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'appMySql'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'skills'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s1"&gt;'skillId'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$userInput&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="s1"&gt;'userId'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s1"&gt;'rank'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'ok'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Refactored Code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The refactored code adheres to clean code principles by breaking down responsibilities, using dependency injection, and following SOLID principles.&lt;/p&gt;

&lt;p&gt;Dependency Injection and Constructor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;UserRoleService&lt;/span&gt; &lt;span class="nv"&gt;$userRoleService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;RequestStack&lt;/span&gt; &lt;span class="nv"&gt;$requestStack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;UserRepository&lt;/span&gt; &lt;span class="nv"&gt;$userRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;EasyJobServiceInterface&lt;/span&gt; &lt;span class="nv"&gt;$easyJobService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;SkillsRepository&lt;/span&gt; &lt;span class="nv"&gt;$skillsRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;AppDataService&lt;/span&gt; &lt;span class="nv"&gt;$appDataService&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;userRoleService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$userRoleService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;requestStack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$requestStack&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;userRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$userRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;easyJobService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$easyJobService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;skillsRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$skillsRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;appDataService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$appDataService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By injecting dependencies, we ensure that each class has a single responsibility and can be easily tested and maintained.&lt;/p&gt;

&lt;p&gt;Single Responsibility for Adding Skills&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="na"&gt;#[Route('/profile/experience/add', name: 'profile_experience_add', methods: ['POST'])]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;addExperience&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;JsonResponse&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;denyAccessUnlessGranted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ROLE_USER'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$skillId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;is_numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$skillId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'error'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Invalid skill ID'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;appDataService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addSkillToUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$skillId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'ok'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'added'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we use a dedicated method to handle the addition of skills. It ensures validation and follows a clean, concise structure.&lt;/p&gt;

&lt;p&gt;Separation of Concerns&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nv"&gt;$allSkills&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;$skills&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_fill_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$allSkills&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$userSkills&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;appDataService&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getSkillsByUserId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userSkills&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$skill&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$skillId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$skill&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getSkillId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;array_key_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$skillId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$skills&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$skills&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$skillId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we use appDataService to decouple the system.&lt;br&gt;
By separating concerns, we keep each method focused on a single task, making the code easier to read and maintain.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;In conclusion, always think about clean code. It might not seem urgent now, but neglecting it can lead to significant problems down the line. Prioritizing clean code will save time, money, and headaches in the future. Refactoring regularly and adhering to coding standards are key to maintaining a healthy codebase. Remember, the effort you put into writing clean code today will pay off in the long run, making your projects more scalable, maintainable, and enjoyable to work on.&lt;/p&gt;

</description>
      <category>cleancode</category>
      <category>architecture</category>
      <category>php</category>
      <category>singleresponsibility</category>
    </item>
    <item>
      <title>How to configure Pulumi using YAML Config Files</title>
      <dc:creator>andersnicolai</dc:creator>
      <pubDate>Sun, 16 Jun 2024 18:56:15 +0000</pubDate>
      <link>https://forem.com/nicolaimagnussen/how-to-configure-pulumi-using-yaml-config-files-2nfm</link>
      <guid>https://forem.com/nicolaimagnussen/how-to-configure-pulumi-using-yaml-config-files-2nfm</guid>
      <description>&lt;p&gt;How to configure Pulumi using YAML Config Files&lt;/p&gt;

&lt;p&gt;When working with Pulumi the other day, I noticed that there are some crucial steps in the documentation which were lacking.&lt;/p&gt;

&lt;p&gt;For example when you have to use the YAML file to configure your environment.&lt;/p&gt;

&lt;p&gt;I even asked in the Slack forum, the official channel of Pulumi Engineers, and I dropped a question, which led to more confusion. After some time I found out the way they had done it. And his answer were the one who helped me. This is taken from one of the engineers working at Pulumi.&lt;/p&gt;

&lt;p&gt;I had to search through the big internet to find what I was looking for, I stumbled upon some blog posts, and decided to write my own.&lt;/p&gt;

&lt;p&gt;Fraser Water was the guy who helped me reach my goal, and a fun fact is that he is one of the authors on the Project Level Configuration page, which he referred me to in the slack discussion. As well as many others, he have been working directly on the Pulumi team.&lt;/p&gt;

&lt;p&gt;When working with Pulumi, you can orchestrate your infrastructure with code, and as shown in the last Post.&lt;/p&gt;

&lt;p&gt;However, when you want to orchestrate your environment, you don’t want to use the command line tool to insert variables.&lt;/p&gt;

&lt;p&gt;For example, you can use the command line tool, to set a variable called Azure Location to NorwayEast. As an example&lt;/p&gt;

&lt;p&gt;pulumi config set AzureLocation NorwayEast&lt;br&gt;
This is fine, when you want to just set a password, but when you have a lot of configuration you would like to swap out, it would be cumbersome to only use the terminal. &lt;/p&gt;

&lt;p&gt;That is where the Pulumi Yaml files comes into play.&lt;/p&gt;

&lt;p&gt;This can be as advanced as you like it, and it supports nesting.&lt;/p&gt;

&lt;p&gt;For example, you can set up your Yaml file like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 Core-Api-Ioc:az-env:
    default:
      tenant:id: xcx2
      subscription:id: 7dxx60dfbax3x
      resource-group:name: rg-youresourcegroup-dev
      location: norwayeast 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can get access to the YAML file in the code this way&lt;/p&gt;

&lt;p&gt;var azEnv = config.RequireObject("az-env");&lt;/p&gt;

&lt;p&gt;TenantId = azEnv.GetProperty("tenant:id").GetString() ?? string.Empty;&lt;/p&gt;

&lt;p&gt;SubscriptionId = azEnv.GetProperty("subscription:id").GetString() ?? string.Empty;&lt;/p&gt;

&lt;p&gt;Location = azEnv.GetProperty("location").GetString() ?? string.Empty;&lt;/p&gt;

&lt;p&gt;ResourceGroupName = azEnv.GetProperty("resource-group:name").GetString() ?? string.Empty;&lt;/p&gt;

&lt;p&gt;What I have done is to create a class called AzureEnv&lt;/p&gt;

&lt;p&gt;You could do this directly in the CoreDevStack.cs file if you'd like, but doing it this way I found out that it helped to clean up my code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using System.Text.Json;
using Config = Pulumi.Config;

namespace Core.Api.Iac.IocConfiguration.Azure;

public class AzureEnv
{
    public AzureEnv(Config config)
    {
        var azEnv = config.RequireObject&amp;lt;JsonElement&amp;gt;("az-env");
        TenantId = azEnv.GetProperty("tenant:id").GetString() ?? string.Empty;
        SubscriptionId = azEnv.GetProperty("subscription:id").GetString() ?? string.Empty;
        Location = azEnv.GetProperty("location").GetString() ?? string.Empty;
        ResourceGroupName = azEnv.GetProperty("resource-group:name").GetString() ?? string.Empty;
    }

    internal string SubscriptionId { get; }
    internal string ResourceGroupName { get; }
    internal string TenantId { get; }
    internal string Location { get; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is an example of nesting the code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Core-Api-Ioc:dbsmydatabase:
  default:
    servername: dbsncoredev
    version: 12.0
    location: westeurope
    security-properties:
      admin-login: yourinformation
      administrator-type: ActiveDirectory
      ad-login: sa-group-dba-dev
      principal-type: Group
      sid: e7343xx53796
      tenant-id: 8c34534534xx0a002
Core-Api-Ioc:dbsmydatabase:

 default:

 servername: dbsncoredev

 version: 12.0

 location: westeurope

 security-properties:

 admin-login: yourinformation

 administrator-type: ActiveDirectory

 ad-login: sa-group-dba-dev

 principal-type: Group

 sid: e7343xx53796

 tenant-id: 8c34534534xx0a002

Then we can get access to it, by doing this.

 Again I have configured a class



using System.Text.Json;
using Core.Api.Iac.IocConfiguration.Azure.Data.Sql.Common;
using Core.Api.Iac.IocConfiguration.Azure.Data.Sql.Databases;
using Config = Pulumi.Config;

namespace Core.Api.Iac.IocConfiguration.Azure.Data.Sql.Server;

public class AzNovoSidDevSql : CommonDb
{
    public AzNovoSidDevSql(Config config)
    {
        var azDbsNCoreDev = config.RequireObject&amp;lt;JsonElement&amp;gt;("dbsmydatabase");
        ServerName = azDbsNCoreDev.GetProperty("servername").GetString() ?? string.Empty;
        Version = azDbsNCoreDev.GetProperty("version").GetDouble();
        Location = azDbsNCoreDev.GetProperty("location").GetString() ?? string.Empty;
        var securityProperties = azDbsNCoreDev.GetProperty("security-properties");
        SecurityProperties.AdminLogin = securityProperties.GetProperty("admin-login").GetString() ?? string.Empty;
        SecurityProperties.AdministratorType = securityProperties.GetProperty("administrator-type").GetString() ?? string.Empty;
        SecurityProperties.AzLogin = securityProperties.GetProperty("ad-login").GetString() ?? string.Empty;
        SecurityProperties.PrincipalType = securityProperties.GetProperty("principal-type").GetString() ?? string.Empty;
        SecurityProperties.Sid = securityProperties.GetProperty("sid").GetString() ?? string.Empty;
        SecurityProperties.TenantId = securityProperties.GetProperty("tenant-id").GetString() ?? string.Empty;
    }
    public SecurityProperties SecurityProperties { get; } = new();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the CoreDevStack.cs file I call it in the constructor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var azDbsMyDatabase = new AzNovoSidDevSql(config);

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

&lt;/div&gt;



&lt;p&gt;Hopefully this helped you a bit as well, if you have any questions, please let me know, I try to answer as much as I can.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
