<?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: Fredy Daniel Flores Lemus </title>
    <description>The latest articles on Forem by Fredy Daniel Flores Lemus  (@fredydlemus).</description>
    <link>https://forem.com/fredydlemus</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%2F1160621%2Fab7a3f63-e0a3-47e1-9a56-8cd7e43c708d.jpg</url>
      <title>Forem: Fredy Daniel Flores Lemus </title>
      <link>https://forem.com/fredydlemus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fredydlemus"/>
    <language>en</language>
    <item>
      <title>From On-Premise Monolith to Scalable AWS Architecture: The Ticket Sales Case Study</title>
      <dc:creator>Fredy Daniel Flores Lemus </dc:creator>
      <pubDate>Thu, 15 Jan 2026 20:14:41 +0000</pubDate>
      <link>https://forem.com/fredydlemus/from-on-premise-monolith-to-scalable-aws-architecture-the-ticket-sales-case-study-1lfe</link>
      <guid>https://forem.com/fredydlemus/from-on-premise-monolith-to-scalable-aws-architecture-the-ticket-sales-case-study-1lfe</guid>
      <description>&lt;h2&gt;
  
  
  The Problem Statement
&lt;/h2&gt;

&lt;p&gt;Imagine the following scenario: a ticket sales application residing on a physical server (On-premise). Currently, the application is a monolith written in Node.js; it handles persistence in a MySQL database hosted on the same server, and stores static files (like event posters) directly on the local hard drive.&lt;/p&gt;

&lt;p&gt;This architecture faces critical issues when tickets for a famous artis go on sale: the server crashes due to traffic, the database gets locked, and images load extremely slowly.&lt;/p&gt;

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

&lt;p&gt;To address these root problems, the decision is made to migrate the application to AWS. This is where architecture planning begins, based on the following functional requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High Availability (HA&lt;/strong&gt;): If a server or zone fails, the app must continue operating without interruption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: The system must handle user load and absorb traffic spikes during major events on demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistence&lt;/strong&gt;: Transaction integrity is vital; no sale can be lost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: The database must be protected and isolated from public internet access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;We need structure the solution by addressing four fundamental pillars:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Compute&lt;/strong&gt;: Where do we run the application and how do we manage traffic?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database&lt;/strong&gt;: Which service do we use for MySQL and how do we optimize reads without saturating the system?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static Storage&lt;/strong&gt;: How do we serve poster images to ensure fast loading?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network &amp;amp; Security&lt;/strong&gt;: How do we organize the network (VPC) to protect data while allowing user access to the web?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Architecture Proposal
&lt;/h2&gt;

&lt;p&gt;For the &lt;strong&gt;compute&lt;/strong&gt; layer, we can run the application on EC2 instances managed by an Auto Scaling Group. This allows us to scale horizontally on demand to handle traffic spikes. In front, we will place a Load Balancer (ALB) to distribute requests among instances, which will be spread across differente Availability Zones (AZs) to ensure high availability.&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;MySQL&lt;/strong&gt;, we will use the managed service Amazon RDS. To optimize performance, we will evaluate two strategies: using Read Replicas or implementing Amazon ElastiCache (we will define the best option later).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static Content&lt;/strong&gt; (poster images) will be migrated to a S3 bucket, utilizing Amazon CloudFront as a CDN to cache content and drastically reduce load times globally.&lt;/p&gt;

&lt;p&gt;Finally, for &lt;strong&gt;Network Security&lt;/strong&gt;, we will implement a three-tier architecture within the VPC:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Load Balancer (our entry point) will reside in a public subnet.&lt;/li&gt;
&lt;li&gt;Both the application instances and the database will be located in private subnets.&lt;/li&gt;
&lt;li&gt;We will use Security Groups to stricly restric access between layers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6j5h6chp7hiv1jcksuj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6j5h6chp7hiv1jcksuj.png" alt="AWS three tier architecture" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib4s07d81f6xw2tjed72.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib4s07d81f6xw2tjed72.png" alt="AWS three tier architecture - Networking" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Dive: Distributed Systems Challenges
&lt;/h2&gt;

&lt;p&gt;The architecture above is solid and meets the infrastructure requirements. However, moving from a monolith to a distributed environment exposes our design to two critical logical problems:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;The User Session&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The original application stored the session in the server's RAM. In the new architecture, using the combination of Auto Scaling + Loab Balancer means that if the balancer routes us to different instance than the one we logged into, we lose the state, resulting in a terrible user experience (unexpected logout).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;How do we solve this?&lt;/strong&gt; We convert the application to be &lt;strong&gt;stateless&lt;/strong&gt;. Instead of storing the session locally, we externalize it to &lt;strong&gt;Amazon ElastiCache&lt;/strong&gt;. Beign an in-memory database, it offers sub-millisecond latency and ensures that even if the user changes instances, their session reamins centrally available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fua2kel7ldfusa5gq07pd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fua2kel7ldfusa5gq07pd.png" alt="Stateless session workflow" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Data Consistency (Race Condition)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here we revisit the debate between using Read Replicas or ElastiCache. Image User A buys a ticket. Milliseconds later, User B checks that same seat. If we use Read Replicas, there is a small delay (replication lag) before User A's purchase is reflected in all copies. This could lead User B to attempt purchasing an already sold seat, causing an error or, worse, overbooking.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nxo2mhcsvnu27mjmp1c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nxo2mhcsvnu27mjmp1c.png" alt="race condition workflow" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do we handle immediate availability without saturating the database?&lt;/strong&gt; The ideal solution is &lt;strong&gt;ElastiCache (Redis)&lt;/strong&gt;. Read Replicas are not ideal for real-time stock control due to the aforemetioned lag. Instead, Redis allow us to leverage its &lt;strong&gt;automicity&lt;/strong&gt;. Since Redis is single-threated (processes operations one by one), it acts as a perfect control mechanism: if multiple purchase requests for the same seat arrive simultaneously, Redis "queues" them and processes them sequentially, allowing only the first transaction to succeed. This not only solves the race condition but also offloads read traffic from the main database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frzg9s0apafowvtqgdn7b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frzg9s0apafowvtqgdn7b.png" alt="Concurrency well handled" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Migrating from an on-premises environemnt to the cloud isn't just about moving servers (Lift &amp;amp; Shift); it's about rethinking how our application handles state and concurrency.&lt;/p&gt;

&lt;p&gt;By integrating &lt;strong&gt;Amazon ElastiCache (Redis)&lt;/strong&gt; into our architecture, we didn't just gain speed in reads-we solved two of the most complex problems in distributed systems: session management in stateless applications and data integrity during race conditions.&lt;/p&gt;

&lt;p&gt;With this architecture, we've moved from a server that collapses under the demand of a famous artist to an elastic, robust infrastructure ready to scale automatically according to demand.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Beginner’s Guide to Kubernetes Architecture: How It All Works</title>
      <dc:creator>Fredy Daniel Flores Lemus </dc:creator>
      <pubDate>Thu, 08 May 2025 23:17:28 +0000</pubDate>
      <link>https://forem.com/fredydlemus/beginners-guide-to-kubernetes-architecture-how-it-all-works-2p1l</link>
      <guid>https://forem.com/fredydlemus/beginners-guide-to-kubernetes-architecture-how-it-all-works-2p1l</guid>
      <description>&lt;p&gt;Getting started with Kubernetes isn't easy, but a good first step is understanding its architecture at a high level. In this post, we'll walk through the different components that make Kubernetes work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nodes
&lt;/h2&gt;

&lt;p&gt;First, Kubernetes has two types of nodes: &lt;strong&gt;control plane nodes&lt;/strong&gt; (formerly called master nodes) and &lt;strong&gt;worker nodes&lt;/strong&gt;. The control plane nodes are responsible for running the components that handle the orchestration of the entire cluster. These nodes manage the desired state, schedule workloads, and monitor the overall health of the system.&lt;/p&gt;

&lt;p&gt;On the other hand, we have worker nodes, which are responsible for hosting and running applications inside containers.&lt;/p&gt;

&lt;p&gt;The control plane nodes host the following components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;etcd&lt;/li&gt;
&lt;li&gt;kube-scheduler&lt;/li&gt;
&lt;li&gt;controller-Manager&lt;/li&gt;
&lt;li&gt;kube-apiserver&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The worker nodes include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;kubelet&lt;/li&gt;
&lt;li&gt;kube-proxy&lt;/li&gt;
&lt;li&gt;Container runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll take a closer look at each of these components next.&lt;/p&gt;

&lt;h2&gt;
  
  
  etcd
&lt;/h2&gt;

&lt;p&gt;Starting with &lt;strong&gt;etcd&lt;/strong&gt;, it is a distributed, reliable key-value store that is simple, secure, and fast.&lt;/p&gt;

&lt;p&gt;In the context of Kubernetes, &lt;strong&gt;etcd&lt;/strong&gt; is used to store the state of the cluster. It contains all the information about the resources that have been created, such as pods, services, deployments, and more.&lt;/p&gt;

&lt;p&gt;When you run a &lt;code&gt;kubectl get&lt;/code&gt; command, the request goes through the Kubernetes API server, which retrieves the necessary data from &lt;strong&gt;etcd&lt;/strong&gt;, where the cluster state is stored.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  kube-apiserver
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;kube-apiserver&lt;/strong&gt; is the central component of the control plane and serves as the primary interface to the Kubernetes cluster. All communication—whether from internal components or external users—goes through the API server.&lt;/p&gt;

&lt;p&gt;Whether you use the &lt;code&gt;kubectl&lt;/code&gt; CLI or send an HTTP request to the Kubernetes API, both are handled by the &lt;strong&gt;kube-apiserver&lt;/strong&gt;, which acts as the entry point to the cluster and validates and processes all API requests.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  controller-manager
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;controller-manager&lt;/strong&gt; runs a set of controllers that constantly observe the current state of the cluster and make the necessary changes to ensure it matches the desired state defined in the configuration.&lt;/p&gt;

&lt;p&gt;For example, the &lt;strong&gt;Node Controller&lt;/strong&gt; monitors the status of nodes, and the &lt;strong&gt;Replication Controller&lt;/strong&gt; ensures that the desired number of pod replicas are running—if a pod dies, it automatically creates a new one.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  kube-scheduler
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;kube-scheduler&lt;/strong&gt; is responsible for deciding which pod should run on which node. It's important to note that the scheduler doesn't actually place the pod on the node—it only assigns the pod to a suitable node based on resource availability, scheduling policies, and criteria.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  kubelet
&lt;/h2&gt;

&lt;p&gt;On the worker node side, we have the &lt;strong&gt;kubelet&lt;/strong&gt;. This component is responsible for registering the node with the Kubernetes cluster and enabling communication between the node and the control plane.&lt;/p&gt;

&lt;p&gt;It is also responsible for instructing the container runtime to pull the required image, run the container inside a pod, and monitor its state.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  kube-proxy
&lt;/h2&gt;

&lt;p&gt;Within a Kubernetes cluster, every pod can communicate with other pods thanks to the underlying pod network. A pod can reach another pod using its IP address, but this is not a reliable approach since pod IPs can change over time.&lt;/p&gt;

&lt;p&gt;To solve this, Kubernetes introduces Services, which provide stable networking endpoints for accessing pods. However, Services don't exist within the pod network themselves—they require a mechanism to route traffic. That's where &lt;strong&gt;kube-proxy&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;kube-proxy&lt;/strong&gt; is a network component that runs on each node. Based on the configured Services, it creates the necessary networking rules to forward traffic.&lt;/p&gt;

&lt;p&gt;So, when a pod tries to reach another pod through a Service, &lt;strong&gt;kube-proxy&lt;/strong&gt; handles the traffic routing under the hood—forwarding it from the Service's virtual IP to the correct pod's IP address.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Container Runtime
&lt;/h2&gt;

&lt;p&gt;Finally, we have the &lt;strong&gt;container runtime&lt;/strong&gt;. This component is responsible for running our applications as containers inside pods. The most commonly used &lt;strong&gt;container runtime&lt;/strong&gt; in Kubernetes is &lt;strong&gt;containerd&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2v3bae2w7f5pkcieqosh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2v3bae2w7f5pkcieqosh.png" alt="container-runtime-k8s" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is just the beginning of your journey into the world of Kubernetes. There's a lot more to learn, but remember—one step at a time is the best way forward.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/fredydlemus/" rel="noopener noreferrer"&gt;my LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Cómo configurar un Path en API Gateway con AWS SAM sin Lambda Proxy Integration</title>
      <dc:creator>Fredy Daniel Flores Lemus </dc:creator>
      <pubDate>Fri, 24 Jan 2025 03:20:38 +0000</pubDate>
      <link>https://forem.com/fredydlemus/como-configurar-un-path-en-api-gateway-con-aws-sam-sin-lambda-proxy-integration-4am2</link>
      <guid>https://forem.com/fredydlemus/como-configurar-un-path-en-api-gateway-con-aws-sam-sin-lambda-proxy-integration-4am2</guid>
      <description>&lt;p&gt;¿Sabías que con API Gateway puedes manejar solicitudes HTTP sin necesidad de preocuparte por servidores? En arquitecturas serverless, este servicio no solo expone tus endpoints, sino que también transforma y controla cómo llegan los datos a tu backend. En este tutorial, te enseñaré cómo llevarlo al siguiente nivel configurando integraciones personalizadas con OpenAPI.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es Lambda Proxy Integration y cuándo evitarlo?
&lt;/h3&gt;

&lt;p&gt;Cuando utilizamos AWS SAM para definir nuestra arquitectura serverless, la integración predeterminada entre Lambda y API Gateway es &lt;strong&gt;Lambda Proxy Integration&lt;/strong&gt;. Esto significa que toda la solicitud HTTP (headers, body, query parameters) se pasa directamente como un evento JSON a la función Lambda.&lt;/p&gt;

&lt;p&gt;Aunque este enfoque es conveniente, no siempre es ideal. Si necesitas transformar las solicitudes o conectarte a otros servicios directamente desde API Gateway, una &lt;strong&gt;integración personalizada&lt;/strong&gt; es la mejor opción.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Definiendo la función Lambda
&lt;/h3&gt;

&lt;p&gt;Comencemos creando nuestra función Lambda en el template de AWS SAM. Configuraremos sus propiedades principales. Como queremos usar una integración personalizada, omitiremos la propiedad &lt;code&gt;Events&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;MyFunction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Lambda::Function&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app.lambdaHandler&lt;/span&gt;
      &lt;span class="na"&gt;Runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodejs18.x&lt;/span&gt;
      &lt;span class="na"&gt;CodeUri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./src/&lt;/span&gt;
      &lt;span class="na"&gt;Timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Definiendo el API Gateway
&lt;/h3&gt;

&lt;p&gt;A continuación, configuraremos nuestro API Gateway manualmente para evitar el comportamiento por defecto de Lambda Proxy Integration. Utilizaremos la propiedad &lt;code&gt;DefinitionBody&lt;/code&gt; para definir la API en formato OpenAPI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;MyApi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Serverless::Api&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyCustomApi&lt;/span&gt;
      &lt;span class="na"&gt;StageName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prod&lt;/span&gt;
      &lt;span class="na"&gt;DefinitionBody&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;openapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.0.1&lt;/span&gt;
        &lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;My API&lt;/span&gt;
          &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.0.1&lt;/span&gt;
        &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;/example&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Configurando una integración personalizada
&lt;/h3&gt;

&lt;p&gt;Ahora especificaremos la integración personalizada para nuestro path. Usaremos la extensión &lt;code&gt;x-amazon-apigateway-integration&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;/example&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;x-amazon-apigateway-integration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AWS"&lt;/span&gt; &lt;span class="c1"&gt;# Tipo de integración personalizada para servicios AWS&lt;/span&gt;
        &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Sub&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyFunction.Arn}/invocations"&lt;/span&gt; &lt;span class="c1"&gt;# URI de la Lambda&lt;/span&gt;
        &lt;span class="na"&gt;httpMethod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST"&lt;/span&gt; &lt;span class="c1"&gt;# Método HTTP usado para invocar el backend&lt;/span&gt;
        &lt;span class="na"&gt;passthroughBehavior&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WHEN_NO_MATCH"&lt;/span&gt; &lt;span class="c1"&gt;# Manejo de solicitudes sin modelo de mapeo definido&lt;/span&gt;
        &lt;span class="na"&gt;requestTemplates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Mapping template que nos ayuda a transformar la data para luego pasarla a nuestro backend&lt;/span&gt;
          &lt;span class="na"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;{&lt;/span&gt;
              &lt;span class="s"&gt;"statusCode": 200&lt;/span&gt;
            &lt;span class="s"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Tambien es posible mapear la respuesta que nos devuelve nuestro backend &lt;/span&gt;
          &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;200"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusión
&lt;/h3&gt;

&lt;p&gt;Con esta configuración, hemos configurado una integración personalizada que nos permite un control total sobre cómo se manejan las solicitudes y respuestas. Esto nos abre la puerta a arquitecturas más avanzadas y flexibles en AWS.&lt;/p&gt;

&lt;p&gt;Si deseas profundizar más en las propiedades como passthroughBehavior o x-amazon-apigateway-integration, consulta la &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-integration.html" rel="noopener noreferrer"&gt;documentación oficial de AWS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Si tienes dudas o comentarios, ¡déjalos abajo!&lt;/p&gt;

</description>
      <category>apigateway</category>
      <category>awssam</category>
      <category>spanish</category>
      <category>aws</category>
    </item>
    <item>
      <title>Estrategias Avanzadas: Cómo Implementar el Patrón Strategy en Tus Proyectos NestJS</title>
      <dc:creator>Fredy Daniel Flores Lemus </dc:creator>
      <pubDate>Wed, 07 Feb 2024 22:36:20 +0000</pubDate>
      <link>https://forem.com/fredydlemus/estrategias-avanzadas-como-implementar-el-patron-strategy-en-tus-proyectos-nestjs-28ca</link>
      <guid>https://forem.com/fredydlemus/estrategias-avanzadas-como-implementar-el-patron-strategy-en-tus-proyectos-nestjs-28ca</guid>
      <description>&lt;p&gt;&lt;a href="https://www.linkedin.com/in/fredydlemus/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/fredydlemus" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.instagram.com/fredydlemus/?next=%2F" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uno de los patrones de diseño que más me llamó la atención al aprender TypeScript fue el &lt;em&gt;Strategy Pattern&lt;/em&gt;. Aunque no es exclusivo de TypeScript, este patrón enriquece significativamente el código al promover la reusabilidad y el desacoplamiento.&lt;/p&gt;
&lt;h2&gt;
  
  
  En que consiste el patrón?
&lt;/h2&gt;

&lt;p&gt;El &lt;em&gt;patrón Strategy&lt;/em&gt; permite que una clase modifique el algoritmo o comportamiento que emplea durante la ejecución. Esto se logra definiendo una serie de algoritmos, cada uno encapsulado en su propia clase y siguiendo una interfaz común. De esta manera, se pueden intercambiar comportamientos de forma sencilla sin necesidad de alterar la clase que los implementa.&lt;/p&gt;
&lt;h2&gt;
  
  
  Un ejemplo en la vida real
&lt;/h2&gt;

&lt;p&gt;Imagina una aplicación que envía notificaciones a los usuarios, con métodos de notificación variables, como correo electrónico, SMS o notificaciones push. En lugar de codificar un único método de envío, tu aplicación puede adoptar diferentes estrategias de notificación según las necesidades del momento. Esto se consigue mediante la implementación de una interfaz común para las estrategias de notificación, asegurando que tu aplicación sepa cómo enviarlas, independientemente del método elegido. Este enfoque permite cambiar los métodos de notificación fácilmente, sin afectar el funcionamiento general de la aplicación.&lt;br&gt;
Al principio suena un poco confuso, así que mejor vayamos a un ejemplo con código&lt;/p&gt;
&lt;h2&gt;
  
  
  Código donde no se esta usando &lt;em&gt;Strategy Pattern&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;En el contexto del ejemplo anterior y utilizando NestJS, consideremos el servicio &lt;code&gt;NotificationService&lt;/code&gt;. Este servicio es responsable de enviar distintos tipos de notificaciones, seleccionando el método apropiado basado en un argumento pasado al método &lt;code&gt;notify&lt;/code&gt;. La selección del método de notificación se realiza mediante condicionales, determinando si se envía un correo electrónico, un SMS o una notificación push según el caso:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;NotificationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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="nx"&gt;method&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;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;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Sending email to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&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="nx"&gt;message&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="c1"&gt;// Lógica para enviar email&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Sending SMS to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phone&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="nx"&gt;message&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="c1"&gt;// Lógica para enviar SMS&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;push&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Sending push notification: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&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="c1"&gt;// Lógica para enviar notificaciones push&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid notification method&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="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;El siguiente fragmento de código demuestra cómo utilizaríamos el &lt;code&gt;NotificationService&lt;/code&gt; para enviar dos notificaciones, una por correo electrónico y otra por SMS. En este escenario, el método de notificación se decide en tiempo de ejecución, lo que muestra la flexibilidad de nuestro servicio para adaptarse a diferentes requisitos de notificación:&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="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;AppService&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="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NotificationService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+1234567890&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is a test message.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Decidir el método en tiempo de ejecución&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Este enfoque revela varias desventajas significativas que merecen atención:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Alto Acoplamiento: La selección y ejecución de los métodos de notificación están estrechamente integradas dentro de una sola clase o función, complicando la gestión y expansión del código. Este alto grado de acoplamiento reduce la flexibilidad y aumenta la complejidad del mantenimiento.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Violación del Principio de Abierto/Cerrado (OCP): Incorporar un nuevo método de notificación implica modificar la clase NotificationService directamente, añadiendo más condiciones. Esto contraviene el principio OCP, según el cual las entidades de software deben permitir su extensión sin necesidad de modificar su contenido existente, promoviendo así una mayor escalabilidad y mantenibilidad.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complejidad en las Pruebas: Verificar el correcto funcionamiento de &lt;code&gt;NotificationService&lt;/code&gt; se vuelve más arduo. Cada condición necesita ser probada individualmente para confirmar su operatividad, incrementando el esfuerzo y la complejidad de las pruebas." &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Refactorizando el código
&lt;/h2&gt;

&lt;p&gt;Para aplicar el patrón Strategy en nuestra refactorización del &lt;code&gt;NotificationService&lt;/code&gt;, eliminaremos las condicionales de la clase. En su lugar, modificaremos la clase para que acepte un objeto a través de su constructor. Este objeto debe adherirse a una interfaz específica que incluya un método &lt;code&gt;send&lt;/code&gt;. Este método será responsable de ejecutar la lógica de envío para el tipo de notificación correspondiente, permitiendo así que &lt;code&gt;NotificationService&lt;/code&gt; delegue la responsabilidad de enviar la notificación, desacoplando el servicio de los detalles de implementación específicos de cada método de envío. De esta manera, &lt;code&gt;NotificationService&lt;/code&gt; actúa meramente como un contexto para el envío de notificaciones, sin estar ligado a ningún método de envío en particular.&lt;/p&gt;

&lt;p&gt;Empezaremos por definir la interfaz común que deben cumplir todos los objetos destinados a ser utilizados como estrategias de notificación. Esta interfaz garantiza que cualquier estrategia de notificación proporcione una implementación del método &lt;code&gt;send&lt;/code&gt;, que es responsable de ejecutar la lógica específica de envío de notificaciones.&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="c1"&gt;// notification.strategy.interface.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;NotificationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;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;Tras definir la interfaz &lt;code&gt;NotificationStrategy&lt;/code&gt;, procedemos a integrarla en nuestro &lt;code&gt;NotificationService&lt;/code&gt;. Este cambio implica ajustar el constructor de &lt;code&gt;NotificationService&lt;/code&gt; para aceptar un objeto que cumpla con &lt;code&gt;NotificationStrategy&lt;/code&gt;. Al hacer esto, eliminamos la necesidad de condicionales dentro del servicio, delegando la responsabilidad de la lógica de envío al método &lt;code&gt;send&lt;/code&gt; del objeto estrategia inyectado. La función &lt;code&gt;notify&lt;/code&gt; del servicio, por lo tanto, se simplifica significativamente, limitándose a invocar send sobre la estrategia proporcionada.&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="c1"&gt;// notification.service.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NotificationStrategy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./notification.strategy.interface&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;NotificationService&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;strategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NotificationStrategy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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;Finalmente, para completar nuestra implementación del patrón de estrategia, creamos diferentes tipos de estrategias de notificación que &lt;code&gt;NotificationService&lt;/code&gt; puede utilizar. Específicamente, desarrollaremos &lt;code&gt;EmailNotificationStrategy&lt;/code&gt; y &lt;code&gt;SmsNotificationStrategy&lt;/code&gt;, cada una con su respectivo método &lt;code&gt;send&lt;/code&gt;. Estas estrategias concretas encapsulan la lógica específica para enviar notificaciones por correo electrónico y SMS, respectivamente.&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="c1"&gt;// email.notification.strategy.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NotificationStrategy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./notification.strategy.interface&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;EmailNotificationStrategy&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;NotificationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Sending email to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&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="nx"&gt;message&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="c1"&gt;// Aquí iría la lógica para enviar el correo electrónico&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// sms.notification.strategy.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NotificationStrategy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./notification.strategy.interface&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;SmsNotificationStrategy&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;NotificationStrategy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Sending SMS to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phone&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="nx"&gt;message&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="c1"&gt;// Aquí iría la lógica para enviar el SMS&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;Para maximizar la flexibilidad de &lt;code&gt;NotificationService&lt;/code&gt; y permitir que cambie su estrategia de notificación en tiempo de ejecución, introducimos un método setter, &lt;code&gt;setStrategy&lt;/code&gt;. Este método permite actualizar la estrategia de notificación que utiliza NotificationService, facilitando la adaptación a diferentes necesidades sin comprometer la instancia actual del servicio.&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="c1"&gt;// notification.service.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NotificationStrategy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./notification.strategy.interface&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;NotificationService&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;strategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NotificationStrategy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;setStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NotificationStrategy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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;Con la implementación del patrón de estrategia en nuestro sistema de notificaciones, hemos demostrado cómo se puede aumentar significativamente la flexibilidad y la mantenibilidad del código. El siguiente ejemplo ilustra cómo &lt;code&gt;AppService&lt;/code&gt; puede cambiar dinámicamente la estrategia de notificación de &lt;code&gt;EmailNotificationStrategy&lt;/code&gt; a &lt;code&gt;SmsNotificationStrategy&lt;/code&gt;, adaptándose a diferentes necesidades de notificación en tiempo de ejecución:&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="c1"&gt;// app.service.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NotificationService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./notification.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EmailNotificationStrategy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./email.notification.strategy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SmsNotificationStrategy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./sms.notification.strategy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&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;AppService&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="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NotificationService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;emailStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EmailNotificationStrategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;smsStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SmsNotificationStrategy&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;async&lt;/span&gt; &lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;phone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+1234567890&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is a test message.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Cambiar estrategia según el contexto&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emailStrategy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Cambiar a SMS&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;smsStrategy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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;Este enfoque no solo valida la versatilidad del patrón de estrategia, sino que también subraya su valor en la creación de aplicaciones modulares y extensibles. Al separar la lógica de notificación en estrategias concretas e intercambiables, facilitamos la adición de nuevos métodos de notificación y mejoramos la capacidad de prueba del sistema. Además, adherimos al principio de abierto/cerrado, permitiendo que nuestro sistema evolucione con cambios mínimos en el código existente."&lt;/p&gt;

&lt;p&gt;"En resumen, la aplicación del patrón de estrategia en la gestión de notificaciones en TypeScript con NestJS demuestra cómo los principios de diseño de software pueden llevarse a la práctica para construir sistemas robustos, flexibles y mantenibles. La capacidad de cambiar estrategias en tiempo de ejecución no solo enriquece nuestra aplicación con flexibilidad operativa, sino que también destaca la importancia de un diseño de software pensado para el futuro.&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>typescript</category>
      <category>design</category>
      <category>español</category>
    </item>
    <item>
      <title>Decoupling Code: Why Dependency Injection is a Must-Have in Programming?</title>
      <dc:creator>Fredy Daniel Flores Lemus </dc:creator>
      <pubDate>Sun, 24 Sep 2023 15:35:01 +0000</pubDate>
      <link>https://forem.com/fredydlemus/decoupling-code-why-dependency-injection-is-a-must-have-in-programming-312h</link>
      <guid>https://forem.com/fredydlemus/decoupling-code-why-dependency-injection-is-a-must-have-in-programming-312h</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.tourl"&gt;https://linktr.ee/fredyflemus&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dependency Injection is a design pattern adopted by prominent frameworks such as Angular and NestJS. If you've ever worked with these frameworks, you've likely encountered Dependency Injection and grasped 'how' to implement it. But have you delved into the 'why' behind its incorporation into these frameworks?&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;p&gt;We refer to a 'dependency' when, for instance, we have a class that requires an instance of another class to function – in other words, it depends on another class. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Engine {
    start() {
        return "Engine started";
    }
}

class Car {
    engine: Engine;

    constructor() {
        this.engine = new Engine();
    }

    drive() {
        return `Driving with ${this.engine.start()}`;
    }
}

// Use:
const myCar = new Car();
console.log(myCar.drive());  // Outputs: "Driving with Engine started"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the Car class has a dependency on the Engine class. When we create an instance of Car, we also need to create an instance of Engine for it to operate correctly. That is, Car relies on Engine to execute its drive() function.&lt;/p&gt;

&lt;p&gt;However, by creating an instance of the Engine class within the Car class constructor, we are violating one of the main principles in software development: the Inversion of Control Principle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inversion of Control (IoC)
&lt;/h2&gt;

&lt;p&gt;This principle dictates that if you want to achieve reusable code, you should write classes that don't instantiate their dependencies on their own. To accomplish this, I'll show you two different approaches:&lt;/p&gt;

&lt;p&gt;Firstly, instead of creating the instance of the Engine class within the Car class as we did in the previous code, we'll pass the instance as an argument to the Car class constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Engine {
    start() {
        return "Engine started";
    }
}

class Car {
    engine: Engine

    constructor(engine) {
        this.engine = engine;
    }

    drive() {
        return `Driving with ${this.engine.start()}`;
    }
}

// Use:
const myEngine = new Engine();
const myCar = new Car(myEngine);
console.log(myCar.drive());  // Outputs: "Driving with Engine started"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The significant downside to this method is that we specifically have to pass an instance of the Engine class. This limitation is what the next approach aims to address. Instead of passing an explicit Engine instance, we'll define an interface. Then, whenever we create an instance of the Car class, all we need to provide is an object that fulfills that interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface IEngine{
    start();
}

class Engine {
    start() {
        return "Engine started";
    }
}

class Car {
    engine: IEngine

    constructor(engine) {
        this.engine = engine;
    }

    drive() {
        return `Driving with ${this.engine.start()}`;
    }
}

// Use:
const myEngine = new Engine();
const myCar = new Car(myEngine);
console.log(myCar.drive());  // Outputs: "Driving with Engine started"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach shines because it isn't rigid about the kind of dependency it needs. It just looks for any object that fits the defined 'blueprint' or interface. For example, it simply asks for something with a start() method. In the real application, this might be our Engine class. But when testing, it allows us the flexibility to use a mock object, making unit tests &lt;strong&gt;smoother and more adaptable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, Inversion of Control isn't without its drawbacks. For instance, when you need to create an instance of a class that relies on another class, which in turn has its own dependencies, the code can become quite verbose as you find yourself having to instantiate each class manually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myBattery = new Battery();
const myEngine = new ElectricEngine(myBattery);
const myCar = new Car(myEngine);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this usage example, you can see the step-by-step instantiation of each dependent class, which emphasizes the potential verbosity Inversion of Control can introduce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependency Injection
&lt;/h2&gt;

&lt;p&gt;Dependency injection is a technique that allows us to adhere to the Inversion of Control principle without the need to manually create different instances every time we require a service, component, or controller, which, in the end, are just classes in the previously mentioned frameworks.&lt;/p&gt;

&lt;p&gt;Dependency Injection operates through something called the DI container (or Injector). This container is an object with various properties. To simplify the explanation, we'll focus on it holding two types of information.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;List of classes and their dependencies&lt;/li&gt;
&lt;li&gt;List of instances that I have created&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The DI container acts like a registry, cataloging all the classes along with their associated dependencies. When it's time to instantiate a particular class, the Dependency Injection system takes charge. It automatically recognizes and creates all the necessary instances for the class's dependencies, ensuring everything is in place for smooth operation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7br4sstn78c6n0cgj2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7br4sstn78c6n0cgj2j.png" alt="DI Container" width="349" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In summary, the DI Container follows this flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upon startup, all classes are registered with the container.&lt;/li&gt;
&lt;li&gt;The container analyzes and determines the dependencies for each class.&lt;/li&gt;
&lt;li&gt;We request the container to instantiate a specific class for us.&lt;/li&gt;
&lt;li&gt;The container autonomously creates all the necessary dependencies and provides us with the desired instance.&lt;/li&gt;
&lt;li&gt;For efficiency, the container retains these instantiated dependencies, reusing them as required.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This last step, where the container retains and reuses instantiated dependencies, is commonly known as the Singleton pattern. In essence, it ensures that a class has just one instance and provides a point of access to that instance from any other part of the application.&lt;/p&gt;

&lt;p&gt;Dependency Injection (DI) serves as a testament to the evolution of software design, placing emphasis on modular, decoupled, and testable code. Through the utilization of the DI container, we streamline the process of managing class dependencies, freeing developers from the intricacies of manual instantiation. As we embrace patterns like Singleton within this realm, we further enhance efficiency and maintainability. Ultimately, while Dependency Injection and its associated practices come with their learning curve, the benefits they offer in scalability, testability, and organization are undeniable. Embracing DI is not just about adhering to modern coding standards, but about paving the way for sustainable, adaptable software development.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>angular</category>
      <category>nestjs</category>
      <category>developer</category>
    </item>
    <item>
      <title>Enhance Your Angular Mastery with the Router: Change Styles According to the Route</title>
      <dc:creator>Fredy Daniel Flores Lemus </dc:creator>
      <pubDate>Wed, 20 Sep 2023 16:31:59 +0000</pubDate>
      <link>https://forem.com/fredydlemus/enhance-your-angular-mastery-with-the-router-change-styles-according-to-the-route-1dkj</link>
      <guid>https://forem.com/fredydlemus/enhance-your-angular-mastery-with-the-router-change-styles-according-to-the-route-1dkj</guid>
      <description>&lt;p&gt;Twitter(X): &lt;a href="https://dev.tourl"&gt;https://twitter.com/fredydlemus&lt;/a&gt;&lt;br&gt;
Instagram: &lt;a href="https://dev.tourl"&gt;https://www.instagram.com/fredydlemus/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're working with Angular's Router, you might have noticed that sometimes you want to customize the styles of your components based on the route you are on. Fortunately, Angular's Router offers us a tool to accomplish this: the routerLinkActive directive. In this article, I will guide you on how to leverage the routerLinkActive directive to breathe new life into your Angular applications and ensure each route possesses its distinct style. Let's get started!&lt;/p&gt;

&lt;p&gt;Imagine we have a menu furnished with buttons that lead us to different routes, each showcasing distinct components beneath the menu upon clicking on them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F32qm2ps4k1e6c1gyw0bc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F32qm2ps4k1e6c1gyw0bc.png" alt="angular routerLinkActive" width="800" height="164"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="container"&amp;gt;
  &amp;lt;div class="row"&amp;gt;
    &amp;lt;div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2"&amp;gt;
      &amp;lt;ul class="nav nav-tabs"&amp;gt;
        &amp;lt;li role="presentation"&amp;gt;
          &amp;lt;a routerLink="/"&amp;gt;Home&amp;lt;/a&amp;gt;
        &amp;lt;/li&amp;gt;
        &amp;lt;li role="presentation"&amp;gt;
          &amp;lt;a routerLink="products"&amp;gt;Products&amp;lt;/a&amp;gt;
        &amp;lt;/li&amp;gt;
        &amp;lt;li role="presentation"&amp;gt;
          &amp;lt;a routerLink="users"&amp;gt;Users&amp;lt;/a&amp;gt;
        &amp;lt;/li&amp;gt;
      &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class="row"&amp;gt;
      &amp;lt;div class="col-xs-12 col-sm-10 col-md-8 col-sm-offset-1 col-md-offset-2"&amp;gt;
        &amp;lt;router-outlet&amp;gt;&amp;lt;/router-outlet&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our goal is that when a button on the menu is clicked and redirects to the corresponding route, it also changes its style to indicate to the user that it's currently active. We can add or remove css classes to achieve this, and this is where the routerLinkActive directive comes into play.&lt;/p&gt;

&lt;p&gt;The routerLinkActive directive enables us to detect whether the route linked in the element is active and specifies one or more CSS classes. This way, we can tailor the style of our elements based on the route we are on. This directive is extremely handy for providing visual feedback to the user regarding their current location within the application and making navigation more intuitive.&lt;/p&gt;

&lt;p&gt;To utilize the routerLinkActive directive, you need to append it to the tag linked to the route you wish to detect. The "active" CSS class will be added to the tag when the linked route is active. If the user navigates to any other route, the "active" class will be removed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...

&amp;lt;ul class="nav nav-tabs"&amp;gt;
  &amp;lt;li role="presentation" routerLinkActive="active"&amp;gt;
    &amp;lt;a routerLink="/"&amp;gt;Home&amp;lt;/a&amp;gt;
  &amp;lt;/li&amp;gt;
  &amp;lt;li role="presentation" routerLinkActive="active"&amp;gt;
    &amp;lt;a routerLink="products"&amp;gt;Products&amp;lt;/a&amp;gt;
  &amp;lt;/li&amp;gt;
  &amp;lt;li role="presentation" routerLinkActive="active"&amp;gt;
    &amp;lt;a routerLink="users"&amp;gt;Users&amp;lt;/a&amp;gt;
  &amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here it is at “/”&lt;/p&gt;

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

&lt;p&gt;Here it is at “/products”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8zbujrmo16168u81y1vh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8zbujrmo16168u81y1vh.png" alt="angular routerLinkActive" width="783" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here it is at "/users"&lt;/p&gt;

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

&lt;p&gt;However, we encounter a very common issue, where the 'Home' button always appears active, even when we are navigating through other routes. This happens because the 'Home' button is linked to the "/" route, and since our other routes also contain "/", Angular's Router recognizes them as active and activates the 'Home' button.&lt;/p&gt;

&lt;p&gt;To rectify this problem, we can utilize the routerLinkActiveOptions feature of the routerLinkActive directive. This feature allows us to specify that Angular should consider the exact route when determining when to add or remove classes. This way, we can ensure that the 'Home' button will only be activated when we are on the root route, and not when we are on other routes that contain "/".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...

&amp;lt;ul class="nav nav-tabs"&amp;gt;
  &amp;lt;li
    role="presentation"
    routerLinkActive="active"
    [routerLinkActiveOptions]="{exact: true}"
  &amp;gt;
    &amp;lt;a routerLink="/"&amp;gt;Home&amp;lt;/a&amp;gt;
  &amp;lt;/li&amp;gt;
  &amp;lt;li role="presentation" routerLinkActive="active"&amp;gt;
    &amp;lt;a routerLink="products"&amp;gt;Products&amp;lt;/a&amp;gt;
  &amp;lt;/li&amp;gt;
  &amp;lt;li role="presentation" routerLinkActive="active"&amp;gt;
    &amp;lt;a routerLink="users"&amp;gt;Users&amp;lt;/a&amp;gt;
  &amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;I hope this post has been beneficial and you've gleaned some insights into utilizing the routerLinkActive directive in Angular. If you have any further questions or require additional assistance, please don't hesitate to let me know. Until next time!.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>angular</category>
      <category>css</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Effective Validations in NestJS: Flawless Software Development!</title>
      <dc:creator>Fredy Daniel Flores Lemus </dc:creator>
      <pubDate>Tue, 19 Sep 2023 02:07:17 +0000</pubDate>
      <link>https://forem.com/fredydlemus/effective-validations-in-nestjs-flawless-software-development-45b3</link>
      <guid>https://forem.com/fredydlemus/effective-validations-in-nestjs-flawless-software-development-45b3</guid>
      <description>&lt;p&gt;Twitter: &lt;a href="https://dev.tourl"&gt;https://twitter.com/fredydlemus&lt;/a&gt;&lt;br&gt;
Instagram: &lt;a href="https://dev.tourl"&gt;https://www.instagram.com/fredydlemus/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Validating the data that enters your application through your APIs stands as a pivotal task in the role of a backend developer. This procedure not only fortifies the security of your application but also enhances the user experience and fosters a robust system. Implementing data validation can mitigate potential risks and ensure the smooth operation of your application, making it a critical aspect to consider for achieving overall excellence in backend development.&lt;/p&gt;

&lt;p&gt;NestJS offers a sophisticated system that allows developers to conduct these validations both cleanly and elegantly. In this blog post, we will delve deep into the methods of implementing such validation processes. So, without further ado, let's embark on this insightful journey.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing Validations on NestJS
&lt;/h2&gt;

&lt;p&gt;To kickstart our journey, we will initiate a new project utilizing the NestJS CLI. We've decided to name this venture 'validation-behind-scenes'. This descriptive name not only encapsulates the essence of our project but also paves the way for a structured and insightful exploration into the world of NestJS validation processes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nest new validation-behind-scenes&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With our project accessible in a code editor, the next step is to head to our app.controller.ts file to craft a new POST route. This is where we will extract the body contained within the request, harboring the critical intention of validating that the incoming data adheres to our established criteria.&lt;/p&gt;

&lt;p&gt;For this demonstration, I envision this route serving a pivotal role in facilitating the creation of new user accounts, thus playing a fundamental part in expanding our application's user base.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Controller, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Post()
  createUser(@Body() body: any) {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the preceding code snippet, it's evident that we are extracting the body content through the utilization of the &lt;a class="mentioned-user" href="https://dev.to/body"&gt;@body&lt;/a&gt; decorator. Yet, it's crucial to note that we have not instituted any form of validation at this juncture. This lapse allows users to enter any data into our application indiscriminately, presenting a significant security risk. To fortify our application's defenses and initiate the implementation of validations, we are compelled to integrate two vital libraries into our project: 'class-transformer' and 'class-validator'. These libraries will serve as the cornerstone for establishing a secure and reliable validation process.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm i --save class-validator class-transformer&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Upon successful installation of these two pivotal libraries, we will advance to the next step of crafting a class referred to as a DTO, or Data Transfer Object. Within this specialized class, we undertake the task of delineating the specific properties and types that the body of our request should embody when we are in the process of creating a new user. This structured approach ensures a coherent and secure data handling procedure, paving the way for a smooth user creation process.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A DTO, or Data Transfer Object, is a simple object that is used to transfer data between software application layers. It does not contain any business logic but only attributes (data fields) with their respective getters and setters (methods to retrieve and update the values of these attributes).&lt;/p&gt;

&lt;p&gt;Think of it as a container for data that needs to be moved from one place to another within a system. It helps to streamline and simplify the data transfer process, promoting cleaner code and easier maintenance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Within the 'src' directory, I am set to establish a new folder denominated as 'dtos'. Nestled within this folder, I will forge a file dubbed 'create-user.dto.ts'. This file will house a class, which will bear the straightforward yet descriptive name 'CreateUserDTO'. This naming convention maintains clarity and directly reflects the purpose and functionality of the class, facilitating ease of understanding and future reference in the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { IsEmail, IsString } from 'class-validator';

export class CreateUserDto {
  @IsEmail()
  email: string;

  @IsString()
  password: string;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As illustrated in the code, we import the decorators @IsEmail and @IsString from the 'class-validator' package. These decorators play a crucial role in specifying the validation criteria that the attributes within our DTO class must adhere to. They facilitate a streamlined validation process by enforcing the respective data types and formats that are expected, thus ensuring the integrity and security of the data handled within our application.&lt;/p&gt;

&lt;p&gt;Now comes the pivotal moment where we synthesize all the elements to forge an effective validation mechanism. This endeavor entails two additional steps to fully realize our objective. Initially, we must incorporate the 'CreateUserDTO' into our controller, establishing it as the designated type for our body parameter. This action facilitates the meticulous screening of input data, aligning it with the criteria we have set forth in the DTO class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Controller, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';
import { CreateUserDto } from './dtos/create-user.dto';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Post()
  createUser(@Body() body: CreateUserDto) {}
}

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

&lt;/div&gt;



&lt;p&gt;As a result, it is imperative that the body of our request encapsulates an email that conforms to a valid email format, along with a password represented as a string. Failing to meet these criteria will trigger the system to return a '400 Bad Request' response to the user, indicating that the input does not satisfy the necessary conditions, and urging the user to amend the input accordingly&lt;/p&gt;

&lt;p&gt;The culmination of our setup process involves one final, vital step. In our main.ts file, we need to implement a global pipe, aptly named 'ValidationPipe', which is sourced from the @nestjs/common package. This particular pipe functions as a facilitator, enabling the validations defined in our body to be actively executed, thereby ensuring that the input data adheres strictly to the established criteria.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
    }),
  );
  await app.listen(3000);
}
bootstrap();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We utilize the 'whitelist: true' setting as a means to guide NestJS in managing unexpected properties in the request body. Specifically, if the body contains properties beyond those stipulated in our DTO (like a 'name' field appearing alongside the 'email' and 'password' fields), this setting will ensure such surplus properties are automatically removed. Consequently, the validation process focuses solely on the parameters defined within our DTO, promoting a clean and streamlined data handling process that adheres to our established structure.&lt;/p&gt;

&lt;p&gt;In this blog post, we have navigated through the intricacies of implementing validations within NestJS. Yet, one may wonder, how does specifying our body as our DTO facilitate achieving the desired validation? This underlying mechanism, which forms the crux of the validation process, warrants further exploration. Stay tuned, as we unravel this concept in greater depth in my forthcoming blog post. 😎&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>backend</category>
      <category>tutorial</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Protect Your Routes in Angular with Guards: Control Access and Exit of Routes Efficiently!</title>
      <dc:creator>Fredy Daniel Flores Lemus </dc:creator>
      <pubDate>Sat, 16 Sep 2023 18:59:41 +0000</pubDate>
      <link>https://forem.com/fredydlemus/protect-your-routes-in-angular-with-guards-control-access-and-exit-of-routes-efficiently-10a0</link>
      <guid>https://forem.com/fredydlemus/protect-your-routes-in-angular-with-guards-control-access-and-exit-of-routes-efficiently-10a0</guid>
      <description>&lt;p&gt;&lt;a href="https://twitter.com/fredydlemus" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.instagram.com/fredydlemus/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking for a way to manage access to your routes in Angular? Guards are the perfect tool for this task. In this blog post, I'll break down how Guards operate and how you can implement them to enhance your application's security. With Guards, you'll be able to specify who can access which routes and redirect unauthorized users to different sections of your application!&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating Access Guard
&lt;/h2&gt;

&lt;p&gt;To create a Guard in Angular, the first step is to establish a new service that will house the code for your Guard. In my case, I will name the service "AuthGuard".&lt;/p&gt;

&lt;p&gt;It's crucial to note that, in order to utilize Guards in your application, you need to import the CanActivate class from the @angular/router module and apply it as an interface to the service you have created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from "@angular/core";
import { CanActivate } from "@angular/router";

@Injectable({ provideIn: "root" })
export class AuthGuard implements CanActive {
  canActivate(): boolean {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you create the Guard service in Angular, you must implement a method called canActivate() within it. This method is responsible for determining whether a user has access to a specific route or not. It should return a boolean value: true if the user can access the route and false otherwise.&lt;/p&gt;

&lt;p&gt;Therefore, within the canActivate() method, you will need to write the necessary code to check if the user meets the access requirements for the particular route. For instance, you can check if the user is logged in, or if they have certain permissions or roles, etc.&lt;/p&gt;

&lt;p&gt;If the user fulfills the access requirements, the canActivate() method should return true. Otherwise, you should redirect the user to another route and return false.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;canActivate(route: ActivatedRouteSnapshot, state:
RouterStateSnapshot): Observable&amp;lt;boolean&amp;gt; | Promise&amp;lt;boolean&amp;gt; | boolean{
    return this.authService.isAuthenticated()
        .then(
            (authenticated: boolean) =&amp;gt;{
                if (authenticated){
                    return true;
                }else{
                    this.router.navigate(['/']);
                    return false;
                }
            }
        )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementing Access Guard
&lt;/h2&gt;

&lt;p&gt;Lastly, to use a Guard on a specific route in Angular, you need to add the canActivate property to the configuration of the respective route. This property is an array that should include the service you created to implement the Guard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const appRoutes: Routes = [
  {
    path: "servers",
    canActivate: [AuthGuard],
    component: ServersComponent,
  },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exit Guard
&lt;/h2&gt;

&lt;p&gt;With this, we will manage to have a protected route that executes a guard to confirm whether or not it is accessible, but often we also want to secure the exits of our routes.&lt;/p&gt;

&lt;p&gt;Angular Guards also allow you to control whether a user can leave a route or not. This is useful, for instance, to prevent a user from closing a page in the middle of an important process without saving the changes.&lt;/p&gt;

&lt;p&gt;To control the exit of a route in Angular, you need to create a Guard in a new service that implements the CanDeactivate interface. This interface is similar to CanActivate, but it triggers when a user attempts to leave a route instead of accessing it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from "@angular/core";
import {
  ActivatedRouteSnapshot,
  CanDeactivate,
  RouterStateSnapshot,
} from "@angular/router";
import { Observable } from "rxjs";

export interface CanComponentDeactivate {
  canDeactivate: () =&amp;gt; Observable&amp;lt;boolean&amp;gt; | Promise&amp;lt;boolean&amp;gt; | boolean;
}

@Injectable({ provideIn: "root" })
export class CanDeactivateGuard
  implements CanDeactivate&amp;lt;CanComponentDeactivate&amp;gt;
{
  canDeactivate(component: CanComponentDeactivate) boolean{
    return component.canDeactivate();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the CanDeactivate method receives the component that is being rendered on the route as a parameter, and within this component, adds a method called canDeactivate() that contains the necessary code to verify if the user can leave the route or not. This method should return a boolean value: true if the user can exit the route and false otherwise.&lt;/p&gt;

&lt;p&gt;Important! When you use a Guard that implements the CanDeactivate interface to control the exit of a route in Angular, you have the option to execute the access verification code either in the service implementing the Guard or in the component being rendered on the route.&lt;/p&gt;

&lt;p&gt;The advantage of executing the access verification code in the component is that you can use the component's attributes to define your verification logic. This allows you to have greater control over the verification process and make it more specific for each component.&lt;/p&gt;

&lt;p&gt;On the other hand, if you execute the access verification code in the service implementing the Guard, you can reuse the same code for several different components. This can be more efficient and maintainable, especially if you have multiple components that share the same access verification requirements.&lt;/p&gt;

&lt;p&gt;In summary, the choice of where to execute the access verification code depends on your needs and preferences. You can do it in the component to have greater control over the process or in the service to reuse the code across various components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;canDeactivate(): boolean | Observable&amp;lt;boolean&amp;gt; | Promise&amp;lt;boolean&amp;gt;{
    if(!this.allowEdit){
        return true;
    }
    if((this.serverName !== this.server.name || this.serverStatus !== this.server.status) &amp;amp;&amp;amp; !this.changesSaved){
        return confirm('Do you want to discard the changes?')
    }else{
        return true;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you can see the canDeactivate method applied in the component that is rendered according to the route, which in my example returns true if the user has saved changes or, in the other case, returns a confirm dialog asking the user if they wish to leave the route without saving their changes.&lt;/p&gt;

&lt;p&gt;Lastly, in the route configuration, add the canDeactivate property and pass the service you created to implement the Guard as an argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const appRoutes: Routes = [
  {
    path: "servers/edit",
    canDeactivate: [CanDeactivateGuard],
    component: EditServerComponent,
  },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this post, we have learned how to secure our routes in Angular using Guards. We've explored how to use the CanActivate and CanDeactivate Guards to control access to and exit from routes, respectively. Additionally, we've discussed how to implement these Guards and how to apply them in route configurations.&lt;/p&gt;

&lt;p&gt;With this knowledge, you now know how to protect your routes in Angular and can employ this technique to ensure that a route is accessed or left only under specific conditions. This will grant you greater control over the flow of your application and guarantee that certain areas are accessed or certain actions are carried out only if predefined requirements are met. I hope you enjoyed learning about this topic!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>angular</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Basic concepts of Routing and Navigation in Web Applications with Angular</title>
      <dc:creator>Fredy Daniel Flores Lemus </dc:creator>
      <pubDate>Wed, 13 Sep 2023 22:20:28 +0000</pubDate>
      <link>https://forem.com/fredydlemus/basic-concepts-of-routing-and-navigation-in-web-applications-with-angular-42fn</link>
      <guid>https://forem.com/fredydlemus/basic-concepts-of-routing-and-navigation-in-web-applications-with-angular-42fn</guid>
      <description>&lt;h2&gt;
  
  
  creating our router
&lt;/h2&gt;

&lt;p&gt;When you develop an application with Angular, you are creating a SPA (Single Page Application). This means that the server sends us an empty HTML file, and then the content of the application is rendered through JavaScript. If you want to add different pages, you must use the Angular router to control which components are displayed according to the route in the browser.&lt;/p&gt;

&lt;p&gt;To organize the paths and the different sections that will be shown in your application, start by establishing a constant in the file called app.module.ts, where you'll detail an array of different routes. Each item in this array indicates a specific path and the matching section or component that should appear when that path is visited in the browser. This method clearly lays out the navigation structure of your application, indicating what users will see at each step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Routes } from "@angular/router";

const appRoutes: Routes = [
  { path: "", component: AppComponent },
  { path: "users", component: UsersComponent },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you've created your list of paths or routes, bring it into the app.module.ts file. Here, you'll use a tool called RouterModule and a method named 'forRoot' to apply your list of routes as a guiding parameter. This step helps in effortlessly steering through your application, showing users the right sections or components depending on the path they are on at any given time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {
    Routes,
    RouterModule }
from "@angular/router";

const appRoutes: Routes = [
  { path: "", component: AppComponent },
  { path: "users", component: UsersComponent },
];

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        RouterModule.forRoot(appRoutes)
    ],
    providers: [],
    bootstrap: [AppComponent]
});
export class AppModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get your routing system up and running, you need to insert a special instruction called the 'router-outlet directive' from Angular in the area where you'd like the matching components for each path to appear. This instruction looks at the current browser's path and alters the displayed component in that area based on the path setup you created earlier. In my case, I'll be adding this instruction into the main viewing area of my principal component, which is found in the file named app.component.html.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;router-outlet&amp;gt;&amp;lt;/router-outlet&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When someone visits the main address of your website (like "mydomain.com") without adding any extra path, they will see the main, or 'HomeComponent', section. If they specifically go to "mydomain.com/users", they will instead see the 'UsersComponent' section. Basically, the router looks at the part of the web address after the domain name to decide which part of your site to show them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigating with our router
&lt;/h2&gt;

&lt;p&gt;When you want to create clickable links that lead from one section to another on your website, use Angular's 'routerLink' feature instead of the regular 'href' attribute that you would use in an HTML &lt;a&gt; tag. This feature lets users click through to different parts of the site without causing the whole page to reload each time, keeping the navigation smooth and fast.&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;a routerLink="/users"&amp;gt;Go to Users&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  navigate through events
&lt;/h2&gt;

&lt;p&gt;To wrap up this article, we'll explore how to move to a different section by triggering an event, like clicking a button. You'll need to set up an 'event binding' on the button, which is a way to connect the button click to a function that you've defined in the respective component's script file (so if your button is located in the 'home.component.html' file, the function it triggers would be found in the 'home.component.ts' file).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button (click)="onNavigate()"&amp;gt;
    Go to other page
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this file, you'll also need to incorporate the Router module within the component's constructor. Doing this allows you to make use of the Router's functions within the component itself.&lt;/p&gt;

&lt;p&gt;After you've incorporated the Router module, you set up a function that activates when the event happens (like a click). In this function, you use the 'navigate' method from the Router module and specify the path you want to head to, formatted as an array. This setup allows you to steer the navigation in your web app smoothly, showing users different sections depending on which path they are on at that moment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Routes } from "@angular/router";

...

export class AppComponent {
    constructor(private router: Router){}

    onNavigate(){
        this.router.navigate(['/servers']);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've come to the end, but really, we've only just scratched the surface when it comes to using Angular's router for navigation! There's so much more to explore and learn about managing your web application's navigation and showcasing different sections to users depending on the paths they visit. Keep an eye out for future posts where we'll dig even deeper into all the functionalities the Angular router can provide!&lt;/p&gt;

&lt;p&gt;Thanks a lot for reading.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
