<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Victor Tihomirov</title>
    <description>The latest articles on DEV Community by Victor Tihomirov (@vixero).</description>
    <link>https://dev.to/vixero</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%2F1042098%2F3c63061f-71dc-488b-96f8-1a07c3a84e63.jpg</url>
      <title>DEV Community: Victor Tihomirov</title>
      <link>https://dev.to/vixero</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vixero"/>
    <language>en</language>
    <item>
      <title>Common mistakes that backend programmers make in Angular</title>
      <dc:creator>Victor Tihomirov</dc:creator>
      <pubDate>Sun, 03 Sep 2023 16:29:05 +0000</pubDate>
      <link>https://dev.to/vixero/common-mistakes-that-backend-programmers-make-in-angular-434d</link>
      <guid>https://dev.to/vixero/common-mistakes-that-backend-programmers-make-in-angular-434d</guid>
      <description>&lt;p&gt;Recently, I found myself in charge of upgrading our Angular application from version 12 to 15. In my current role, which I've held for just over a year, most of my focus has been on the backend, and I hadn't even touched the frontend apps until now. I've got to be honest; this upgrade process turned out to be a tougher nut to crack than I initially thought. It's not a knock on the Angular team's &lt;a href="https://update.angular.io/"&gt;Angular Update Guide&lt;/a&gt;, though; they did a solid job. The real challenge came from the fact that we had a bunch of custom-made components that didn't quite follow the best practices playbook.&lt;/p&gt;

&lt;p&gt;To provide a bit more context, our entire team primarily comprises .NET developers who possess some familiarity with HTML, CSS, and basic JavaScript. The rationale behind this choice stemmed from the belief that transitioning to Angular would be smoother for backend developers, possibly owing to the familiarity with the MVC (Model-View-Controller) pattern. At the time of this decision, Angular was also considered the go-to standard choice for frontend development.&lt;/p&gt;

&lt;p&gt;Although I did manage to pull it off eventually, here's what tripped me up along the way and some insights into areas where improvements could be made. Here are the key points I'd like to highlight:&lt;/p&gt;

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

&lt;p&gt;While reviewing the codebase, I couldn't help but notice numerous inconsistencies and common mistakes that would have been easily caught by &lt;code&gt;ESLint&lt;/code&gt;. After setting up and configuring it with recommended rules for &lt;code&gt;Angular&lt;/code&gt;, &lt;code&gt;TypeScript&lt;/code&gt;, and &lt;code&gt;RxJS&lt;/code&gt;, I ran the linter. To my surprise, it uncovered over 5000 linting issues, with approximately 2000 of them being automatically fixable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frr0pw74jn9kpvswlgs5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frr0pw74jn9kpvswlgs5w.png" alt="Linting meme" width="600" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, my primary goal wasn't to fix all these linting errors, as I couldn't guarantee that doing so wouldn't introduce unforeseen issues. Instead, I chose to install &lt;a href="https://www.npmjs.com/package/husky"&gt;husky&lt;/a&gt; and set up linting and automatic fixing exclusively for committed files. In cases where automatic fixing wasn't feasible, I encouraged the developers to follow the "boy scout rule" and address the errors they encountered. As I delved into these improvements, I also took the opportunity to seamlessly integrate and configure &lt;a href="https://www.npmjs.com/package/prettier"&gt;prettier&lt;/a&gt; alongside &lt;code&gt;ESLint&lt;/code&gt;. After all, who enjoys scrolling through diffs or pull requests with only formatting changes? It just makes the code review process smoother and more pleasant for everyone involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. TypeScript
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpfxndu2u4pjtv2bafjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpfxndu2u4pjtv2bafjy.png" alt="any meme" width="636" height="767"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I found myself inspecting the codebase in sheer horror as I discovered that practically everything was marked as &lt;code&gt;any&lt;/code&gt;. The most significant advantage of &lt;strong&gt;Type&lt;/strong&gt;Script seems to have been overlooked. &lt;/p&gt;

&lt;p&gt;Picture writing C# code where everything is either an anonymous type or simply of type &lt;code&gt;object&lt;/code&gt; – it's akin to a maintenance nightmare.&lt;/p&gt;

&lt;p&gt;This is one of the factors that made me hesitate to automatically fix all the linting issues and approach the upgrade with caution.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Unit tests
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5vcm1q02c1twae257do.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5vcm1q02c1twae257do.png" alt="testing meme" width="526" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This brings me to the second reason why I hesitated to automatically fix all the linting issues. There are numerous factors contributing to the absence of unit tests in our app, ranging from time constraints and knowledge gaps to a perceived low value, lack of a testing culture, and motivation. I won't delve too deep into each of these reasons, but I can say that the lack of unit tests significantly undermined my confidence in the app's stability following the upgrade. As it turned out, my concerns were justified, as various issues did arise and required subsequent fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. RxJS: observables and higher-order observables
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5gl1gfqhnzgmildz47s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5gl1gfqhnzgmildz47s.png" alt="observables meme" width="500" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've noticed that our codebase includes a fair share of &lt;code&gt;Promises&lt;/code&gt;, &lt;code&gt;async/await&lt;/code&gt;, and &lt;code&gt;RxJS&lt;/code&gt; usage. Let's establish one thing: &lt;code&gt;RxJS&lt;/code&gt; not only covers all the functionality of &lt;code&gt;Promises&lt;/code&gt; and &lt;code&gt;async/await&lt;/code&gt; but does so with superior flexibility and maintainability. One of the standout features of &lt;code&gt;RxJS&lt;/code&gt; is its inherent support for cancellation and resource cleanup. &lt;code&gt;Promises&lt;/code&gt; and &lt;code&gt;async/await&lt;/code&gt; don't provide these capabilities out of the box; you'd often need to resort to workarounds or third-party libraries to achieve similar functionality.&lt;/p&gt;

&lt;p&gt;I've also come across a common mistake in the codebase where developers tend to nest subscriptions. This practice can introduce a lot of problems, including memory leaks, unpredictable behavior, challenges in error handling, code that becomes increasingly complex and hard to maintain, and a loss of control over the execution flow.&lt;/p&gt;

&lt;p&gt;Adding to the mix, I also stumbled upon &lt;code&gt;Promises&lt;/code&gt; and &lt;code&gt;async/await&lt;/code&gt; nested within &lt;code&gt;RxJS&lt;/code&gt; subscriptions. This not only heightened the complexity of the code but also made it significantly harder to understand and read. What's more, there's the looming threat of potential deadlocks because &lt;code&gt;RxJS&lt;/code&gt; is tailored to function seamlessly with non-blocking, asynchronous operations, and introducing &lt;code&gt;async/await&lt;/code&gt; or &lt;code&gt;Promises&lt;/code&gt; into the mix can disrupt this delicate balance.&lt;/p&gt;

&lt;p&gt;To steer clear of all these potential issues, I strongly recommend sticking to observables and higher-order observables as the primary means of chaining or flattening them.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Composition over inheritance
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkab1jd06ziu1u9kscdtu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkab1jd06ziu1u9kscdtu.png" alt="composition over inheritance meme" width="484" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This one is probably my favorite. Angular favors composition over inheritance and it's easy to get caught up in the inheritance trap.&lt;/p&gt;

&lt;p&gt;Let me illustrate this with an example. Imagine the business comes to me and says, "Hey, we need two forms for our new app." And I'm like, "Sure thing, here they are."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContactComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="nf"&gt;displayErrors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;submitForm&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegistrationComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;displayErrors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;submitForm&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;Later on, they throw in a request for a new login form. That's when I begin to notice some code repetition. So, I decide to follow the DRY principle and create a base class to handle all this shared functionality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseFormComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;displayErrors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;submitForm&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContactComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseFormComponent&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegistrationComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseFormComponent&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseFormComponent&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything seems to be shaping up nicely. I've gone ahead and refactored the code, successfully eliminating those pesky code duplications.&lt;/p&gt;

&lt;p&gt;Now, here comes the business again, this time requesting a rating widget to be added. "No worries," I think, "I've got this covered."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RatingComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseFormComponent&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Somewhere in the back of my mind, I can't help but think that the rating form doesn't need any validations. But hey, for the sake of consistency, I'll stick to using that trusty base class. Who knows, even if it doesn't need those features right now, it might come in handy down the road, right? Better safe than sorry.&lt;/p&gt;

&lt;p&gt;And then, the business strikes once more, this time requesting a new email notification feature. They want users to receive a thank-you email after every contact, registration, or rating submission.&lt;/p&gt;

&lt;p&gt;This seems like a straightforward task. I'll just inject an &lt;code&gt;SMTPClient&lt;/code&gt; into the base class, and then I can easily share the email notification logic with all its subclasses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseFormComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormGroup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormGroup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;smtpClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SMTPClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;displayErrors&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;submitForm&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ContactComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseFormComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;smtpClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SMTPClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;smtpClient&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegistrationComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseFormComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;smtpClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SMTPClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;smtpClient&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoginComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseFormComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;smtpClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SMTPClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;smtpClient&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RatingComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseFormComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;smtpClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SMTPClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;smtpClient&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;After going through my changes, something just doesn't sit right. Why on earth should my &lt;code&gt;LoginComponent&lt;/code&gt; have to deal with injecting the &lt;code&gt;SMTPClient&lt;/code&gt;? This is a significant code smell, no doubt about it. &lt;/p&gt;

&lt;p&gt;In a nutshell, here's what I've managed to accomplish so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created code that's less flexible and harder to maintain.&lt;/li&gt;
&lt;li&gt;Introduced tight coupling between components.&lt;/li&gt;
&lt;li&gt;Achieved a delightful level of code duplication.&lt;/li&gt;
&lt;li&gt;Made writing tests feel like an Olympic event.&lt;/li&gt;
&lt;li&gt;And let's not forget the introduction of the notorious fragile base class problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quite the list, isn't it? 😅&lt;/p&gt;

&lt;p&gt;Sadly, this is precisely the situation I'm grappling with in the codebase I'm currently working on.&lt;/p&gt;

&lt;p&gt;To address these issues effectively, we need to shift our focus to composition instead. Remember the &lt;code&gt;is-a&lt;/code&gt; vs &lt;code&gt;has-a&lt;/code&gt;?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;RatingComponent&lt;/code&gt; has an &lt;code&gt;SMTPClientService&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;LoginComponent&lt;/code&gt; has a &lt;code&gt;ValidationEngineService&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;RegistrationComponent&lt;/code&gt; has a &lt;code&gt;ValidationEngineService&lt;/code&gt; and an &lt;code&gt;SMTPClientService&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using services in this manner, we can craft &lt;strong&gt;reusable code&lt;/strong&gt; that's not only &lt;strong&gt;easier to maintain&lt;/strong&gt; but also &lt;strong&gt;decoupled&lt;/strong&gt;. Plus, writing unit tests becomes a breeze. This approach offers a fresh perspective and a cleaner path forward.&lt;/p&gt;




&lt;p&gt;That's a wrap for my rant. Time to go brew some coffee. If any of you have questions or want more examples, feel free to ask in the comments – I'm here to help and answer them all! ☕😊&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you liked my article and would like to buy me a coffee, you can do it &lt;a href="https://www.buymeacoffee.com/vixero"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>learning</category>
    </item>
    <item>
      <title>A simple Angular folder structure that makes development feel natural and easy.</title>
      <dc:creator>Victor Tihomirov</dc:creator>
      <pubDate>Sat, 11 Mar 2023 20:06:49 +0000</pubDate>
      <link>https://dev.to/vixero/a-simple-angular-folder-structure-that-makes-development-feel-natural-and-easy-241d</link>
      <guid>https://dev.to/vixero/a-simple-angular-folder-structure-that-makes-development-feel-natural-and-easy-241d</guid>
      <description>&lt;p&gt;After years of working on multiple Angular projects, I have had firsthand experience with the difficulties of poorly thought out designs. Projects that were supposed to be scalable were unscalable, had unreadable code, and did not adhere to the &lt;a href="https://angular.io/guide/styleguide"&gt;Angular coding style guide&lt;/a&gt;. Luckily, the coding style guide already gives us a place to start when it comes to project structure, with a &lt;a href="https://angular.io/guide/styleguide#shared-feature-module"&gt;shared module&lt;/a&gt; and &lt;a href="https://angular.io/guide/styleguide#feature-modules"&gt;a module for each feature&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this guide, I will go over the feature-based approach in greater detail and explain the whys and hows.&lt;/p&gt;

&lt;p&gt;First of all, why is a well-designed folder structure important?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It allows us to be more flexible with our application. We can add new functionality without breaking anything.&lt;/li&gt;
&lt;li&gt;A well-designed system is simple to understand and navigate.&lt;/li&gt;
&lt;li&gt;It improves testing, maintainability, and reusability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I like to split the project into six main folders, each with its own responsibility: &lt;code&gt;core&lt;/code&gt;, &lt;code&gt;features&lt;/code&gt;, &lt;code&gt;shared&lt;/code&gt;, &lt;code&gt;apis&lt;/code&gt;, &lt;code&gt;types&lt;/code&gt;, and &lt;code&gt;store&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Core folder
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;CoreModule&lt;/code&gt; is located in the core folder and contains essential services, components, and other functionality that are required by many parts of the application, either once (components) or as a singleton (services). Here are some examples of such components and services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Components (header, footer, navbar, error, etc.)&lt;/li&gt;
&lt;li&gt;Logging service&lt;/li&gt;
&lt;li&gt;Exception handling service&lt;/li&gt;
&lt;li&gt;Configuration service&lt;/li&gt;
&lt;li&gt;Localization service&lt;/li&gt;
&lt;li&gt;Auth service&lt;/li&gt;
&lt;li&gt;Http interceptors&lt;/li&gt;
&lt;li&gt;Guards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By encapsulating this functionality into a single module, we gain a centralized location for managing dependencies and configuring the application at a high level.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CoreModule&lt;/code&gt; is typically imported once in the application's root module. Its components and services are made available to other modules via dependency injection.&lt;/p&gt;

&lt;p&gt;To avoid accidentally importing the &lt;code&gt;CoreModule&lt;/code&gt; more than once, include the following code in the constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SkipSelf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;parentModule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CoreModule&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;parentModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`CoreModule has already been loaded. Import it in the AppModule only.`&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;This is how the core folder might look.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-- core
|   |-- components
|   |   |-- header
|   |   |   |-- header.component.ts
|   |   |   |-- header.component.html
|   |   |   |-- header.component.scss
|   |   |-- footer
|   |   |   |-- footer.component.ts
|   |   |   |-- footer.component.html
|   |   |   |-- footer.component.scss
|   |-- services
|   |   |-- auth.service.ts
|   |   |-- logging.service.ts
|   |   |-- exception.service.ts
|   |-- interceptors
|   |   |-- auth.interceptor.ts
|   |-- guards
|   |   |-- auth.guard.ts
|   |-- core.module.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Shared folder
&lt;/h4&gt;

&lt;p&gt;The shared folder contains the &lt;code&gt;SharedModule&lt;/code&gt; which typically contains reusable UI components used throughout the application, such as buttons, form fields, and input validation. It may also include directives and pipes that are used by numerous modules. &lt;/p&gt;

&lt;p&gt;Developers can avoid code duplication across multiple modules by encapsulating these shared components in the 'SharedModule,' which would otherwise result in code bloat and maintenance issues. It also helps to enforce UI consistency because all modules will be using the same shared components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus&lt;/strong&gt;: Create a &lt;code&gt;ThirdPartyModule&lt;/code&gt; to differentiate between own components and vendor components such as &lt;code&gt;NgbModule&lt;/code&gt;. This module should be imported into the &lt;code&gt;SharedModule&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The shared folder might look 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;|-- shared
|   |-- components
|   |   |-- spinner
|   |   |   |-- spinner.component.ts
|   |   |   |-- spinner.component.html
|   |   |   |-- spinner.component.scss
|   |   |-- modal
|   |   |   |-- modal.component.ts
|   |   |   |-- modal.component.html
|   |   |   |-- modal.component.scss
|   |-- directives
|   |   |-- highlight.directive.ts
|   |-- pipes
|   |   |-- capitalize.pipe.ts
|   |-- shared.module.ts
|   |-- third-party.module.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Features folder
&lt;/h4&gt;

&lt;p&gt;This folder contains the features of the application. Each feature has its own module that contains a collection of components, services, directives, pipelines, and other code that encapsulates a specific aspect of the application's functionality.&lt;/p&gt;

&lt;p&gt;I like to think of a feature as a slice of pie. You should be able to easily remove a slice of pie without making a mess. This means that our features should not be dependent on one another.&lt;/p&gt;

&lt;p&gt;The features folder can look 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;|-- features
|   |-- products
|   |   |-- components
|   |   |   |-- product-list
|   |   |   |   |-- product-list.component.ts
|   |   |   |   |-- product-list.component.html
|   |   |   |   |-- product-list.component.scss
|   |   |   |-- product-details
|   |   |   |   |-- product-details.component.ts
|   |   |   |   |-- product-details.component.html
|   |   |   |   |-- product-details.component.scss
|   |   |-- product-root.component.html
|   |   |-- product-root.component.ts
|   |   |-- product-routing.module.ts
|   |   |-- product.module.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Apis folder
&lt;/h4&gt;

&lt;p&gt;The apis folder is used to store files related to consuming RESTful APIs or other web services. These files may include service classes, models or interfaces, and helper functions related to working with the APIs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-- apis
|   |-- product.service.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Types folder
&lt;/h4&gt;

&lt;p&gt;The types folder is a location for storing type definitions that are used across the application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-- types
|   |-- user
|   |   |-- user.ts
|   |   |-- user-status.enum.ts
|   |-- product
|   |   |-- product.ts
|   |   |-- product-type.enum.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Store folder
&lt;/h4&gt;

&lt;p&gt;If you're using &lt;code&gt;NgRx&lt;/code&gt; for state management, the store folder is ideal for providing a centralized location for managing application state, which can help to simplify the codebase and make complex state interactions easier to manage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|-- store
|   |-- user
|   |   |-- actions
|   |   |   |-- user.actions.ts
|   |   |-- reducers
|   |   |   |-- user.reducers.ts
|   |   |-- selectors
|   |   |   |-- user.selectors.ts
|   |-- product
|   |   |-- actions
|   |   |   |-- product.actions.ts
|   |   |-- reducers
|   |   |   |-- product.reducers.ts
|   |   |-- selectors
|   |   |   |-- product.selectors.ts
|   |-- store.module.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, the Angular world and the best practices are evolving, and so do we. I will come back again in a year and revise what can be improved (hello, signals!).&lt;/p&gt;

&lt;p&gt;Keep learning, stay curious, and never stop coding!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you liked my article and would like to buy me a coffee, you can do it &lt;a href="https://www.buymeacoffee.com/vixero"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>tutorial</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
