<?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: Amirsaeed Sadeghi Komjani</title>
    <description>The latest articles on DEV Community by Amirsaeed Sadeghi Komjani (@amirsaeed_skomjani).</description>
    <link>https://dev.to/amirsaeed_skomjani</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%2F3437665%2F1642c12b-b1ba-4fe6-b4db-5e02bb4c8d13.jpeg</url>
      <title>DEV Community: Amirsaeed Sadeghi Komjani</title>
      <link>https://dev.to/amirsaeed_skomjani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amirsaeed_skomjani"/>
    <language>en</language>
    <item>
      <title>Why Do So Many Teams Fail at Testing?</title>
      <dc:creator>Amirsaeed Sadeghi Komjani</dc:creator>
      <pubDate>Fri, 12 Dec 2025 10:12:13 +0000</pubDate>
      <link>https://dev.to/amirsaeed_skomjani/why-do-so-many-teams-fail-at-testing-399n</link>
      <guid>https://dev.to/amirsaeed_skomjani/why-do-so-many-teams-fail-at-testing-399n</guid>
      <description>&lt;h2&gt;
  
  
  Why Do So Many Teams Fail at Testing?
&lt;/h2&gt;

&lt;p&gt;Almost every team starts with the same optimism.&lt;/p&gt;

&lt;p&gt;At the beginning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TDD is declared “the right way”&lt;/li&gt;
&lt;li&gt;“Code without tests equals bugs” becomes a mantra&lt;/li&gt;
&lt;li&gt;Frameworks, runners, and pipelines are set up with care&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything looks mature and professional.&lt;/p&gt;

&lt;p&gt;Then a few months pass.&lt;/p&gt;

&lt;p&gt;Reality slowly shows up.&lt;/p&gt;

&lt;p&gt;Tests become painfully slow.&lt;br&gt;&lt;br&gt;
A small change breaks dozens of unrelated tests.&lt;br&gt;&lt;br&gt;
No one has time to refactor the test suite.&lt;br&gt;&lt;br&gt;
Test debt grows quietly.&lt;br&gt;&lt;br&gt;
Deadlines arrive, and management pressure increases: &lt;em&gt;“Ship first, fix later.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At that point, tests stop being a safety net.&lt;br&gt;&lt;br&gt;
They turn into a burden.&lt;/p&gt;

&lt;p&gt;Teams either abandon them entirely or keep them just to satisfy metrics.&lt;br&gt;&lt;br&gt;
Coverage numbers look fine, but confidence is gone.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Uncomfortable Truth About TDD
&lt;/h2&gt;

&lt;p&gt;Here is the controversial part.&lt;/p&gt;

&lt;p&gt;Classic TDD does not always work.&lt;/p&gt;

&lt;p&gt;Many teams adopt it with enthusiasm, but without the conditions it actually requires.&lt;br&gt;&lt;br&gt;
Velocity drops.&lt;br&gt;&lt;br&gt;
Deadlines get tighter.&lt;br&gt;&lt;br&gt;
And eventually, even the important tests stop being written.&lt;/p&gt;

&lt;p&gt;TDD works best when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The domain is well understood&lt;/li&gt;
&lt;li&gt;Uncertainty is low&lt;/li&gt;
&lt;li&gt;Discipline is consistently high&lt;/li&gt;
&lt;li&gt;The team treats tests as first-class code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most real-world projects do not meet these conditions.&lt;/p&gt;

&lt;p&gt;Requirements change.&lt;br&gt;&lt;br&gt;
Architecture evolves.&lt;br&gt;&lt;br&gt;
Time is limited.&lt;/p&gt;

&lt;p&gt;In those environments, strict TDD often creates more friction than value.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Problem Is Not Testing — It’s How We Think About It
&lt;/h2&gt;

&lt;p&gt;Tests are often treated as a ritual, not as software.&lt;/p&gt;

&lt;p&gt;But tests &lt;em&gt;are&lt;/em&gt; software.&lt;/p&gt;

&lt;p&gt;They have architecture.&lt;br&gt;&lt;br&gt;
They need maintenance.&lt;br&gt;&lt;br&gt;
They create coupling.&lt;br&gt;&lt;br&gt;
They accumulate debt.&lt;/p&gt;

&lt;p&gt;High coverage without meaningful assertions creates a false sense of security.&lt;br&gt;&lt;br&gt;
A thousand fragile tests are worse than ten reliable ones.&lt;/p&gt;

&lt;p&gt;If a test does not protect a business rule, a critical workflow, or a risky integration,&lt;br&gt;&lt;br&gt;
its value should be questioned.&lt;/p&gt;




&lt;h2&gt;
  
  
  A More Pragmatic Approach
&lt;/h2&gt;

&lt;p&gt;In practice, many teams succeed with a different mindset:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design for testability first, not test-first by default&lt;/li&gt;
&lt;li&gt;Write tests after the design is clear enough to be stable&lt;/li&gt;
&lt;li&gt;Focus on boundaries: core logic, integrations, critical paths&lt;/li&gt;
&lt;li&gt;Accept that not everything deserves a test&lt;/li&gt;
&lt;li&gt;Measure confidence, not coverage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A mix of test-after and thoughtful design often produces more resilient systems than rigid dogma.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;Testing is not about purity.&lt;br&gt;&lt;br&gt;
It is about trust.&lt;/p&gt;

&lt;p&gt;If your test suite slows you down, breaks constantly, or no longer gives confidence,&lt;br&gt;&lt;br&gt;
the problem is not a lack of discipline.&lt;br&gt;&lt;br&gt;
It is a lack of architectural thinking applied to tests.&lt;/p&gt;

&lt;p&gt;Sometimes, fewer tests — designed better — protect a system far more than perfect coverage ever could.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What has been your experience?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Does TDD genuinely help your team, or only under very specific conditions?&lt;br&gt;&lt;br&gt;
When deadlines hit, are tests part of the Definition of Done — or the first thing sacrificed?&lt;/p&gt;

</description>
      <category>testing</category>
      <category>tdd</category>
      <category>architecture</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>From Framework Lock-in to Building Our Own ORM</title>
      <dc:creator>Amirsaeed Sadeghi Komjani</dc:creator>
      <pubDate>Sat, 08 Nov 2025 10:30:41 +0000</pubDate>
      <link>https://dev.to/amirsaeed_skomjani/from-framework-lock-in-to-building-our-own-orm-3mjb</link>
      <guid>https://dev.to/amirsaeed_skomjani/from-framework-lock-in-to-building-our-own-orm-3mjb</guid>
      <description>&lt;p&gt;Why we decided to build a custom ORM in a real-world project&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;In one of our enterprise projects, the core requirement was clear: &lt;strong&gt;the&lt;br&gt;
Core had to be fully independent from any framework&lt;/strong&gt; --- so that future&lt;br&gt;
migrations (to another framework or even another programming language)&lt;br&gt;
would not require rewriting the business logic.&lt;br&gt;
That requirement forced us to build the Core from scratch, without any&lt;br&gt;
framework dependencies. The biggest challenge? Designing a&lt;br&gt;
&lt;strong&gt;framework-agnostic Data Access Layer&lt;/strong&gt;, which naturally led us to&lt;br&gt;
build our own &lt;strong&gt;QueryBuilder/ORM&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architectural Goals
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Decouple domain logic from infrastructure and framework layers&lt;/li&gt;
&lt;li&gt;  Enable technology migration without rewriting domain code&lt;/li&gt;
&lt;li&gt;  Achieve full unit-testability without a real database&lt;/li&gt;
&lt;li&gt;  Gain fine-grained control over query generation and execution&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why existing ORMs didn't fit
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Framework-Independent Data Layer&lt;/strong&gt; -- Most popular ORMs are deeply
tied to the lifecycle and conventions of their host framework.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Unit Testing without a real DB&lt;/strong&gt; -- We needed to test repositories
and queries with in-memory fakes.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Modular Clauses&lt;/strong&gt; -- Each clause had to be composable and
replaceable without touching the Core.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Precise Execution Control&lt;/strong&gt; -- We required control over query
batching, timing, and transaction handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When "build" makes more sense than "buy"
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Domain requirements impose contracts that off-the-shelf ORMs can't
model cleanly.&lt;/li&gt;
&lt;li&gt;  Long-term architectural stability and Core independence outweigh
early speed.&lt;/li&gt;
&lt;li&gt;  The team has enough technical maturity and resources to maintain a
custom data layer.&lt;/li&gt;
&lt;li&gt;  Migration cost and framework lock-in risk are expected to be high
across the product's lifespan.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;If these conditions aren't met, adopting a mature ORM is wiser.&lt;br&gt;
Reinventing the wheel only makes sense when the wheel you need doesn't&lt;br&gt;
exist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Design Foundations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Fluent Interface&lt;/strong&gt; -- A clean, chainable API for query
construction&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Clause Strategy + Factory&lt;/strong&gt; -- Each clause implemented as a
strategy; a factory orchestrates their composition&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Query Context&lt;/strong&gt; -- Carries state, bindings, and execution
metadata&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Collection Integration&lt;/strong&gt; -- Returns results as a collection object
supporting map, filter, paginate, and metadata&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ports &amp;amp; Adapters&lt;/strong&gt; --

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Ports:&lt;/em&gt; Repository and QueryService as Core contracts&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Adapters:&lt;/em&gt; Database drivers (PDO, MySQL, PostgreSQL) and
in-memory adapters for testing&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Execution Pipeline&lt;/strong&gt; -- Staged SQL building, parameter binding,
secure execution, and mapping to domain models&lt;/li&gt;

&lt;li&gt;  &lt;strong&gt;Error Mapping&lt;/strong&gt; -- Translates low-level DB errors into
application-level exceptions&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Keys to Testability
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;In-Memory Driver&lt;/strong&gt; -- Executes clauses in memory for unit tests&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Contract Tests&lt;/strong&gt; -- Guarantee adapter compliance with Core
interfaces&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Deterministic Hydration&lt;/strong&gt; -- Predictable mapping from raw data to
domain models&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Boundary Tests&lt;/strong&gt; -- Validate that infrastructure concerns never
leak into the domain&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance and Optimization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Lazy vs. Eager Execution&lt;/strong&gt; -- Build queries lazily, execute
explicitly at defined boundaries&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Batching&lt;/strong&gt; -- Combine operations to reduce round-trips&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Index-Aware Hints&lt;/strong&gt; -- Inject DB-specific execution hints without
leaking them into Core logic&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Metrics Hooks&lt;/strong&gt; -- Measure runtime performance, record counts, and
detect N+1 issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Transactions and Concurrency
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Unit of Work (optional)&lt;/strong&gt; -- Track and commit grouped changes
atomically&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Explicit Transactions&lt;/strong&gt; -- Provide clear APIs for
begin/commit/rollback at the adapter layer&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Idempotency and Retries&lt;/strong&gt; -- Built-in hooks for retrying critical
operations safely&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pitfalls and Anti-patterns
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Reinventing Active Record&lt;/strong&gt; -- Mixing domain models with DB
operations defeats independence&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Infrastructure Leakage&lt;/strong&gt; -- No low-level types or exceptions
should cross Core boundaries&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Low-level APIs inside Core&lt;/strong&gt; -- The Core should talk through
domain contracts, not SQL or clauses&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ignoring Migration Paths&lt;/strong&gt; -- Always design for adapter and
database version evolution&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparison Snapshot
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Eloquent:&lt;/strong&gt; Excellent developer experience within Laravel, but
tightly coupled to it&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Doctrine:&lt;/strong&gt; Highly flexible and decoupled, but heavy and complex&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Custom ORM (ours):&lt;/strong&gt; Tailored to exact architectural needs, at the
cost of maintenance responsibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Outcome
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  A framework-agnostic Core, portable across frameworks or even
languages&lt;/li&gt;
&lt;li&gt;  Strong testability without relying on a physical database&lt;/li&gt;
&lt;li&gt;  Full control over query generation and execution paths&lt;/li&gt;
&lt;li&gt;  Greater architectural transparency and deeper engineering insight
within the team&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When not to take this path
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  The project is short-lived or framework lock-in is an acceptable
risk&lt;/li&gt;
&lt;li&gt;  The team is small and can't maintain a custom data layer&lt;/li&gt;
&lt;li&gt;  Existing ORMs already meet all functional and architectural
requirements&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Building a custom ORM is both a technical and economic decision --- not&lt;br&gt;
a vanity project.&lt;br&gt;
If Core independence, offline testability, and precise control over data&lt;br&gt;
access are your first-order priorities &lt;em&gt;and&lt;/em&gt; your team can sustain the&lt;br&gt;
maintenance cost, then this path is worth it.&lt;br&gt;
Otherwise, rely on proven ORMs and keep your focus on the domain.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>php</category>
      <category>designpatterns</category>
      <category>orm</category>
    </item>
    <item>
      <title>Framework Lock-In: Are you building a product—or just a framework extension?</title>
      <dc:creator>Amirsaeed Sadeghi Komjani</dc:creator>
      <pubDate>Tue, 04 Nov 2025 21:36:33 +0000</pubDate>
      <link>https://dev.to/amirsaeed_skomjani/framework-lock-in-are-you-building-a-product-or-just-a-framework-extension-1c4f</link>
      <guid>https://dev.to/amirsaeed_skomjani/framework-lock-in-are-you-building-a-product-or-just-a-framework-extension-1c4f</guid>
      <description>&lt;p&gt;Ever looked at code that feels more like a &lt;strong&gt;framework demo&lt;/strong&gt; than a real product?&lt;/p&gt;

&lt;p&gt;Many teams proudly say: “We’ve built an independent product.”&lt;br&gt;&lt;br&gt;
But when you dig deeper, you realize everything — from routing to authentication — is tightly bound to the framework.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why is this a problem?
&lt;/h2&gt;

&lt;p&gt;In that scenario, your product has &lt;strong&gt;no independent identity&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
If the framework gets deprecated tomorrow or the team shifts direction, you’ll end up &lt;strong&gt;rewriting everything from scratch&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;That’s the danger of &lt;strong&gt;Framework Lock-In&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The trade-off
&lt;/h2&gt;

&lt;p&gt;On the flip side, some teams intentionally give up freedom for &lt;strong&gt;development speed&lt;/strong&gt; and &lt;strong&gt;community support&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Fair enough… but is that truly a &lt;strong&gt;strategy&lt;/strong&gt;, or just &lt;strong&gt;convenience disguised as one&lt;/strong&gt;?&lt;/p&gt;




&lt;h2&gt;
  
  
  What often gets forgotten
&lt;/h2&gt;

&lt;p&gt;A real product should have its &lt;strong&gt;own architectural identity&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
A framework should remain a &lt;strong&gt;tool&lt;/strong&gt;, not the thing that defines your product.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The uncomfortable truth: many so-called “products” are really just framework extensions.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Question
&lt;/h3&gt;

&lt;p&gt;Would your product survive without the framework,&lt;br&gt;&lt;br&gt;
or is it just a plug-in living on top of it?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What do you think?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Have you ever refactored a system that was too tied to its framework?&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>softwaredesign</category>
      <category>systemthinking</category>
      <category>developers</category>
    </item>
    <item>
      <title>Why is the line between juniors and seniors so often misunderstood?</title>
      <dc:creator>Amirsaeed Sadeghi Komjani</dc:creator>
      <pubDate>Sat, 01 Nov 2025 14:01:58 +0000</pubDate>
      <link>https://dev.to/amirsaeed_skomjani/why-is-the-line-between-juniors-and-seniors-so-often-misunderstood-5f62</link>
      <guid>https://dev.to/amirsaeed_skomjani/why-is-the-line-between-juniors-and-seniors-so-often-misunderstood-5f62</guid>
      <description>&lt;p&gt;In simpler CRUD-based projects, complex architecture quickly turns into &lt;strong&gt;technical debt&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Here, developers with a &lt;strong&gt;pragmatic, delivery-focused&lt;/strong&gt; approach (often juniors) tend to be more effective — because business reality values &lt;strong&gt;simplicity and speed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But once a project grows beyond CRUD into &lt;strong&gt;service-based or domain-heavy complexity&lt;/strong&gt;, that’s where &lt;strong&gt;seniors show their real value&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The ability to define &lt;strong&gt;clear context boundaries&lt;/strong&gt;, design &lt;strong&gt;proper abstractions&lt;/strong&gt;, and think in terms of &lt;strong&gt;scalability and maintainability&lt;/strong&gt; isn’t something you gain just by writing code for years.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Real Difference
&lt;/h3&gt;

&lt;p&gt;The difference between a &lt;em&gt;junior&lt;/em&gt; and a &lt;em&gt;senior&lt;/em&gt; is &lt;strong&gt;not about years of experience&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
It’s about &lt;strong&gt;maturity&lt;/strong&gt; — in architecture, long-term maintainability, system evolution, and even teamwork and collaboration.&lt;/p&gt;

&lt;p&gt;I’ve seen people with 3–4 years of experience act more mature in architecture and team interaction than someone who’s been coding for a decade.&lt;/p&gt;

&lt;p&gt;That’s why, instead of counting years on a résumé, we should assess &lt;strong&gt;engineering maturity&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Question for you
&lt;/h3&gt;

&lt;p&gt;Have you seen juniors shine in CRUD projects, or seniors saving the day in complex systems?&lt;/p&gt;

&lt;p&gt;Let’s discuss&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>career</category>
      <category>engineering</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Why Most Developers Misunderstand Clean Architecture</title>
      <dc:creator>Amirsaeed Sadeghi Komjani</dc:creator>
      <pubDate>Mon, 20 Oct 2025 10:37:52 +0000</pubDate>
      <link>https://dev.to/amirsaeed_skomjani/why-most-developers-misunderstand-clean-architecture-e5p</link>
      <guid>https://dev.to/amirsaeed_skomjani/why-most-developers-misunderstand-clean-architecture-e5p</guid>
      <description>&lt;p&gt;For many, &lt;strong&gt;Clean Architecture&lt;/strong&gt; is just a checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A controller layer&lt;/li&gt;
&lt;li&gt;  A service layer&lt;/li&gt;
&lt;li&gt;  A repository for the database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And they think they're done.&lt;br&gt;
But that's only the surface.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Mistakes I've Observed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Misunderstanding dependency inversion&lt;/strong&gt;&lt;br&gt;
Core classes still depend on the database or framework, while the rule&lt;br&gt;
says everything should depend on business logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring context&lt;/strong&gt;&lt;br&gt;
Developers add ten layers for a simple CRUD app --- resulting in&lt;br&gt;
over-engineering and unnecessary ceremony.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forgetting business goals&lt;/strong&gt;&lt;br&gt;
Teams build architecture for engineering ego, not for solving real&lt;br&gt;
problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Real Clean Architecture Looks Like
&lt;/h2&gt;

&lt;p&gt;The core runs even without a database or framework.&lt;br&gt;
Tests execute fast, directly on the domain logic.&lt;br&gt;
Switching frameworks or databases doesn't break the system.&lt;/p&gt;




&lt;p&gt;From my experience, the cleanest projects had the fewest layers, but&lt;br&gt;
applied the &lt;strong&gt;Dependency Rule&lt;/strong&gt; and &lt;strong&gt;DIP&lt;/strong&gt; correctly.&lt;/p&gt;




&lt;h3&gt;
  
  
  Question
&lt;/h3&gt;

&lt;p&gt;Have you seen teams add complexity in the name of Clean Architecture?&lt;br&gt;
Share your experience below.&lt;/p&gt;

</description>
      <category>cleanarchitecture</category>
      <category>architecture</category>
      <category>systemdesign</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Did you know your database schema might be leaking through error messages and stack traces?</title>
      <dc:creator>Amirsaeed Sadeghi Komjani</dc:creator>
      <pubDate>Sat, 13 Sep 2025 08:08:08 +0000</pubDate>
      <link>https://dev.to/amirsaeed_skomjani/did-you-know-your-database-schema-might-be-leaking-through-error-messages-and-stack-traces-2pe0</link>
      <guid>https://dev.to/amirsaeed_skomjani/did-you-know-your-database-schema-might-be-leaking-through-error-messages-and-stack-traces-2pe0</guid>
      <description>&lt;p&gt;AI is now smart enough to reconstruct your database from what looks like harmless errors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQL errors (constraint violations, duplicate entries)
&lt;/li&gt;
&lt;li&gt;ORM/Model exceptions (table names, class names, line numbers)
&lt;/li&gt;
&lt;li&gt;NoSQL hints (like MongoDB’s “document not found” or “index violation”)
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why is this dangerous?
&lt;/h2&gt;

&lt;p&gt;Attackers can gradually infer your schema:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQL → table names, keys, relationships
&lt;/li&gt;
&lt;li&gt;NoSQL → collection names, document structures, indexes
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Insight
&lt;/h2&gt;

&lt;p&gt;Not all databases leak the same way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relational DBs often reveal too much detail.
&lt;/li&gt;
&lt;li&gt;NoSQL may leak less by default, but verbose logging or misconfiguration changes the game.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What can you do?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Never expose raw errors in production.
&lt;/li&gt;
&lt;li&gt;Use generic error handling.
&lt;/li&gt;
&lt;li&gt;Regularly audit your API responses.
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;What about you?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have you ever seen a “simple” DB error reveal way too much?
&lt;/li&gt;
&lt;li&gt;If you had to choose: SQL with verbose errors or NoSQL with misconfig risks — which one feels safer to you, and why?
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cybersecurity</category>
      <category>database</category>
      <category>architecture</category>
      <category>ai</category>
    </item>
    <item>
      <title>Your API Security Assumptions Are Outdated: AI Isn’t Just a User — It’s an Attacker</title>
      <dc:creator>Amirsaeed Sadeghi Komjani</dc:creator>
      <pubDate>Tue, 02 Sep 2025 07:31:50 +0000</pubDate>
      <link>https://dev.to/amirsaeed_skomjani/your-api-security-assumptions-are-outdated-ai-isnt-just-a-user-its-an-attacker-5g3k</link>
      <guid>https://dev.to/amirsaeed_skomjani/your-api-security-assumptions-are-outdated-ai-isnt-just-a-user-its-an-attacker-5g3k</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI isn’t just a user — it can be an attacker.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most teams still think securing an API means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using &lt;strong&gt;JWT&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enforcing &lt;strong&gt;HTTPS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Applying &lt;strong&gt;Rate Limiting&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That used to be enough.&lt;/p&gt;




&lt;h2&gt;
  
  
  But today’s reality is different:
&lt;/h2&gt;

&lt;p&gt;AI is &lt;strong&gt;reading and analyzing your responses&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Unlike human users, AI can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Process &lt;strong&gt;millions of API responses&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Extract &lt;strong&gt;patterns from error messages&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reverse-engineer&lt;/strong&gt; your system faster than any human hacker&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Real-World Vulnerabilities
&lt;/h2&gt;

&lt;p&gt;Here’s how your API might already be leaking knowledge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Raw stack traces&lt;/strong&gt;  → Reveal your &lt;strong&gt;framework&lt;/strong&gt; and &lt;strong&gt;version&lt;/strong&gt; → AI maps it to known CVEs in seconds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exposed SQL queries&lt;/strong&gt;  → Reveal your &lt;strong&gt;schema&lt;/strong&gt; and &lt;strong&gt;business logic&lt;/strong&gt; → Free blueprint for attackers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Detailed validation errors&lt;/strong&gt;  → Help AI learn your &lt;strong&gt;internal rules&lt;/strong&gt; and &lt;strong&gt;edge cases&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📉 The Result?
&lt;/h2&gt;

&lt;p&gt;You’re handing over your system’s architecture to an intelligent attacker — for free.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛡 Practical Steps to Protect Your API
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Obfuscation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Return &lt;strong&gt;generic error codes/messages&lt;/strong&gt; — not full details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Response Layer&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sanitize and filter every outgoing response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AI-aware Security&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Assume your API is consumed by a &lt;strong&gt;learning model&lt;/strong&gt;, not just a user.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 My Take
&lt;/h2&gt;

&lt;p&gt;Once we shifted our mindset from &lt;em&gt;"protecting data"&lt;/em&gt; to &lt;em&gt;"protecting knowledge"&lt;/em&gt;,&lt;br&gt;&lt;br&gt;
many risks &lt;strong&gt;simply disappeared&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your Turn
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do you think AI is becoming:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a helper for security?
&lt;/li&gt;
&lt;li&gt;or the next big threat?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s discuss in the comments 👇&lt;/p&gt;




&lt;p&gt;👉 Follow me for more insights on &lt;strong&gt;Software Architecture + Security in the AI Era&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>api</category>
      <category>ai</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Why Design Patterns Often Fail in Real Projects</title>
      <dc:creator>Amirsaeed Sadeghi Komjani</dc:creator>
      <pubDate>Mon, 25 Aug 2025 10:45:55 +0000</pubDate>
      <link>https://dev.to/amirsaeed_skomjani/why-design-patterns-often-fail-in-real-projects-nh5</link>
      <guid>https://dev.to/amirsaeed_skomjani/why-design-patterns-often-fail-in-real-projects-nh5</guid>
      <description>&lt;p&gt;📉 Honestly, I’ve seen it many times: instead of helping, Design Patterns end up making projects worse.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Common reasons why they fail
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Copied directly from books/tutorials without understanding the &lt;em&gt;why&lt;/em&gt; and &lt;em&gt;when&lt;/em&gt;.
&lt;/li&gt;
&lt;li&gt;Forcing every problem into a Pattern → pure over-engineering.
&lt;/li&gt;
&lt;li&gt;Team members interpret patterns differently → inconsistent, bloated code.
&lt;/li&gt;
&lt;li&gt;Architecture evolves, but rigid implementations stay stuck.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💡 How to make them work (from a CTO’s perspective)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A pattern is a tool, not the goal. Use it only when it solves a repeatable problem.
&lt;/li&gt;
&lt;li&gt;Align the chosen pattern with the &lt;strong&gt;architecture vision &amp;amp; product strategy&lt;/strong&gt;, not just personal taste.
&lt;/li&gt;
&lt;li&gt;Make sure the &lt;strong&gt;whole team understands why&lt;/strong&gt; this pattern was picked — otherwise, failure is guaranteed.
&lt;/li&gt;
&lt;li&gt;Keep the architecture flexible and refactor-friendly.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 My take? The most successful patterns I’ve seen were the ones that became a &lt;strong&gt;shared language&lt;/strong&gt; for the team — not a handcuff.  &lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Your turn:&lt;/strong&gt; Have you seen a Design Pattern cause more pain than value? &lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>cleanarchitecture</category>
      <category>systemdesign</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Why Most Refactors Fail — And How to Fix Them</title>
      <dc:creator>Amirsaeed Sadeghi Komjani</dc:creator>
      <pubDate>Sun, 17 Aug 2025 08:05:37 +0000</pubDate>
      <link>https://dev.to/amirsaeed_skomjani/why-most-refactors-fail-and-how-to-fix-them-3adj</link>
      <guid>https://dev.to/amirsaeed_skomjani/why-most-refactors-fail-and-how-to-fix-them-3adj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“We should refactor the whole thing…”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've heard this line more times than I can count — and honestly, &lt;strong&gt;most of those refactors failed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not because refactoring is a bad idea. But because &lt;strong&gt;they were done wrong&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  📉 Why They Fail
&lt;/h2&gt;

&lt;p&gt;Here are the top reasons I’ve seen (and experienced):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No clear target architecture&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
“We just want it cleaner” is not a plan.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lack of test coverage&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you don’t have a safety net, every change is a risk.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Big-bang rewrites&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Trying to change everything at once = chaos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Team misalignment&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If everyone has a different definition of “clean,” good luck.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ How to Do It Right
&lt;/h2&gt;

&lt;p&gt;If you want your refactor to succeed, start with these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Define the end goal&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
What will the architecture look like after refactoring?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Refactor incrementally&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Small, focused changes are easier to test, review, and roll back.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write tests first&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Ensure you’re not breaking things while cleaning things up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Align the team on standards&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Agree on patterns, formatting, naming — everything.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 My Take
&lt;/h2&gt;

&lt;p&gt;The best refactors I’ve seen had these 3 things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A clear &lt;strong&gt;vision&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A solid &lt;strong&gt;test suite&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A well-communicated &lt;strong&gt;plan&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Refactoring without those? You’re just rewriting code and hoping for the best.&lt;/p&gt;




&lt;h2&gt;
  
  
  🙋 Your Turn
&lt;/h2&gt;

&lt;p&gt;Have you ever done a big refactor?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Was it painful or satisfying?
&lt;/li&gt;
&lt;li&gt;Did you have the plan and tests?
&lt;/li&gt;
&lt;li&gt;Or was it more like “rip it out and hope”?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s share some refactor war stories in the comments. 👇&lt;/p&gt;




</description>
      <category>refactoring</category>
      <category>cleancode</category>
      <category>softwaredesign</category>
      <category>programming</category>
    </item>
    <item>
      <title>Repository Layer: Decoration or Real Architecture?</title>
      <dc:creator>Amirsaeed Sadeghi Komjani</dc:creator>
      <pubDate>Fri, 15 Aug 2025 17:17:02 +0000</pubDate>
      <link>https://dev.to/amirsaeed_skomjani/repository-layer-decoration-or-real-architecture-2hmf</link>
      <guid>https://dev.to/amirsaeed_skomjani/repository-layer-decoration-or-real-architecture-2hmf</guid>
      <description>&lt;p&gt;Many developers add a &lt;strong&gt;Repository Layer&lt;/strong&gt; to make their projects look cleaner and more professional.  &lt;/p&gt;

&lt;p&gt;But in reality, if all repositories are silently coupled to a single driver like &lt;strong&gt;Laravel Eloquent&lt;/strong&gt;, this layer becomes decorative and useless.  &lt;/p&gt;

&lt;p&gt;In this post, I’ll explain why that happens, the architectural risks behind it, and how to design a Repository Layer that &lt;em&gt;actually&lt;/em&gt; delivers on its promise.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;The issue surfaces when you need to &lt;strong&gt;switch databases&lt;/strong&gt; or introduce a new driver.  &lt;/p&gt;

&lt;p&gt;Instead of swapping drivers smoothly, you’re forced into a &lt;strong&gt;major refactor&lt;/strong&gt; because your Repository Layer is tightly bound to one specific ORM or database driver.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Purpose of the Repository Layer
&lt;/h2&gt;

&lt;p&gt;A well-designed Repository Layer should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow replacing or adding multiple drivers &lt;strong&gt;without touching your services or controllers&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Keep your application &lt;strong&gt;multi-driver&lt;/strong&gt; and even &lt;strong&gt;multi-tenant&lt;/strong&gt; ready.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When implemented correctly, it becomes the &lt;strong&gt;abstraction boundary&lt;/strong&gt; between your domain logic and your data sources — not just an extra file to look “professional.”&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Fix It — Adapter Pattern to the Rescue
&lt;/h2&gt;

&lt;p&gt;To truly decouple your dependencies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Define Repository Interfaces&lt;/strong&gt; in your domain layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create Adapter Classes&lt;/strong&gt; that translate interface methods into driver-specific implementations.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Dependency Injection&lt;/strong&gt; so your services/controllers depend on the interface, not the concrete driver.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example in Laravel/PHP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UserRepositoryInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;findByEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EloquentUserRepository&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;UserRepositoryInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;findByEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;first&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, swapping to another driver (e.g., MongoDB) means creating a new adapter without touching the rest of your codebase.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Question for You
&lt;/h2&gt;

&lt;p&gt;How do you implement your Repository Layer?&lt;br&gt;
Do you leverage the Adapter Pattern to truly decouple your dependencies, or is your layer just decorative?&lt;/p&gt;




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

&lt;p&gt;A Repository Layer is not just for aesthetics — it’s a key architectural tool for flexibility and scalability.&lt;br&gt;
When paired with the Adapter Pattern, it gives you the freedom to change persistence layers with minimal effort.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;💬 Have you ever had to refactor a whole project just to change the database driver? Share your experience in the comments!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>architecture</category>
      <category>designpatterns</category>
      <category>cleanarchitecture</category>
      <category>adapterpattern</category>
    </item>
  </channel>
</rss>
