<?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: Jasen</title>
    <description>The latest articles on DEV Community by Jasen (@jasen_dev).</description>
    <link>https://dev.to/jasen_dev</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%2F3161404%2Fd3fdadd1-9caf-4f71-bfd1-4199a99bfb27.png</url>
      <title>DEV Community: Jasen</title>
      <link>https://dev.to/jasen_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jasen_dev"/>
    <language>en</language>
    <item>
      <title>AI-assisted development in 2025: the problem is no longer the code</title>
      <dc:creator>Jasen</dc:creator>
      <pubDate>Wed, 17 Dec 2025 17:14:56 +0000</pubDate>
      <link>https://dev.to/jasen_dev/ai-assisted-development-in-2025-the-problem-is-no-longer-the-code-452e</link>
      <guid>https://dev.to/jasen_dev/ai-assisted-development-in-2025-the-problem-is-no-longer-the-code-452e</guid>
      <description>&lt;p&gt;AI coding assistants are no longer experimental — they've quietly become part of everyday development. &lt;strong&gt;Copilot, Claude, Cursor&lt;/strong&gt;, agent-based workflows — for many teams this is now just the default way of working.&lt;/p&gt;

&lt;p&gt;For a long time, I didn't fully buy into the hype.&lt;/p&gt;

&lt;p&gt;I was skeptical. I reviewed almost every line AI produced, verified edge cases, and double-checked logic. Most of the time, AI felt like a very confident junior developer: fast, enthusiastic, but prone to repetition, unnecessary abstractions, and bloated code. No matter which model I tried, the pattern was similar — code that looked ok, but required careful cleanup and verification.&lt;/p&gt;

&lt;p&gt;As for me, reading "mostly correct" AI-generated code is cognitively harder than writing it yourself. This isn't just a subjective feeling. A &lt;a href="https://www.reuters.com/business/ai-slows-down-some-experienced-software-developers-study-finds-2025-07-10/" rel="noopener noreferrer"&gt;2025 industry study reported by Reuters&lt;/a&gt; found that AI tools sometimes slow down experienced developers, because time saved during generation is lost during review and correction.&lt;/p&gt;

&lt;p&gt;Over time, however, something changed — not only in the tools, but also in me.&lt;/p&gt;

&lt;p&gt;I started relying more on agents. If the code worked, I stopped checking every single line. Not consciously, not intentionally — it just happened. Only later did I realize that this shift is not unique to me.&lt;/p&gt;

&lt;p&gt;Recent research describes this behavior as &lt;strong&gt;automation bias&lt;/strong&gt; — the tendency to trust automated systems even when they are wrong. What's counter-intuitive is that &lt;a href="https://arxiv.org/abs/2509.08514" rel="noopener noreferrer"&gt;studies show&lt;/a&gt; this effect is often stronger in experienced developers than in juniors. Once earlier AI suggestions appear correct, developers become significantly more likely to accept subsequent ones without deep scrutiny.&lt;/p&gt;

&lt;p&gt;That finding didn't feel abstract. It explained my own behavior uncomfortably well.&lt;/p&gt;

&lt;p&gt;This isn't about losing language knowledge or forgetting syntax. Research on human-AI interaction in development environments points to a deeper issue. A &lt;a href="https://arxiv.org/abs/2503.06195" rel="noopener noreferrer"&gt;2025 systematic literature review&lt;/a&gt; analyzing 89 peer-reviewed studies shows recurring patterns: reduced independent problem formulation, weaker mental models of systems, and a gradual outsourcing of reasoning to tools.&lt;/p&gt;

&lt;p&gt;Developers still know how to implement things — but increasingly rely on AI to decide what to build and why.&lt;/p&gt;

&lt;p&gt;From my perspective, this directly translates into growing technical debt. Code is merged without being fully understood. Security and reliability gaps slip through. Architectural understanding becomes shallower over time — especially when AI output "looks good enough".&lt;/p&gt;

&lt;p&gt;What worries me most, though, is not the tooling itself, but a cultural shift I'm already hearing in conversations.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Well, the AI generated it."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Using AI as an explanation — or worse, as a justification — for gaps in understanding or code quality feels dangerous. I don't want to become the engineer who hides behind tools instead of taking responsibility.&lt;/p&gt;

&lt;p&gt;Yes, even this article is written with the help of AI tools. And that's fine. We should use every capability available to us. But using powerful tools doesn’t remove the need for understanding.&lt;/p&gt;

&lt;p&gt;What I'm arguing for — first and foremost for myself — is &lt;strong&gt;mindful development&lt;/strong&gt;. Approaching code with awareness, not just efficiency.&lt;/p&gt;

&lt;p&gt;To overcome it, now I force myself not to commit anything I don't understand. I make myself review the code at least diagonally and leave TODO notes wherever I notice a gap that I can't fix right away. Over time, this has become harder and harder. On older, complex projects that I wrote myself before the era of AI agents, I don't use AI at all — not even to fix small bugs. The benefit there is minimal: I know the codebase, and it's faster for me to find and adjust the issue myself than to write a prompt and wait for a response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My mantra for 2026:&lt;/strong&gt; strong engineers will be defined not by how much AI they use, but by their ability to know when &lt;em&gt;not to use it&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.reuters.com/business/ai-slows-down-some-experienced-software-developers-study-finds-2025-07-10/" rel="noopener noreferrer"&gt;AI slows down some experienced software developers, study finds - Reuters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2509.08514" rel="noopener noreferrer"&gt;Bias in the Loop - arXiv:2509.08514&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2503.06195" rel="noopener noreferrer"&gt;Human-AI Experience in IDEs - arXiv:2503.06195&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>How to understand Dependency Injection?</title>
      <dc:creator>Jasen</dc:creator>
      <pubDate>Wed, 21 May 2025 21:58:43 +0000</pubDate>
      <link>https://dev.to/jasen_dev/how-to-understand-dependency-injection-4dpg</link>
      <guid>https://dev.to/jasen_dev/how-to-understand-dependency-injection-4dpg</guid>
      <description>&lt;p&gt;&lt;strong&gt;Dependency Injection&lt;/strong&gt; (DI) is a design pattern that manages dependencies by providing (injecting) the required objects (dependencies) to a class from the outside, instead of the class creating them internally.&lt;/p&gt;

&lt;h3&gt;
  
  
  First, let’s briefly dive into the history.
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;In 1994, the GoF in their book "Design Patterns: Elements of Reusable Object-Oriented Software" introduced the principle of "Inversion of Control", although they did not call it Dependency Injection, but they defined the principle that an object should not manage its own dependencies, but instead obtain them from outside.&lt;/li&gt;
&lt;li&gt;In early 2004, Martin Fowler systematized the idea of ​​DI, presenting it as an implementation of IoC.&lt;/li&gt;
&lt;li&gt;In 2004, Spring brought the concept of DI to the Java world. Spring was the first framework to implement DI as a container.&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%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5qd5khr0aprrtvs7gi6.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%2Fz5qd5khr0aprrtvs7gi6.png" alt="history of Dependency Injection" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  So, why was it necessary?
&lt;/h3&gt;

&lt;p&gt;It's just because DI solves problems. Let's find it out on NestJS. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Memory efficiency&lt;/strong&gt;&lt;br&gt;
Nest.js creates each dependency only once (if using a singleton), and it can be reused across the application. 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 {}
class Car {
  constructor(private engine: Engine) {}
}

@Module({
  providers: [Engine, Car],
})
export class AppModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, Engine is created only once, even if Car is used in multiple places.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Ease of testing&lt;/strong&gt;&lt;br&gt;
You can easily mock dependencies for testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mockEngine = { start: jest.fn() };
const car = new Car(mockEngine as Engine);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Scalability&lt;/strong&gt;&lt;br&gt;
Instead of tightly coupled objects, you can easily add or replace dependencies in one place.&lt;/p&gt;

&lt;p&gt;If this concept still feels challenging, let’s simplify it.&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%2F7v91vrhr645g27330xn8.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%2F7v91vrhr645g27330xn8.png" alt="Dependency Injection" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine a chef who needs ingredients. Without DI, the chef grows the vegetables, raises the chickens, and milks the cows. It’s chaos, they’re exhausted, and your dinner is late.&lt;/p&gt;

&lt;p&gt;With DI, the chef gets ingredients from a fancy supermarket. They only need to say, "I need chicken and vegetables," and it’s delivered fresh and ready to cook. &lt;/p&gt;

&lt;p&gt;In this case, ingredients (Dependencies):&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 '@nestjs/common';

@Injectable()
export class Vegetables {
  get() {
    return 'Fresh vegetables';
  }
}

@Injectable()
export class Chicken {
  get() {
    return 'Organic chicken';
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chef (Service):&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 '@nestjs/common';
import { Vegetables } from './vegetables';
import { Chicken } from './chicken';

@Injectable()
export class Chef {
  constructor(private vegetables: Vegetables, private chicken: Chicken) {}

  cookDish(): string {
    const veggies = this.vegetables.get();
    const meat = this.chicken.get();
    return `Cooked dish with ${veggies} and ${meat}`;
  }
}

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

&lt;/div&gt;



&lt;p&gt;Restaurant (Controller):&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, Get } from '@nestjs/common';
import { Chef } from './chef';

@Controller('restaurant')
export class RestaurantController {
  constructor(private chef: Chef) {}

  @Get('order')
  takeOrder(): string {
    return this.chef.cookDish();
  }
}

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

&lt;/div&gt;



&lt;p&gt;Module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Module } from '@nestjs/common';
import { Vegetables } from './vegetables';
import { Chicken } from './chicken';
import { Chef } from './chef';
import { RestaurantController } from './restaurant.controller';

@Module({
  providers: [Vegetables, Chicken, Chef],
  controllers: [RestaurantController],
})
export class RestaurantModule {}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  What happens?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client request:&lt;/strong&gt; User sends a GET request to /restaurant/order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controller:&lt;/strong&gt; RestaurantController receives the request and calls the cookDish() method in Chef.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service:&lt;/strong&gt; Chef requests the ingredients (Vegetables and Chicken) via DI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DI container:&lt;/strong&gt; NestJS creates instances of Vegetables and Chicken and passes them to Chef.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result:&lt;/strong&gt; The string returned is: Cooked dish with Fresh vegetables and Organic chicken.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Dependency Injection is the foundation for creating a non-obvious, scalable, and testable architecture. By using DI, you can spend less time managing dependencies and more time solving business problems.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;AI did the heavy lifting by injecting code at my request, while I discovered the recipe, cooked the visuals, and added some extra spice to the writing.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
