<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maria Baptista</title>
    <description>The latest articles on DEV Community by Maria Baptista (@mariajtik).</description>
    <link>https://dev.to/mariajtik</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3347538%2Fa6e7eb72-b727-42ed-95e5-20ff737878d3.png</url>
      <title>DEV Community: Maria Baptista</title>
      <link>https://dev.to/mariajtik</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mariajtik"/>
    <language>en</language>
    <item>
      <title>Why Salesforce? Where Technology Meets Business</title>
      <dc:creator>Maria Baptista</dc:creator>
      <pubDate>Sun, 30 Aug 2026 19:29:04 +0000</pubDate>
      <link>https://dev.to/mariajtik/why-salesforce-where-technology-meets-business-3bb7</link>
      <guid>https://dev.to/mariajtik/why-salesforce-where-technology-meets-business-3bb7</guid>
      <description>&lt;p&gt;As a &lt;em&gt;&lt;strong&gt;software developer&lt;/strong&gt;&lt;/em&gt;, I have always been interested in the point where &lt;em&gt;technology&lt;/em&gt; stops being &lt;u&gt;&lt;strong&gt;just code&lt;/strong&gt;&lt;/u&gt; and starts solving a &lt;strong&gt;business problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That is one of the reasons &lt;strong&gt;Salesforce&lt;/strong&gt; interests me now.&lt;/p&gt;

&lt;p&gt;Salesforce is not simply a &lt;strong&gt;CRM platform&lt;/strong&gt;. It is an ecosystem where &lt;em&gt;customer data, business processes, automation, applications, analytics&lt;/em&gt; and &lt;em&gt;increasingly artificial intelligence&lt;/em&gt; can come &lt;strong&gt;together&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For someone with a &lt;strong&gt;&lt;em&gt;technical background&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;experience&lt;/em&gt;&lt;/strong&gt; across &lt;em&gt;development&lt;/em&gt;, &lt;em&gt;automation&lt;/em&gt;, &lt;em&gt;customer interaction&lt;/em&gt;, &lt;em&gt;sales&lt;/em&gt; and &lt;em&gt;digital processes&lt;/em&gt;, that combination is &lt;u&gt;particularly interesting.&lt;/u&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Salesforce as a CRM
&lt;/h2&gt;

&lt;p&gt;At its core, &lt;strong&gt;Salesforce&lt;/strong&gt; helps organizations manage relationships and interactions with their customers.&lt;/p&gt;

&lt;p&gt;But the platform becomes much more interesting when we look at how its different building blocks work together.&lt;/p&gt;

&lt;p&gt;Some of the fundamental concepts include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accounts&lt;/li&gt;
&lt;li&gt;Contacts&lt;/li&gt;
&lt;li&gt;Leads&lt;/li&gt;
&lt;li&gt;Opportunities&lt;/li&gt;
&lt;li&gt;Cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These objects represent different parts of a company's relationship with customers and prospects.&lt;/p&gt;

&lt;p&gt;For example, a &lt;em&gt;Lead&lt;/em&gt; can represent a &lt;em&gt;potential customer.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An &lt;em&gt;Account&lt;/em&gt; can represent a &lt;em&gt;company&lt;/em&gt; or &lt;em&gt;organization&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;Contact&lt;/em&gt; represents a &lt;em&gt;person&lt;/em&gt; associated with an account.&lt;/p&gt;

&lt;p&gt;An &lt;em&gt;Opportunity&lt;/em&gt; represents a &lt;em&gt;potential business&lt;/em&gt; opportunity.&lt;/p&gt;

&lt;p&gt;And a &lt;em&gt;Case&lt;/em&gt; can represent a customer service &lt;em&gt;issue&lt;/em&gt; that needs to be managed.&lt;/p&gt;

&lt;p&gt;Understanding these relationships is important because CRM is ultimately about understanding the customer journey and the processes surrounding it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sales Cloud
&lt;/h2&gt;

&lt;p&gt;Sales Cloud focuses on supporting &lt;strong&gt;sales processes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The concepts of &lt;strong&gt;Leads&lt;/strong&gt; and &lt;strong&gt;Opportunities&lt;/strong&gt; are particularly important here.&lt;/p&gt;

&lt;p&gt;A company might start with a &lt;strong&gt;potential&lt;/strong&gt; lead, &lt;strong&gt;qualify&lt;/strong&gt; that lead, and eventually &lt;strong&gt;manage&lt;/strong&gt; a business &lt;strong&gt;opportunity&lt;/strong&gt; through different stages of the &lt;strong&gt;sales process&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Technology can then help make this process more organized, measurable and automated.&lt;/p&gt;

&lt;p&gt;This connects closely with my own experience.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have worked with lead generation, digital marketing, WhatsApp communication and the handoff of potential customers to business teams.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That experience made me interested in the technological side of the same process.&lt;/p&gt;

&lt;p&gt;Instead of simply generating and forwarding leads, &lt;strong&gt;CRM&lt;/strong&gt; platforms can provide a structured environment for &lt;strong&gt;managing&lt;/strong&gt; the &lt;strong&gt;entire relationship.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Service Cloud
&lt;/h2&gt;

&lt;p&gt;Sales is only one part of the customer relationship.&lt;/p&gt;

&lt;p&gt;After a customer becomes a customer, &lt;strong&gt;support&lt;/strong&gt; and &lt;strong&gt;service&lt;/strong&gt; become equally important.&lt;/p&gt;

&lt;p&gt;This is where &lt;em&gt;Service Cloud&lt;/em&gt; becomes relevant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cases&lt;/strong&gt; can be used to &lt;em&gt;organize&lt;/em&gt; customer &lt;em&gt;issues&lt;/em&gt;, &lt;em&gt;requests&lt;/em&gt; and &lt;em&gt;support processes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My experience at CLYRA included two months working directly with customer support, helping users with questions and problems related to the platform.&lt;/p&gt;

&lt;p&gt;That experience gave me a practical understanding of something important in CRM:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Customer experience does not end when the sale happens.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Automation with Salesforce Flows
&lt;/h2&gt;

&lt;p&gt;One of the concepts that I understand just living as a Developer is automation through &lt;strong&gt;Salesforce Flow.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;business&lt;/em&gt; process often contains &lt;strong&gt;repetitive steps&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of requiring a person to manually perform every action (&lt;del&gt;_Imagine running a huge company and having to type in data for millions of people&lt;/del&gt;... nowadays, it makes no sense)_, so, a flow can automate parts of the process based on defined conditions and events.&lt;/p&gt;

&lt;p&gt;This immediately connects with my previous experience using &lt;strong&gt;n8n&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Although the technologies and platforms are different, the underlying idea is familiar:&lt;/p&gt;

&lt;p&gt;«Understand the process → identify repetitive actions → define conditions → automate the workflow → validate the result.»&lt;/p&gt;

&lt;p&gt;This is one of the reasons I believe my existing automation experience can provide a strong foundation for learning Salesforce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration vs Development
&lt;/h2&gt;

&lt;p&gt;Another distinction that interests me is the relationship between configuration and development.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Salesforce solution&lt;/strong&gt; does &lt;strong&gt;not&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;necessarily&lt;/em&gt;&lt;/strong&gt; require custom code for &lt;strong&gt;every requirement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sometimes the platform's existing capabilities and configuration options are enough.&lt;/p&gt;

&lt;p&gt;Other situations may require custom development.&lt;/p&gt;

&lt;p&gt;Understanding when to configure and when to develop is therefore not only a technical question.&lt;/p&gt;

&lt;p&gt;It is a solution-design question.&lt;/p&gt;

&lt;p&gt;The goal should not be to write more code.&lt;/p&gt;

&lt;p&gt;The goal should be to build the most appropriate solution for the customer's requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lightning and the Salesforce Platform
&lt;/h2&gt;

&lt;p&gt;The Salesforce Platform provides an environment for building and extending business applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lightning&lt;/strong&gt; provides the modern experience through which users interact with Salesforce and its applications.&lt;/p&gt;

&lt;p&gt;For someone coming from &lt;strong&gt;web development&lt;/strong&gt;, concepts such as components, interfaces, data, workflows and application logic provide interesting connections with technologies I have already worked with.&lt;/p&gt;

&lt;p&gt;My background in JavaScript, React, Node.js, APIs and UI/UX gives me a foundation for understanding these concepts while learning the Salesforce-specific ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apex — Conceptually
&lt;/h2&gt;

&lt;p&gt;Apex is Salesforce's programming language for developing custom logic on the platform.&lt;/p&gt;

&lt;p&gt;I am approaching Apex from the perspective of understanding where custom programming fits into the Salesforce ecosystem.&lt;/p&gt;

&lt;p&gt;Coming from JavaScript and Node.js, I already have experience with programming logic, APIs, backend development and application architecture.&lt;/p&gt;

&lt;p&gt;The syntax and platform-specific concepts are different, but the underlying software engineering principles remain relevant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear logic&lt;/li&gt;
&lt;li&gt;Maintainability&lt;/li&gt;
&lt;li&gt;Separation of responsibilities&lt;/li&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Understanding requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not simply to learn another syntax.&lt;/p&gt;

&lt;p&gt;It is to understand how development works within the Salesforce platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dashboards and Business Visibility
&lt;/h2&gt;

&lt;p&gt;Data becomes much more useful when it helps people make decisions.&lt;/p&gt;

&lt;p&gt;Salesforce &lt;strong&gt;dashboards&lt;/strong&gt; and reports can transform CRM data into information that business teams can actually use.&lt;/p&gt;

&lt;p&gt;For example, an organization might want to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many leads are being generated?&lt;/li&gt;
&lt;li&gt;How many opportunities are active?&lt;/li&gt;
&lt;li&gt;Which opportunities are progressing?&lt;/li&gt;
&lt;li&gt;How quickly are customer cases being resolved?&lt;/li&gt;
&lt;li&gt;Where are potential bottlenecks in the sales process?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where CRM moves beyond data storage.&lt;/p&gt;

&lt;p&gt;It becomes a decision-support system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Permissions and Trust
&lt;/h2&gt;

&lt;p&gt;A CRM contains sensitive business and customer information.&lt;/p&gt;

&lt;p&gt;That makes permissions and access control an important part of Salesforce.&lt;/p&gt;

&lt;p&gt;Different users may need different levels of access depending on their responsibilities.&lt;/p&gt;

&lt;p&gt;Understanding who can see, modify or manage information is therefore part of designing a responsible business solution.&lt;/p&gt;

&lt;p&gt;This is another reminder that enterprise software is not only about functionality.&lt;/p&gt;

&lt;p&gt;It is also about governance, security and trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Salesforce and Artificial Intelligence
&lt;/h2&gt;

&lt;p&gt;The evolution of Salesforce towards AI is another reason I find the ecosystem good to explore.&lt;/p&gt;

&lt;p&gt;AI can potentially help organizations work with their customer data more intelligently, assist users and automate parts of business processes.&lt;/p&gt;

&lt;p&gt;But I believe the same principle applies here as in software development:&lt;/p&gt;

&lt;p&gt;AI should amplify human judgment, not replace it.&lt;/p&gt;

&lt;p&gt;Good AI implementation starts with understanding the business problem.&lt;/p&gt;

&lt;p&gt;Without that understanding, adding AI simply because it is available does not necessarily create value.&lt;/p&gt;

&lt;p&gt;Why Salesforce?&lt;/p&gt;

&lt;p&gt;So, why Salesforce?&lt;/p&gt;

&lt;p&gt;Personal goals...&lt;br&gt;
Because it sits exactly at an intersection that interests me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Technology + Business + Customers + Automation + AI.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My experience is not limited to software development.&lt;/p&gt;

&lt;p&gt;I have worked with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web development&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;Automation&lt;/li&gt;
&lt;li&gt;UI/UX&lt;/li&gt;
&lt;li&gt;Artificial Intelligence tools&lt;/li&gt;
&lt;li&gt;Customer support&lt;/li&gt;
&lt;li&gt;Lead generation&lt;/li&gt;
&lt;li&gt;Digital marketing&lt;/li&gt;
&lt;li&gt;Business processes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Salesforce gives me an opportunity to bring these experiences together while developing deeper expertise in CRM and enterprise technology.&lt;/p&gt;

&lt;p&gt;I am particularly interested in learning the platform in a real consulting environment, understanding customer requirements, contributing to implementations and continuously developing my technical and business skills.&lt;/p&gt;

&lt;p&gt;I don't see Salesforce as simply another technology to add to my CV.&lt;/p&gt;

&lt;p&gt;I see it as an opportunity to become better at something I find increasingly important in technology:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building solutions that make sense not only technically, but also for the people and businesses using them.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Learning by doing! Dev.to friend's! Even though I'm already familiar with the concepts, I'm taking a 52-hour course to sharpen my skills. I've just hit the 10% mark, and my goal is to finish it in 5 days, posting every new progress right here in the comments! Stay tuned and share with me. 🐞&lt;/p&gt;

</description>
      <category>salesforce</category>
      <category>tecnology</category>
    </item>
    <item>
      <title>AI-Assisted Development Without Losing Engineering Judgment</title>
      <dc:creator>Maria Baptista</dc:creator>
      <pubDate>Sat, 29 Aug 2026 12:49:32 +0000</pubDate>
      <link>https://dev.to/mariajtik/ai-assisted-development-without-losing-engineering-judgment-4md1</link>
      <guid>https://dev.to/mariajtik/ai-assisted-development-without-losing-engineering-judgment-4md1</guid>
      <description>&lt;p&gt;Modern software development gives us access to increasingly powerful &lt;strong&gt;&lt;em&gt;AI tools&lt;/em&gt;&lt;/strong&gt;. But using AI effectively is not the same as letting &lt;del&gt;AI make every technical decision.&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;For me, AI is most valuable when it accelerates the development process while the developer remains responsible for architecture, requirements, user experience, integrations and the final result.&lt;/p&gt;

&lt;p&gt;This approach became particularly relevant in my work at &lt;strong&gt;CLYRA&lt;/strong&gt;, where I worked across frontend development, backend development, UI/UX, automation and external integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI as Part of the Development Workflow
&lt;/h2&gt;

&lt;p&gt;At CLYRA, Lovable was an important part of my development workflow.&lt;/p&gt;

&lt;p&gt;Rather than treating it as a replacement for development, I used &lt;em&gt;AI-assisted tooling&lt;/em&gt; to &lt;strong&gt;accelerate&lt;/strong&gt; activities such as &lt;strong&gt;prototyping&lt;/strong&gt;, &lt;strong&gt;exploring&lt;/strong&gt; interfaces and moving &lt;strong&gt;ideas&lt;/strong&gt; towards &lt;strong&gt;implementation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The important part was not simply generating code.&lt;/p&gt;

&lt;p&gt;The important part was deciding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What should be built?&lt;/li&gt;
&lt;li&gt;What should the user experience look like?&lt;/li&gt;
&lt;li&gt;How should different services communicate?&lt;/li&gt;
&lt;li&gt;What belongs in the frontend?&lt;/li&gt;
&lt;li&gt;What belongs in the backend?&lt;/li&gt;
&lt;li&gt;How should an external API be integrated?&lt;/li&gt;
&lt;li&gt;How should the resulting functionality behave in a real product?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI could accelerate the path from an idea to an implementation, but &lt;u&gt;engineering judgment remained essential.&lt;/u&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  React, Node.js and Tailwind CSS
&lt;/h2&gt;

&lt;p&gt;My work also involved technologies that sit at the core of &lt;em&gt;modern web development&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I worked with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React.js&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;REST APIs&lt;/li&gt;
&lt;li&gt;UI/UX&lt;/li&gt;
&lt;li&gt;n8n&lt;/li&gt;
&lt;li&gt;External service integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allowed me to work across different parts of a product rather than focusing exclusively on one layer.&lt;/p&gt;

&lt;p&gt;On the &lt;strong&gt;&lt;em&gt;frontend&lt;/em&gt;&lt;/strong&gt;, React and Tailwind CSS supported the development of modern interfaces.&lt;/p&gt;

&lt;p&gt;On the &lt;strong&gt;&lt;em&gt;backend&lt;/em&gt;&lt;/strong&gt;, Node.js enabled application logic and integrations.&lt;/p&gt;

&lt;p&gt;And between systems, APIs connected the different services required by the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automation with n8n
&lt;/h2&gt;

&lt;p&gt;Another important part of the workflow was automation.&lt;/p&gt;

&lt;p&gt;I worked with n8n to create and manage workflows, connecting different services and reducing repetitive manual processes.&lt;/p&gt;

&lt;p&gt;This is one of the areas where I find the combination of &lt;strong&gt;&lt;em&gt;AI&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;automation&lt;/em&gt;&lt;/strong&gt; particularly interesting.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI can help accelerate the creation and exploration of solutions.&lt;/p&gt;

&lt;p&gt;Automation can make those solutions repeatable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But someone still needs to understand the &lt;u&gt;&lt;strong&gt;business process being automated&lt;/strong&gt;&lt;/u&gt;.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;A technically impressive automation that solves the wrong problem is still the wrong solution.&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating Real-World Services
&lt;/h2&gt;

&lt;p&gt;The work at CLYRA also involved integrations with external services, including:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WhatsApp API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Used as part of communication and platform workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;QR Codes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Used as part of the product's digital interaction flows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stripe&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Used for payment functionality and plan management.&lt;/p&gt;

&lt;p&gt;These integrations reinforced something that is easy to overlook when learning software development:&lt;/p&gt;

&lt;p&gt;«&lt;strong&gt;&lt;em&gt;A product is rarely just the interface.&lt;/em&gt;&lt;/strong&gt;»&lt;/p&gt;

&lt;p&gt;A real application needs its &lt;strong&gt;&lt;em&gt;frontend, backend, APIs, authentication, automation, payments and user experience&lt;/em&gt;&lt;/strong&gt; to work &lt;strong&gt;together&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customer Support Changed How I Think About Software
&lt;/h2&gt;

&lt;p&gt;For two months at CLYRA, I also worked in customer support.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(I am highlighting my corporate experience at Clyra because my prior experience involved more autonomous roles with fewer administrative constraints)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Customers&lt;/em&gt;&lt;/strong&gt; contacted the team with questions and &lt;em&gt;&lt;strong&gt;problems&lt;/strong&gt;&lt;/em&gt; related to the &lt;strong&gt;&lt;em&gt;platform&lt;/em&gt;&lt;/strong&gt;, and we helped them &lt;strong&gt;understand&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;resolve&lt;/em&gt;&lt;/strong&gt; those &lt;strong&gt;issues&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That experience was valuable because it put me on the other side of the product.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;feature&lt;/strong&gt; can work &lt;strong&gt;technically&lt;/strong&gt; and still be &lt;u&gt;&lt;strong&gt;confusing to the person using it.&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;&lt;em&gt;workflow&lt;/em&gt;&lt;/strong&gt; can be &lt;strong&gt;&lt;em&gt;logically&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;correct&lt;/em&gt;&lt;/strong&gt; and still &lt;u&gt;&lt;em&gt;fail to solve the customer's actual problem.&lt;/em&gt;&lt;/u&gt;&lt;/p&gt;

&lt;p&gt;This is one reason I consider customer understanding an important part of software development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Without AI
&lt;/h2&gt;

&lt;p&gt;AI-assisted development is powerful, but &lt;strong&gt;&lt;em&gt;I don't consider it a requirement for building software.&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;I am also _comfortable developing projects _using &lt;strong&gt;conventional&lt;/strong&gt; engineering &lt;strong&gt;practices&lt;/strong&gt; and &lt;strong&gt;technologies&lt;/strong&gt; without relying on AI to generate the solution.&lt;/p&gt;

&lt;p&gt;One example is &lt;strong&gt;Kwendi&lt;/strong&gt;, a project focused on technology, education and the learning of Umbundu.&lt;/p&gt;

&lt;p&gt;The project involves product thinking, application architecture, UI/UX and the design of a learning experience.&lt;/p&gt;

&lt;p&gt;The important lesson for me is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI is a tool. It is not the developer.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A strong developer should be able to work with AI when it creates value, but should also be able to reason about a problem, design a solution and build software independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Take From This
&lt;/h2&gt;

&lt;p&gt;My approach to modern software development can be summarized in four ideas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Understand the problem → Design the solution → Use the right tools → Validate the result.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes the right tool is &lt;strong&gt;AI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sometimes it is &lt;strong&gt;automation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Sometimes it is simply writing the &lt;strong&gt;code yourself&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The technology should serve the problem — not the other way around.&lt;/p&gt;

&lt;p&gt;And that is where I believe AI-assisted development becomes genuinely powerful: when it increases the developer's ability to experiment, learn and deliver without removing responsibility for the final solution.&lt;/p&gt;




</description>
      <category>automation</category>
      <category>ai</category>
      <category>productivity</category>
      <category>coding</category>
    </item>
    <item>
      <title>Building a Full Stack App with .NET and Angular the TDD Way</title>
      <dc:creator>Maria Baptista</dc:creator>
      <pubDate>Fri, 19 Sep 2025 16:19:19 +0000</pubDate>
      <link>https://dev.to/mariajtik/building-a-full-stack-app-with-net-and-angular-the-tdd-way-37ih</link>
      <guid>https://dev.to/mariajtik/building-a-full-stack-app-with-net-and-angular-the-tdd-way-37ih</guid>
      <description>&lt;p&gt;In this hands-on guide, we'll build a full-stack application from scratch using .NET for the backend and Angular for the frontend, but with one golden rule: no production code is written unless a test fails first. &lt;strong&gt;Welcome to the world of TDD!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge: Confidence in Your Code
&lt;/h2&gt;

&lt;p&gt;How many times have you fixed a bug, only to accidentally break another part of the system? Or implemented a new feature, fearing that something might go wrong in production? A lack of confidence in our own code is one of the biggest enemies of a developer's productivity and peace of mind.&lt;/p&gt;

&lt;p&gt;The solution? A safety net. A suite of automated tests that ensures your application behaves exactly as expected. And the best way to build this net is to weave it as you build the application itself.&lt;/p&gt;

&lt;p&gt;In this article, we'll build a simple to-do list application using a modern stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Backend:&lt;/strong&gt; .NET 7 Web API&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Frontend:&lt;/strong&gt; Angular 14+&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Methodology:&lt;/strong&gt; Test-Driven Development (TDD) from end to end.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our golden rule will be the classic TDD cycle: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Red -&amp;gt; Green -&amp;gt; Refactor&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Red:&lt;/strong&gt; Write a test that fails because the feature doesn't exist yet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Green:&lt;/strong&gt; Write the simplest possible code to make the test pass.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Refactor:&lt;/strong&gt; Improve the code without changing its behavior (and without breaking the test).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's start with the backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: The Test-Driven .NET Backend
&lt;/h2&gt;

&lt;p&gt;Our goal is to create a &lt;code&gt;GET /api/tasks&lt;/code&gt; endpoint that returns a list of tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Red - Writing the First Test
&lt;/h3&gt;

&lt;p&gt;First, we create a test project (using xUnit, NUnit, etc.) and write a test for our future &lt;code&gt;TasksController&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In the Test project (e.g., Tasks.API.Tests/TasksControllerTests.cs)&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TasksControllerTests&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;GetTasks_WhenCalled_ShouldReturnOkWithListOfTasks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
        &lt;span class="c1"&gt;// The controller doesn't even exist yet, but we're already defining how it should behave.&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TasksController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- This will cause a compile error!&lt;/span&gt;

        &lt;span class="c1"&gt;// Act&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTasks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// Assert&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;okResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OkObjectResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAssignableFrom&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TaskItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;okResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NotEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&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;At this point, the code doesn't compile. &lt;code&gt;TasksController&lt;/code&gt; doesn't exist, the &lt;code&gt;GetTasks&lt;/code&gt; method doesn't exist. Perfect. We are in the &lt;strong&gt;Red&lt;/strong&gt; phase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Green - Making the Test Pass
&lt;/h3&gt;

&lt;p&gt;Now, let's go to our API project and write the simplest possible code to make the test compile and pass.&lt;/p&gt;

&lt;p&gt;First, the &lt;code&gt;TaskItem&lt;/code&gt; model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In the API project (e.g., Tasks.API/Models/TaskItem.cs)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TaskItem&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsCompleted&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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;Now, the &lt;code&gt;TasksController&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// In the API project (e.g., Tasks.API/Controllers/TasksController.cs)&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.Mvc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/[controller]"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TasksController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetTasks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Warning: We are hardcoding the data.&lt;/span&gt;
        &lt;span class="c1"&gt;// This is the shortest path to "Green". Refactoring comes later.&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TaskItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;TaskItem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Learn TDD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IsCompleted&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="c1"&gt;// We use Task.FromResult to simulate an async operation&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&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;If we run our test now, it should pass. We are in the &lt;strong&gt;Green&lt;/strong&gt; phase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Refactor - Improving the Code
&lt;/h3&gt;

&lt;p&gt;The code works, but it's using a hardcoded list. Let's refactor it to use a service, preparing for a future database connection, without breaking our test.&lt;/p&gt;

&lt;p&gt;First, the service interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ITaskService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TaskItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAllAsync&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;Now, the refactored &lt;code&gt;TasksController&lt;/code&gt; using dependency injection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TasksController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&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="n"&gt;ITaskService&lt;/span&gt; &lt;span class="n"&gt;_taskService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;TasksController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ITaskService&lt;/span&gt; &lt;span class="n"&gt;taskService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Dependency Injection&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_taskService&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;taskService&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="n"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetTasks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_taskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAllAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&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;Of course, our test now breaks because the &lt;code&gt;TasksController&lt;/code&gt; constructor has changed. This is good! The test is protecting our architecture. Let's adjust it using a mock (with libraries like Moq or NSubstitute).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Adjusted Test&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;GetTasks_WhenCalled_ShouldReturnOkWithListOfTasks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mockService&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ITaskService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="n"&gt;mockService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAllAsync&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReturnsAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TaskItem&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;TaskItem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Title&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Test"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TasksController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mockService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Act&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetTasks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Assert&lt;/span&gt;
    &lt;span class="c1"&gt;// ... same assertions as before&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We run the tests again. Everything is &lt;strong&gt;Green&lt;/strong&gt;. We now have cleaner, decoupled, and equally functional code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: The Test-Driven Angular Frontend
&lt;/h2&gt;

&lt;p&gt;Let's apply the same logic in Angular to create a component that displays the tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Red - Testing the Component
&lt;/h3&gt;

&lt;p&gt;The Angular CLI already creates a test file (&lt;code&gt;.spec.ts&lt;/code&gt;) for us. Let's modify it to test if our &lt;code&gt;TaskListComponent&lt;/code&gt; calls the service and renders the data.&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;// task-list.component.spec.ts&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TaskListComponent&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TaskListComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ComponentFixture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TaskListComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;mockTaskService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jasmine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SpyObj&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We create a spy for our service&lt;/span&gt;
    &lt;span class="nx"&gt;mockTaskService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jasmine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createSpyObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TaskService&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getTasks&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="nx"&gt;TestBed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configureTestingModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;TaskListComponent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;useValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mockTaskService&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;compileComponents&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;fixture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;TestBed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TaskListComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;componentInstance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should call getTasks on init and render the tasks&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TaskItem&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test the component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isCompleted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}];&lt;/span&gt;
    &lt;span class="nx"&gt;mockTaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;and&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;returnValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Simulate the Observable's return&lt;/span&gt;

    &lt;span class="c1"&gt;// Act&lt;/span&gt;
    &lt;span class="nx"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;detectChanges&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Triggers ngOnInit and the component's lifecycle&lt;/span&gt;

    &lt;span class="c1"&gt;// Assert&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockTaskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTasks&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Was the service called?&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTMLElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeElement&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;taskTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskTitle&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toContain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test the component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Was the title rendered?&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test will fail. Our component is empty. We are in the &lt;strong&gt;Red&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Green - Implementing the Component
&lt;/h3&gt;

&lt;p&gt;Now, let's write the minimal code in the component and template to make the test pass.&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;// task-list.component.ts&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-task-list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./task-list.component.html&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TaskListComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;tasks$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TaskItem&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&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;taskService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TaskService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&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;tasks$&lt;/span&gt; &lt;span class="o"&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;taskService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTasks&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- task-list.component.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;*ngFor=&lt;/span&gt;&lt;span class="s"&gt;"let task of tasks$ | async"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {{ task.title }}
  &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the &lt;code&gt;TaskService&lt;/code&gt; will make the HTTP call to our .NET API.&lt;/p&gt;

&lt;p&gt;If we run the test now, it will pass. &lt;strong&gt;Green&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Refactor
&lt;/h3&gt;

&lt;p&gt;Our code is already quite clean thanks to the use of the &lt;code&gt;async&lt;/code&gt; pipe and &lt;code&gt;Observables&lt;/code&gt;. A possible refactoring would be to add error handling (and a test for it!), such as displaying a friendly message if the API fails. But for now, our cycle is complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: More Than Just Tests
&lt;/h2&gt;

&lt;p&gt;As we've seen, TDD isn't just about writing tests. It's a &lt;strong&gt;software design&lt;/strong&gt; methodology. It forces us to think about the interface and behavior of our components and services &lt;em&gt;before&lt;/em&gt; we implement them.&lt;/p&gt;

&lt;p&gt;The result is code that is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;More Reliable:&lt;/strong&gt; The test suite is your safety net.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;More Decoupled:&lt;/strong&gt; The need to mock dependencies encourages dependency injection and a cleaner design.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Better Documented:&lt;/strong&gt; The tests themselves serve as living documentation of how the system should behave.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Starting with TDD might feel slower at first, but the speed and confidence you gain in the long run are immeasurable. The next time you start a project, try writing a failing test first. It might just be the beginning of a new way of coding.&lt;/p&gt;



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

&lt;/div&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>csharp</category>
    </item>
    <item>
      <title>🚫 No Internet, No Cloud, No Problem: Building Monitoring Systems That Survive Offline</title>
      <dc:creator>Maria Baptista</dc:creator>
      <pubDate>Sat, 12 Jul 2025 05:51:19 +0000</pubDate>
      <link>https://dev.to/mariajtik/no-internet-no-cloud-no-problem-building-monitoring-systems-that-survive-offline-from-angola-4nca</link>
      <guid>https://dev.to/mariajtik/no-internet-no-cloud-no-problem-building-monitoring-systems-that-survive-offline-from-angola-4nca</guid>
      <description>&lt;p&gt;When you think about monitoring infrastructure, what comes to mind?&lt;/p&gt;

&lt;p&gt;Maybe dashboards in Grafana, real-time alerts from Prometheus, centralized logs, and seamless cloud connectivity across AWS or GCP...&lt;/p&gt;

&lt;p&gt;Well, none of that works here.&lt;/p&gt;

&lt;p&gt;🌍 &lt;strong&gt;Where I Come From&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m Maria, a self-taught engineer who has already had many problems of unstable infrastructure.&lt;/p&gt;

&lt;p&gt;Somewhere, it’s normal to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lose internet multiple times a day&lt;/li&gt;
&lt;li&gt;Have speeds under 1 Mbps&lt;/li&gt;
&lt;li&gt;See power cuts without warning&lt;/li&gt;
&lt;li&gt;Rely on SMS instead of Slack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But guess what? We still have systems to monitor. Critical alerts still matter. And that’s exactly why I started building my own solution.&lt;/p&gt;

&lt;p&gt;⚡ &lt;strong&gt;The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Traditional observability tools are powerful — but they &lt;em&gt;assume&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High uptime&lt;/li&gt;
&lt;li&gt;Fast internet&lt;/li&gt;
&lt;li&gt;Access to the cloud&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of those assumptions hold true in large parts of Africa, South America, and Asia. And most engineers in Silicon Valley don’t even realize it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I needed something different. Something &lt;strong&gt;local-first&lt;/strong&gt;, &lt;strong&gt;resilient&lt;/strong&gt;, and &lt;strong&gt;cloud-optional&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔧 &lt;strong&gt;Meet Kuze Alert&lt;/strong&gt; Monitoring for the Real World&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kuze Alert&lt;/strong&gt; is my open-source project designed to monitor systems in the harshest, most unreliable environments.&lt;/p&gt;

&lt;p&gt;It’s not just another tool. It’s a survival kit for devs like me who work under conditions where &lt;em&gt;“just push to the cloud”&lt;/em&gt; doesn’t work.&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Offline-first alert generation&lt;/li&gt;
&lt;li&gt;✅ Works on cheap hardware&lt;/li&gt;
&lt;li&gt;✅ Sends alerts via SMS or local radio&lt;/li&gt;
&lt;li&gt;✅ Compresses and syncs data when internet returns&lt;/li&gt;
&lt;li&gt;✅ Integrates with Prometheus locally&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;I’m currently building it in &lt;strong&gt;Go&lt;/strong&gt;, using &lt;strong&gt;Prometheus&lt;/strong&gt; and &lt;strong&gt;edge storage&lt;/strong&gt; (SQLite/in-memory).&lt;br&gt;&lt;br&gt;
Soon, it will support push/pull sync and even visual dashboards — without internet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;📡 &lt;strong&gt;Real-World Scenario&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a small ISP in Luanda that monitors routers in 3 provinces. The internet drops at night — every night.&lt;/p&gt;

&lt;p&gt;With Kuze Alert:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Metrics are collected &lt;strong&gt;locally&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Alerts are fired even &lt;strong&gt;offline&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Critical events are cached and sent &lt;strong&gt;when possible&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s observability that &lt;em&gt;respects your reality&lt;/em&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%2Fplcruamfv0odxqochxle.jpg" 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%2Fplcruamfv0odxqochxle.jpg" alt=" " width="736" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Why This Matters (and Not Just to Me)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Over &lt;strong&gt;3.5 billion people&lt;/strong&gt; live with unstable internet&lt;/li&gt;
&lt;li&gt;Cloud-first tools leave these people behind&lt;/li&gt;
&lt;li&gt;Most “global” tools break outside high-income regions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m building something different. Something grounded. Something I wish someone had built for me.&lt;/p&gt;

&lt;p&gt;👩🏽‍💻 &lt;strong&gt;Who I Am (and Why I’m Writing This)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m young. Woman. I’m self-taught. I’ve been building little systems since I was more younger.&lt;/p&gt;

&lt;p&gt;I created this article because I recently discovered the &lt;strong&gt;Dev.to&lt;/strong&gt; community — and I’m absolutely LOVING the energy here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The people, the projects, the passion — it’s inspiring.&lt;br&gt;&lt;br&gt;
I’m learning more every day, and I finally feel like I’ve found my tech family.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🔗 &lt;strong&gt;Follow My Journey&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm sharing everything I learn while building Kuze Alert, contributing to open source, and growing from Angola to the world.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/mariajtik" rel="noopener noreferrer"&gt;github.com/mariajtik&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💼 &lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a href="https://ao.linkedin.com/in/maria-baptista-95b582280" rel="noopener noreferrer"&gt;linkedin.com/in/maria-baptista-95b582280&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re working with observability, edge computing, or cloud-native systems, let’s connect (some other IT area, would be a pleasure too).&lt;br&gt;&lt;br&gt;
If you’ve ever built tech in low-resource environments, I want to hear your story.&lt;/p&gt;

&lt;p&gt;And if this article resonated with you — &lt;strong&gt;react, share, or comment&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
It helps me grow, and helps this message reach the people who need it most.&lt;/p&gt;

&lt;p&gt;✊🏽 &lt;strong&gt;Let’s Build a Truly Global Stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One that works offline.
&lt;/li&gt;
&lt;li&gt;One that’s resilient.
&lt;/li&gt;
&lt;li&gt;One that doesn’t leave half the world behind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Join me. ⭐ Star my GitHub. 💬 Leave your thoughts. 📣 Share this post.&lt;/p&gt;

&lt;h1&gt;
  
  
  Observability #Monitoring #AfricaTech #OpenSource #DevOps #Prometheus #Grafana #KuzeAlert #EdgeComputing #SelfTaught
&lt;/h1&gt;

</description>
      <category>networking</category>
      <category>architecture</category>
      <category>devops</category>
      <category>monitoring</category>
    </item>
  </channel>
</rss>
