<?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: Ayman Atif</title>
    <description>The latest articles on DEV Community by Ayman Atif (@a95yman).</description>
    <link>https://dev.to/a95yman</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%2F3887349%2F44f7eb73-8509-408e-94a4-f2d98502a27d.jpg</url>
      <title>DEV Community: Ayman Atif</title>
      <link>https://dev.to/a95yman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/a95yman"/>
    <language>en</language>
    <item>
      <title>AI Could Build My Client’s App in a Week. Making It Reliable Took Me 3 Months.</title>
      <dc:creator>Ayman Atif</dc:creator>
      <pubDate>Mon, 21 Sep 2026 17:39:31 +0000</pubDate>
      <link>https://dev.to/a95yman/ai-could-build-my-clients-app-in-a-week-making-it-reliable-took-me-3-months-3clk</link>
      <guid>https://dev.to/a95yman/ai-could-build-my-clients-app-in-a-week-making-it-reliable-took-me-3-months-3clk</guid>
      <description>&lt;h1&gt;
  
  
  AI Could Build My Client’s App in a Week. Making It Reliable Took Me 3 Months.
&lt;/h1&gt;

&lt;p&gt;AI can generate software frighteningly fast.&lt;/p&gt;

&lt;p&gt;That is both its greatest advantage and one of the easiest traps to fall into.&lt;/p&gt;

&lt;p&gt;Earlier this year, I started working on a fairly complex client project. What began as an Excel spreadsheet gradually became a production platform with around 20 interconnected modules.&lt;/p&gt;

&lt;p&gt;I used AI heavily throughout development.&lt;/p&gt;

&lt;p&gt;Claude Sonnet and Opus helped with design and implementation. Codex Terra and Sol became my second pair of eyes for architecture, planning, and code review.&lt;/p&gt;

&lt;p&gt;The amount of code we could produce was incredible.&lt;/p&gt;

&lt;p&gt;At some points, it genuinely felt like the entire application could have been built in a week.&lt;/p&gt;

&lt;p&gt;Three months later, I understood why that would have been a terrible idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Version Is the Easy Part
&lt;/h2&gt;

&lt;p&gt;There is something addictive about building software with AI.&lt;/p&gt;

&lt;p&gt;You describe a feature.&lt;/p&gt;

&lt;p&gt;AI understands it.&lt;/p&gt;

&lt;p&gt;A few minutes later, you have hundreds of lines of working code.&lt;/p&gt;

&lt;p&gt;You test it.&lt;/p&gt;

&lt;p&gt;It works.&lt;/p&gt;

&lt;p&gt;Then you move on to the next feature.&lt;/p&gt;

&lt;p&gt;And the next.&lt;/p&gt;

&lt;p&gt;And the next.&lt;/p&gt;

&lt;p&gt;For a small project, that workflow can be incredibly productive.&lt;/p&gt;

&lt;p&gt;But complexity compounds.&lt;/p&gt;

&lt;p&gt;By the time my project had grown into a large interconnected system, implementing a feature was no longer the difficult part.&lt;/p&gt;

&lt;p&gt;The difficult question became:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What did this feature accidentally break?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Feature Worked. Something Else Broke.
&lt;/h2&gt;

&lt;p&gt;This became one of the most frustrating patterns during development.&lt;/p&gt;

&lt;p&gt;I would implement a new feature and test it.&lt;/p&gt;

&lt;p&gt;Perfect.&lt;/p&gt;

&lt;p&gt;Then I would discover that something seemingly unrelated had stopped working.&lt;/p&gt;

&lt;p&gt;Sometimes a change interfered with the application's Content Security Policy.&lt;/p&gt;

&lt;p&gt;Sometimes functionality elsewhere in the platform regressed.&lt;/p&gt;

&lt;p&gt;Sometimes the generated implementation duplicated logic that already existed somewhere else.&lt;/p&gt;

&lt;p&gt;AI was extremely good at solving the problem directly in front of it.&lt;/p&gt;

&lt;p&gt;But production software isn't a collection of isolated problems.&lt;/p&gt;

&lt;p&gt;Everything lives in a system.&lt;/p&gt;

&lt;p&gt;And once that system becomes sufficiently complex, local correctness isn't enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then I Found a 20,000-Line File
&lt;/h2&gt;

&lt;p&gt;This was one of those moments where you look at your codebase and realize you have allowed something to go much too far.&lt;/p&gt;

&lt;p&gt;One file had grown to roughly &lt;strong&gt;20,000 lines of code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;AI didn't particularly care.&lt;/p&gt;

&lt;p&gt;It could keep reading the file, finding the relevant section, inserting another method, and continuing with its business.&lt;/p&gt;

&lt;p&gt;Technically, development could continue.&lt;/p&gt;

&lt;p&gt;Architecturally, it was becoming ridiculous.&lt;/p&gt;

&lt;p&gt;So I stopped generating features and dealt with the structure myself.&lt;/p&gt;

&lt;p&gt;I created the folders and files I wanted.&lt;/p&gt;

&lt;p&gt;I defined clearer responsibilities.&lt;/p&gt;

&lt;p&gt;Then I had AI help split the existing implementation across that structure.&lt;/p&gt;

&lt;p&gt;That experience changed how I use AI.&lt;/p&gt;

&lt;p&gt;I stopped asking only:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Does this work?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started asking:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Where does this belong?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Those are very different questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scariest Problem Wasn't Messy Code
&lt;/h2&gt;

&lt;p&gt;Messy architecture is annoying.&lt;/p&gt;

&lt;p&gt;Data loss is different.&lt;/p&gt;

&lt;p&gt;At one point, I encountered a race condition that could result in data being lost.&lt;/p&gt;

&lt;p&gt;AI investigated it.&lt;/p&gt;

&lt;p&gt;A fix was implemented.&lt;/p&gt;

&lt;p&gt;The reasoning sounded convincing.&lt;/p&gt;

&lt;p&gt;The problem appeared solved.&lt;/p&gt;

&lt;p&gt;Except it wasn't.&lt;/p&gt;

&lt;p&gt;Eventually, I had to follow the execution path through myself, identify what was actually happening, and correct the underlying problem.&lt;/p&gt;

&lt;p&gt;That incident hammered home something important for me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Confidence is not evidence.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI can articulate an explanation beautifully while still being wrong.&lt;/p&gt;

&lt;p&gt;When you're building a toy project, that might cost you an afternoon.&lt;/p&gt;

&lt;p&gt;When you're building software for a client, that changes the equation.&lt;/p&gt;

&lt;p&gt;Someone else's business can depend on the code you're shipping.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Also Doesn't Care If Your Product Slowly Loses Its Identity
&lt;/h2&gt;

&lt;p&gt;Another problem was subtler.&lt;/p&gt;

&lt;p&gt;Design inconsistency.&lt;/p&gt;

&lt;p&gt;When you're generating pages individually, each page can look perfectly acceptable.&lt;/p&gt;

&lt;p&gt;But put 15 or 20 of them together and suddenly:&lt;/p&gt;

&lt;p&gt;Buttons don't quite match.&lt;/p&gt;

&lt;p&gt;Spacing changes.&lt;/p&gt;

&lt;p&gt;Forms behave slightly differently.&lt;/p&gt;

&lt;p&gt;Modals follow different patterns.&lt;/p&gt;

&lt;p&gt;One section feels like it belongs to another application.&lt;/p&gt;

&lt;p&gt;No individual page looks terrible.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;product&lt;/strong&gt; looks inconsistent.&lt;/p&gt;

&lt;p&gt;So my role increasingly became less about typing code and more about monitoring the whole system.&lt;/p&gt;

&lt;p&gt;I had to catch discrepancies, regressions, security vulnerabilities, architectural problems, and UX inconsistencies.&lt;/p&gt;

&lt;p&gt;AI was doing more implementation.&lt;/p&gt;

&lt;p&gt;I was doing more supervision.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Eventually Split the Responsibilities Between AI Models
&lt;/h2&gt;

&lt;p&gt;Instead of asking one AI to do everything, I developed a workflow that worked much better for me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codex became the planner and reviewer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I used it to inspect architecture, challenge implementations, identify risks, and review changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude became the designer and implementer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sonnet and Opus handled much of the actual feature development and UI work.&lt;/p&gt;

&lt;p&gt;Then came testing.&lt;/p&gt;

&lt;p&gt;Automated tests.&lt;/p&gt;

&lt;p&gt;Manual tests.&lt;/p&gt;

&lt;p&gt;Browser testing.&lt;/p&gt;

&lt;p&gt;And, importantly, me actually using the application rather than assuming passing tests meant everything was fine.&lt;/p&gt;

&lt;p&gt;This slowed development down.&lt;/p&gt;

&lt;p&gt;That was a good thing.&lt;/p&gt;

&lt;p&gt;The goal was no longer to produce the most code possible.&lt;/p&gt;

&lt;p&gt;The goal was to confidently ship software.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Didn't Replace the Developer. It Changed the Developer's Job.
&lt;/h2&gt;

&lt;p&gt;This is probably my biggest takeaway from the entire project.&lt;/p&gt;

&lt;p&gt;I wrote dramatically less code manually than I would have a few years ago.&lt;/p&gt;

&lt;p&gt;But I didn't have dramatically less responsibility.&lt;/p&gt;

&lt;p&gt;In some ways, I had more.&lt;/p&gt;

&lt;p&gt;I needed to understand enough about the system to notice when AI was heading in the wrong direction.&lt;/p&gt;

&lt;p&gt;I needed to be assertive about architecture instead of letting generated code accumulate wherever convenient.&lt;/p&gt;

&lt;p&gt;I needed to recognize security regressions.&lt;/p&gt;

&lt;p&gt;I needed to test assumptions.&lt;/p&gt;

&lt;p&gt;I needed to reconsider my position when an implementation that looked elegant turned out to be fragile.&lt;/p&gt;

&lt;p&gt;And when something broke in production, I couldn't tell the client:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"The AI said it was fixed."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The responsibility was still mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Could AI Have Built It in a Week?
&lt;/h2&gt;

&lt;p&gt;Possibly.&lt;/p&gt;

&lt;p&gt;At least something that looked like the finished application.&lt;/p&gt;

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

&lt;p&gt;Generating 20 modules isn't the same thing as building a dependable 20-module system.&lt;/p&gt;

&lt;p&gt;You can move incredibly fast with AI.&lt;/p&gt;

&lt;p&gt;But if every new feature creates two regressions, you're borrowing time from your future self.&lt;/p&gt;

&lt;p&gt;Eventually, you pay it back through debugging, refactoring, client complaints, longer working hours, and trying to identify which seemingly harmless change caused the latest problem.&lt;/p&gt;

&lt;p&gt;Speed is valuable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Controlled speed is much more valuable.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Months Later
&lt;/h2&gt;

&lt;p&gt;The project eventually reached the point where I was genuinely comfortable with it.&lt;/p&gt;

&lt;p&gt;It became a large production system with interconnected workflows, financial data, document generation, external sharing, contact management, reporting, and a substantial amount of business logic.&lt;/p&gt;

&lt;p&gt;More importantly, the development process itself became disciplined.&lt;/p&gt;

&lt;p&gt;AI remained heavily involved.&lt;/p&gt;

&lt;p&gt;I didn't respond to the problems by abandoning AI.&lt;/p&gt;

&lt;p&gt;I learned to use it differently.&lt;/p&gt;

&lt;p&gt;That's the part of AI-assisted development I think gets overlooked.&lt;/p&gt;

&lt;p&gt;The interesting question isn't:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Can AI build an app?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of course it can.&lt;/p&gt;

&lt;p&gt;The more useful question is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Can you manage what AI builds when the application becomes complicated?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's where software engineering starts to matter again.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Documented the Full Experience
&lt;/h2&gt;

&lt;p&gt;I ended up turning the experience into a short case study covering the architecture problems, regressions, security issues, race condition, data loss, testing process, and the workflow I eventually developed between Claude, Codex, and myself.&lt;/p&gt;

&lt;p&gt;It's called &lt;strong&gt;I Built a 20-Module Business Valuation System With AI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The title reveals more about the project than I wanted to discuss publicly here, while the case study goes much deeper into what actually happened during those three months.&lt;/p&gt;

&lt;p&gt;If you're using AI to build your own product or client software, you can read the full case study here:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://yaman95.gumroad.com/l/built-business-valuation-system-with-ai" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpublic-files.gumroad.com%2Fg53m6n3ei6v8pef8pdhxasw84ibj" height="451" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://yaman95.gumroad.com/l/built-business-valuation-system-with-ai" rel="noopener noreferrer" class="c-link"&gt;
            I Built a 20-Module Business Valuation System With AI
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            I used AI to help turn an Excel spreadsheet into a complete 20-module business valuation system.It looked like AI could make the project ridiculously fast.Then the real problems started.New features caused regressions. Security policies broke. Unrelated parts of the platform stopped working. Designs became inconsistent. One file grew to more than 20,000 lines. A race condition eventually caused data loss, even after AI confidently suggested the problem had been fixed.This case study explains what happened and how I changed my workflow to get the project under control.I cover how I used Claude for design and implementation, Codex for architecture and review, and automated tests, manual testing, and browser testing to catch problems before they reached the client.The finished system handles business sellability, financial analysis, valuation workflows, CIM and BLI generation, and controlled sharing with sellers, buyers, bankers, and other relevant contacts.It took around three months to reach a result I was comfortable shipping.This is not a prompt collection or a guide promising that AI will build your SaaS overnight.It is my experience building a complex client system with AI, including the mistakes, regressions, architectural problems, security issues, and lessons that came with it.Written by Ayman Atif, software developer.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpublic-files.gumroad.com%2Fc3turpghsvintnl2nead2w8415ly" width="400" height="400"&gt;
          yaman95.gumroad.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I'm &lt;strong&gt;Ayman Atif&lt;/strong&gt;, a software developer who has spent years building business software. AI has changed how I work considerably.&lt;/p&gt;

&lt;p&gt;It hasn't taken responsibility out of the equation.&lt;/p&gt;

&lt;p&gt;If anything, it has made knowing &lt;strong&gt;when to intervene&lt;/strong&gt; more important than ever.&lt;/p&gt;

</description>
      <category>aiops</category>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>I've Been Programming for 14 Years. I Just Earned My First Microsoft Credential.</title>
      <dc:creator>Ayman Atif</dc:creator>
      <pubDate>Sat, 19 Sep 2026 15:10:42 +0000</pubDate>
      <link>https://dev.to/a95yman/ive-been-programming-for-14-years-i-just-earned-my-first-microsoft-credential-4gg4</link>
      <guid>https://dev.to/a95yman/ive-been-programming-for-14-years-i-just-earned-my-first-microsoft-credential-4gg4</guid>
      <description>&lt;p&gt;I’ve been programming for around 14 years.&lt;/p&gt;

&lt;p&gt;During all that time, I never really cared about certificates.&lt;/p&gt;

&lt;p&gt;I learned by building things.&lt;/p&gt;

&lt;p&gt;Web applications. Business software. APIs. Automation tools. Desktop applications. Projects that broke, projects that worked, and projects that forced me to learn things I thought I already understood.&lt;/p&gt;

&lt;p&gt;For years, that was enough for me.&lt;/p&gt;

&lt;p&gt;Then I decided to try something different.&lt;/p&gt;

&lt;p&gt;I gave myself three days to prepare for the &lt;strong&gt;Microsoft Applied Skills: Get started with classes, properties, and methods in C#&lt;/strong&gt; assessment.&lt;/p&gt;

&lt;p&gt;I passed.&lt;/p&gt;

&lt;p&gt;And it made me reconsider my position on technical credentials.&lt;/p&gt;

&lt;p&gt;I also turned the notes and exercises I personally used during those three days into a compact preparation resource for developers who want to follow a similar approach:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://yaman95.gumroad.com/l/microsoft-applied-skills-classes-methods-properties" rel="noopener noreferrer"&gt;https://yaman95.gumroad.com/l/microsoft-applied-skills-classes-methods-properties&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the interesting part isn’t the product.&lt;/p&gt;

&lt;p&gt;It’s what happened during those three days.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I ignored programming certificates for so long
&lt;/h2&gt;

&lt;p&gt;My reasoning used to be pretty simple:&lt;/p&gt;

&lt;p&gt;If I can build software, why do I need a certificate telling people that I can build software?&lt;/p&gt;

&lt;p&gt;And there is still some truth to that.&lt;/p&gt;

&lt;p&gt;A credential cannot replace experience.&lt;/p&gt;

&lt;p&gt;It cannot replace the hours you spend debugging a problem that makes absolutely no sense until you finally find the tiny mistake causing it.&lt;/p&gt;

&lt;p&gt;It cannot replace shipping software.&lt;/p&gt;

&lt;p&gt;And it definitely cannot turn someone into an experienced developer overnight.&lt;/p&gt;

&lt;p&gt;So for most of my career, certificates were completely out of the equation.&lt;/p&gt;

&lt;p&gt;I based my argument on practical experience.&lt;/p&gt;

&lt;p&gt;Build things. Solve problems. Learn what you need. Repeat.&lt;/p&gt;

&lt;p&gt;But there was a weakness in that argument that I hadn't paid enough attention to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experience and proof are not the same thing
&lt;/h2&gt;

&lt;p&gt;You might know C#.&lt;/p&gt;

&lt;p&gt;You might have used it professionally for years.&lt;/p&gt;

&lt;p&gt;But someone looking at your LinkedIn profile, resume, portfolio, or job application doesn't automatically know that.&lt;/p&gt;

&lt;p&gt;They have to take your word for it or spend time examining your work.&lt;/p&gt;

&lt;p&gt;A credential gives them another signal.&lt;/p&gt;

&lt;p&gt;Not proof that you're an amazing developer.&lt;/p&gt;

&lt;p&gt;Not proof that you're better than somebody without one.&lt;/p&gt;

&lt;p&gt;Just another piece of evidence.&lt;/p&gt;

&lt;p&gt;That distinction changed the equation for me.&lt;/p&gt;

&lt;p&gt;Microsoft describes Applied Skills credentials as a way to demonstrate practical ability through lab-based assessments involving real tasks rather than relying entirely on traditional knowledge questions.&lt;/p&gt;

&lt;p&gt;That caught my attention.&lt;/p&gt;

&lt;p&gt;So I decided to test one.&lt;/p&gt;

&lt;h2&gt;
  
  
  I chose C# classes, properties, and methods
&lt;/h2&gt;

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

&lt;p&gt;&lt;strong&gt;Microsoft Applied Skills: Get started with classes, properties, and methods in C#&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's a beginner-level credential focused on fundamental object-oriented C# skills. Microsoft says the assessment evaluates your ability to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create classes, objects, and types&lt;/li&gt;
&lt;li&gt;work with properties&lt;/li&gt;
&lt;li&gt;work with methods&lt;/li&gt;
&lt;li&gt;call properties and methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The assessment itself is an interactive lab, and Microsoft currently gives candidates up to two hours to complete it.&lt;/p&gt;

&lt;p&gt;You can see the official credential and assessment here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/credentials/applied-skills/get-started-with-classes-properties-and-methods-in-c-sharp/" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/credentials/applied-skills/get-started-with-classes-properties-and-methods-in-c-sharp/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I already had years of .NET experience, so my goal wasn't to learn C# from zero.&lt;/p&gt;

&lt;p&gt;My goal was different:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Could I organize what I needed to revise, hammer on my weak areas, practice them, and pass the assessment in three days?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I started preparing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three-day preparation
&lt;/h2&gt;

&lt;p&gt;I didn't want to spend three days passively reading documentation.&lt;/p&gt;

&lt;p&gt;I wanted something I could actually work through.&lt;/p&gt;

&lt;p&gt;So I built my own preparation folder.&lt;/p&gt;

&lt;p&gt;As I revised, I organized the concepts I needed, wrote examples, practiced the syntax, and focused on the areas covered by the assessment.&lt;/p&gt;

&lt;p&gt;Classes.&lt;/p&gt;

&lt;p&gt;Objects.&lt;/p&gt;

&lt;p&gt;Constructors.&lt;/p&gt;

&lt;p&gt;Properties.&lt;/p&gt;

&lt;p&gt;Access modifiers.&lt;/p&gt;

&lt;p&gt;Nullable properties.&lt;/p&gt;

&lt;p&gt;Methods.&lt;/p&gt;

&lt;p&gt;Return values.&lt;/p&gt;

&lt;p&gt;Method overloading.&lt;/p&gt;

&lt;p&gt;Static classes and members.&lt;/p&gt;

&lt;p&gt;Object initializers.&lt;/p&gt;

&lt;p&gt;And the small details that are incredibly easy to understand when reading code but surprisingly easy to forget when you have to write the code yourself.&lt;/p&gt;

&lt;p&gt;That last part mattered.&lt;/p&gt;

&lt;p&gt;There's a big difference between:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Yeah, I know what that is.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Give me an empty editor. I can implement it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Microsoft's own study guide reflects that practical scope, covering class creation, property access, nullable/default values, methods, overloads, static classes, object instantiation, and calling methods and properties.&lt;/p&gt;

&lt;p&gt;So I practiced.&lt;/p&gt;

&lt;p&gt;Then I took the assessment.&lt;/p&gt;

&lt;p&gt;And I passed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The certificate wasn't actually the biggest benefit
&lt;/h2&gt;

&lt;p&gt;This was the counterintuitive part.&lt;/p&gt;

&lt;p&gt;I started because I wanted the credential.&lt;/p&gt;

&lt;p&gt;But the preparation itself ended up being just as valuable.&lt;/p&gt;

&lt;p&gt;When you've programmed for a long time, you accumulate knowledge from everywhere.&lt;/p&gt;

&lt;p&gt;Documentation.&lt;/p&gt;

&lt;p&gt;Stack Overflow.&lt;/p&gt;

&lt;p&gt;Projects.&lt;/p&gt;

&lt;p&gt;Coworkers.&lt;/p&gt;

&lt;p&gt;Bugs.&lt;/p&gt;

&lt;p&gt;Frameworks.&lt;/p&gt;

&lt;p&gt;Old codebases.&lt;/p&gt;

&lt;p&gt;New codebases.&lt;/p&gt;

&lt;p&gt;And increasingly, AI tools.&lt;/p&gt;

&lt;p&gt;You can become productive while still having little gaps in fundamentals that you haven't explicitly revisited in years.&lt;/p&gt;

&lt;p&gt;Preparing for an assessment forces you to organize that knowledge.&lt;/p&gt;

&lt;p&gt;You stop saying:&lt;/p&gt;

&lt;p&gt;“I basically know this.”&lt;/p&gt;

&lt;p&gt;You have to find out whether you actually do.&lt;/p&gt;

&lt;p&gt;That exposed a few things I needed to hammer on.&lt;/p&gt;

&lt;p&gt;And that's useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Certificates won't replace a portfolio
&lt;/h2&gt;

&lt;p&gt;I still wouldn't tell a developer to collect certificates and neglect everything else.&lt;/p&gt;

&lt;p&gt;If I had to weigh a credential against the ability to actually build software, practical ability would take precedence.&lt;/p&gt;

&lt;p&gt;Build projects.&lt;/p&gt;

&lt;p&gt;Write code.&lt;/p&gt;

&lt;p&gt;Learn debugging.&lt;/p&gt;

&lt;p&gt;Understand databases.&lt;/p&gt;

&lt;p&gt;Learn APIs.&lt;/p&gt;

&lt;p&gt;Understand how applications are structured.&lt;/p&gt;

&lt;p&gt;Break things.&lt;/p&gt;

&lt;p&gt;Fix them.&lt;/p&gt;

&lt;p&gt;Ship something.&lt;/p&gt;

&lt;p&gt;But it doesn't have to be &lt;strong&gt;projects OR credentials&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can have both.&lt;/p&gt;

&lt;p&gt;A project demonstrates what you've built.&lt;/p&gt;

&lt;p&gt;Experience demonstrates what you've done professionally.&lt;/p&gt;

&lt;p&gt;A credential gives you an external signal that you've demonstrated a defined set of skills.&lt;/p&gt;

&lt;p&gt;Those things can complement each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credentials can also give your learning a finish line
&lt;/h2&gt;

&lt;p&gt;This might be my favorite benefit.&lt;/p&gt;

&lt;p&gt;“Learn more C#” is a terrible goal.&lt;/p&gt;

&lt;p&gt;Where do you stop?&lt;/p&gt;

&lt;p&gt;What exactly do you study?&lt;/p&gt;

&lt;p&gt;How do you know when you've learned enough?&lt;/p&gt;

&lt;p&gt;An assessment gives the learning process boundaries.&lt;/p&gt;

&lt;p&gt;You have a defined skill set.&lt;/p&gt;

&lt;p&gt;You prepare.&lt;/p&gt;

&lt;p&gt;You practice.&lt;/p&gt;

&lt;p&gt;You take the assessment.&lt;/p&gt;

&lt;p&gt;You pass or you discover where you're weak.&lt;/p&gt;

&lt;p&gt;Either outcome gives you information.&lt;/p&gt;

&lt;p&gt;Instead of endlessly consuming tutorials, you're working toward something concrete.&lt;/p&gt;

&lt;p&gt;For me, that created momentum.&lt;/p&gt;

&lt;p&gt;I got the first credential.&lt;/p&gt;

&lt;p&gt;Now I want to keep rolling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does a Microsoft Applied Skills credential guarantee you a job?
&lt;/h2&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;And I wouldn't sell that idea to anyone.&lt;/p&gt;

&lt;p&gt;A hiring decision involves experience, communication, technical ability, location, salary, the company, the role, competition, and sometimes plain luck.&lt;/p&gt;

&lt;p&gt;One credential doesn't erase that.&lt;/p&gt;

&lt;p&gt;But job hunting is rarely about finding one magical thing that gets you hired.&lt;/p&gt;

&lt;p&gt;It's about compounding signals.&lt;/p&gt;

&lt;p&gt;Your experience.&lt;/p&gt;

&lt;p&gt;Your projects.&lt;/p&gt;

&lt;p&gt;Your portfolio.&lt;/p&gt;

&lt;p&gt;Your GitHub.&lt;/p&gt;

&lt;p&gt;Your ability to articulate technical decisions.&lt;/p&gt;

&lt;p&gt;Your credentials.&lt;/p&gt;

&lt;p&gt;Your communication.&lt;/p&gt;

&lt;p&gt;One more credible signal can be useful.&lt;/p&gt;

&lt;p&gt;Microsoft itself positions Applied Skills as Microsoft-verified credentials designed to demonstrate specific practical skills, including through interactive, lab-based assessments.&lt;/p&gt;

&lt;p&gt;That's the way I'm looking at them now.&lt;/p&gt;

&lt;p&gt;Not as a replacement for experience.&lt;/p&gt;

&lt;p&gt;As another layer of proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would I pursue more Microsoft credentials?
&lt;/h2&gt;

&lt;p&gt;Yes.&lt;/p&gt;

&lt;p&gt;That's probably the biggest change in my position.&lt;/p&gt;

&lt;p&gt;After roughly 14 years of programming without paying much attention to certificates, I earned one and immediately understood why they can be useful.&lt;/p&gt;

&lt;p&gt;Not because the badge suddenly makes me a better programmer.&lt;/p&gt;

&lt;p&gt;It doesn't.&lt;/p&gt;

&lt;p&gt;The value was the process:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose a skill → revise it → practice it → identify gaps → prove it → move forward.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's a learning loop I can repeat.&lt;/p&gt;

&lt;p&gt;And I intend to.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you're preparing for the same C# assessment
&lt;/h2&gt;

&lt;p&gt;During my three-day preparation, I created the material for myself first.&lt;/p&gt;

&lt;p&gt;It wasn't originally some grand product idea.&lt;/p&gt;

&lt;p&gt;It was my prep folder.&lt;/p&gt;

&lt;p&gt;After passing, I realized someone else preparing for the exact same assessment might find it useful.&lt;/p&gt;

&lt;p&gt;So I cleaned it up and turned it into a focused preparation resource:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C# Classes, Properties &amp;amp; Methods: My 3-Day Microsoft Applied Skills Prep&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It follows the concepts I revised before successfully completing the Microsoft Applied Skills assessment, with explanations, C# examples, and exercises.&lt;/p&gt;

&lt;p&gt;It's not a shortcut around learning the material.&lt;/p&gt;

&lt;p&gt;It's the material I used to make my own revision more focused.&lt;/p&gt;

&lt;p&gt;You can check it out here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://yaman95.gumroad.com/l/microsoft-applied-skills-classes-methods-properties" rel="noopener noreferrer"&gt;https://yaman95.gumroad.com/l/microsoft-applied-skills-classes-methods-properties&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And whether you use my notes or prepare completely on your own, I'd recommend giving the assessment a shot if these are skills you're currently learning.&lt;/p&gt;

&lt;p&gt;Three days ago, I had never earned a Microsoft credential.&lt;/p&gt;

&lt;p&gt;Now I have my first one.&lt;/p&gt;

&lt;p&gt;Time to work toward the next.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>webdev</category>
      <category>programming</category>
      <category>csharp</category>
    </item>
    <item>
      <title>I’ve Written C# for 10+ Years. These Are the Fundamentals I Still Revisit.</title>
      <dc:creator>Ayman Atif</dc:creator>
      <pubDate>Thu, 17 Sep 2026 21:23:10 +0000</pubDate>
      <link>https://dev.to/a95yman/ive-written-c-for-10-years-these-are-the-fundamentals-i-still-revisit-2f0h</link>
      <guid>https://dev.to/a95yman/ive-written-c-for-10-years-these-are-the-fundamentals-i-still-revisit-2f0h</guid>
      <description>&lt;p&gt;After more than 10 years of writing C#, I still look things up.&lt;/p&gt;

&lt;p&gt;Not obscure reflection APIs.&lt;/p&gt;

&lt;p&gt;Not some forgotten compiler flag.&lt;/p&gt;

&lt;p&gt;Fundamentals.&lt;/p&gt;

&lt;p&gt;The difference between &lt;code&gt;const&lt;/code&gt; and &lt;code&gt;readonly&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What exactly happens when I pass a reference type to a method.&lt;/p&gt;

&lt;p&gt;Whether a LINQ query has actually executed yet.&lt;/p&gt;

&lt;p&gt;What lifetime a dependency should have.&lt;/p&gt;

&lt;p&gt;What happens to an exception inside an asynchronous operation.&lt;/p&gt;

&lt;p&gt;Things I learned years ago.&lt;/p&gt;

&lt;p&gt;Early in my career, I thought becoming an experienced developer meant eventually reaching a point where these questions disappeared.&lt;/p&gt;

&lt;p&gt;The opposite happened.&lt;/p&gt;

&lt;p&gt;The longer I worked with production software, the more I realized that a surprising number of difficult bugs come down to simple concepts behaving exactly as designed.&lt;/p&gt;

&lt;p&gt;You just misunderstood the design.&lt;/p&gt;

&lt;p&gt;I’m &lt;strong&gt;Ayman Atif&lt;/strong&gt;, a software engineer with more than 10 years of experience building business software, including CRM systems, financial applications, APIs, automation tools, reporting systems, and other production applications.&lt;/p&gt;

&lt;p&gt;C# and .NET have been a major part of that journey.&lt;/p&gt;

&lt;p&gt;You can see some of the software I’ve worked on and more about my background on my portfolio:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://ayman-atif.vercel.app/" rel="noopener noreferrer"&gt;Ayman Atif — Software Engineer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are some of the C# fundamentals I still revisit.&lt;/p&gt;

&lt;p&gt;Not because I forgot how to write C#.&lt;/p&gt;

&lt;p&gt;Because understanding them properly matters much more once the code has to survive production.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Value Types vs. Reference Types
&lt;/h2&gt;

&lt;p&gt;Every C# developer learns this fairly early.&lt;/p&gt;

&lt;p&gt;Value types contain their value.&lt;/p&gt;

&lt;p&gt;Reference types contain a reference to an object.&lt;/p&gt;

&lt;p&gt;Easy.&lt;/p&gt;

&lt;p&gt;Until code like this appears:&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;customer&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;Customer&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"John"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;UpdateCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;UpdateCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ayman"&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;The output is:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;That surprises almost nobody with C# experience.&lt;/p&gt;

&lt;p&gt;But change the method slightly:&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;void&lt;/span&gt; &lt;span class="nf"&gt;UpdateCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;customer&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;Customer&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ayman"&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 original object hasn't been replaced.&lt;/p&gt;

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

&lt;p&gt;Because the reference itself was passed &lt;strong&gt;by value&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The method received a copy of that reference.&lt;/p&gt;

&lt;p&gt;Both references initially pointed to the same object. Reassigning the local copy doesn't change the caller's variable.&lt;/p&gt;

&lt;p&gt;That distinction sounds academic when you're learning C#.&lt;/p&gt;

&lt;p&gt;It stops being academic when you're debugging mutation across a large application.&lt;/p&gt;

&lt;p&gt;The useful question isn't simply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this a class or a struct?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What exactly is being copied, and what exactly can this code mutate?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question has saved me considerably more time than memorizing definitions.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;code&gt;const&lt;/code&gt; vs. &lt;code&gt;readonly&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is another one that looks almost too basic to revisit.&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;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;MaxRetries&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;versus:&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;readonly&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;MaxRetries&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;const&lt;/code&gt; value is known at compile time and is implicitly static.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;readonly&lt;/code&gt; field can be assigned when declared or inside a constructor.&lt;/p&gt;

&lt;p&gt;That means this is perfectly valid:&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;RetryPolicy&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;readonly&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;MaxRetries&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;RetryPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;maxRetries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;MaxRetries&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;maxRetries&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;But there's another reason I pay attention to &lt;code&gt;const&lt;/code&gt;, especially when libraries or multiple assemblies are involved.&lt;/p&gt;

&lt;p&gt;Constants can effectively be embedded into consuming code at compile time.&lt;/p&gt;

&lt;p&gt;Change a public constant in one assembly and an already-compiled consumer may continue using the old value until it is recompiled.&lt;/p&gt;

&lt;p&gt;That's the kind of detail that doesn't matter much in a console exercise.&lt;/p&gt;

&lt;p&gt;Across independently deployed components, it can matter a lot.&lt;/p&gt;

&lt;p&gt;The fundamental didn't change.&lt;/p&gt;

&lt;p&gt;The context did.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;code&gt;var&lt;/code&gt; Is Not &lt;code&gt;dynamic&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I still see these mentally grouped together because both can make the declared type less obvious when reading a line of code.&lt;/p&gt;

&lt;p&gt;But they solve completely different problems.&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetCustomer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler still knows the type of &lt;code&gt;customer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This:&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="kt"&gt;dynamic&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetCustomer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is different.&lt;/p&gt;

&lt;p&gt;Certain type checks are deferred until runtime.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;var&lt;/code&gt;, this fails at compile time:&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ten"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;dynamic&lt;/code&gt;, this is allowed:&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="kt"&gt;dynamic&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ten"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That flexibility comes with a tradeoff.&lt;/p&gt;

&lt;p&gt;You are moving some protection from compile time to runtime.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;var&lt;/code&gt; is mostly about letting the compiler infer a type.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dynamic&lt;/code&gt; changes how operations on that value are resolved.&lt;/p&gt;

&lt;p&gt;Small distinction.&lt;/p&gt;

&lt;p&gt;Very different consequences.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;out&lt;/code&gt;, and &lt;code&gt;in&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;These keywords are easy to memorize and surprisingly easy to become fuzzy about when you don't use them regularly.&lt;/p&gt;

&lt;p&gt;I periodically revisit them.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ref&lt;/code&gt; passes a variable by reference and expects it to already be initialized.&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;void&lt;/span&gt; &lt;span class="nf"&gt;Increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;number&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;&lt;code&gt;out&lt;/code&gt; also passes by reference, but the called method must assign a value before returning.&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="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;TryGetAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&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="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;age&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;&lt;code&gt;in&lt;/code&gt; passes an argument by reference while preventing the method from assigning to the parameter.&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;void&lt;/span&gt; &lt;span class="nf"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;LargeStruct&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// data cannot be reassigned here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax isn't the interesting part.&lt;/p&gt;

&lt;p&gt;The interesting part is recognizing what these keywords communicate about ownership, mutation, and intent.&lt;/p&gt;

&lt;p&gt;Most code doesn't need them.&lt;/p&gt;

&lt;p&gt;That's exactly why they're worth revisiting before using them casually.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. LINQ: When Does This Code Actually Run?
&lt;/h2&gt;

&lt;p&gt;LINQ is one of my favorite parts of C#.&lt;/p&gt;

&lt;p&gt;It is also very easy to write code that looks simpler than what it actually does.&lt;/p&gt;

&lt;p&gt;Consider:&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;activeCustomers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsActive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Has the filtering happened?&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;Many LINQ operations use deferred execution.&lt;/p&gt;

&lt;p&gt;The query may execute when you enumerate it:&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;foreach&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;customer&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;activeCustomers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&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;Or when you materialize it:&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="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="n"&gt;activeCustomers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That difference becomes much more important with Entity Framework Core.&lt;/p&gt;

&lt;p&gt;This:&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Customers&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsActive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;isn't the same thing as immediately loading every matching customer into memory.&lt;/p&gt;

&lt;p&gt;You're building a query.&lt;/p&gt;

&lt;p&gt;Then something like:&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;customers&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Customers&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsActive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;causes it to execute against the database.&lt;/p&gt;

&lt;p&gt;When debugging LINQ or EF Core code, one of my first questions is often:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At what point does this query actually execute?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many times does it execute?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Those two questions can expose some nasty performance problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; Don't Mean "Create Another Thread"
&lt;/h2&gt;

&lt;p&gt;This is probably one of the most important C# fundamentals to understand properly.&lt;/p&gt;

&lt;p&gt;I used to mentally associate asynchronous programming much more closely with threads.&lt;/p&gt;

&lt;p&gt;That's an easy mental model to fall back on.&lt;/p&gt;

&lt;p&gt;But:&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;await&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;does not simply mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create another thread and make it wait for the HTTP request.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For I/O-bound work, the whole point is that a thread doesn't need to sit there blocked while the external operation completes.&lt;/p&gt;

&lt;p&gt;When the operation finishes, execution can continue.&lt;/p&gt;

&lt;p&gt;That's incredibly important for server applications.&lt;/p&gt;

&lt;p&gt;Imagine an ASP.NET Core API handling hundreds of requests that are all waiting for databases, HTTP APIs, file operations, or other I/O.&lt;/p&gt;

&lt;p&gt;Blocking threads while they wait can eat up resources quickly.&lt;/p&gt;

&lt;p&gt;Asynchronous I/O allows those resources to be used more effectively.&lt;/p&gt;

&lt;p&gt;But there is another lesson here:&lt;/p&gt;

&lt;p&gt;Making a method &lt;code&gt;async&lt;/code&gt; doesn't magically make the application scalable.&lt;/p&gt;

&lt;p&gt;If you write:&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="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="nf"&gt;SomeAsyncOperation&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&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="nf"&gt;SomeAsyncOperation&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you are blocking again.&lt;/p&gt;

&lt;p&gt;Understanding &lt;strong&gt;why&lt;/strong&gt; async works matters much more than knowing where to type &lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. &lt;code&gt;IDisposable&lt;/code&gt; and &lt;code&gt;using&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I learned &lt;code&gt;using&lt;/code&gt; a long time ago.&lt;/p&gt;

&lt;p&gt;I appreciate it much more now.&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;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stream&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;FileStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;FileMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the scope ends, &lt;code&gt;Dispose()&lt;/code&gt; is called.&lt;/p&gt;

&lt;p&gt;Simple.&lt;/p&gt;

&lt;p&gt;But the underlying lesson is about resource ownership.&lt;/p&gt;

&lt;p&gt;Some objects represent resources that shouldn't simply be left for garbage collection to eventually deal with.&lt;/p&gt;

&lt;p&gt;Files.&lt;/p&gt;

&lt;p&gt;Streams.&lt;/p&gt;

&lt;p&gt;Database-related resources.&lt;/p&gt;

&lt;p&gt;Network resources.&lt;/p&gt;

&lt;p&gt;Native handles.&lt;/p&gt;

&lt;p&gt;And plenty of other things.&lt;/p&gt;

&lt;p&gt;Modern C# makes the syntax extremely clean:&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;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;CreateConnection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The syntax is almost boring.&lt;/p&gt;

&lt;p&gt;The responsibility behind it isn't.&lt;/p&gt;

&lt;p&gt;When working with something disposable, I want to know:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who owns this resource?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who is responsible for disposing it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That becomes especially important once dependency injection enters the equation.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Dependency Injection Lifetimes
&lt;/h2&gt;

&lt;p&gt;If you work with ASP.NET Core, you've probably seen these:&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="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddTransient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IService&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;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IService&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;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IService&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's tempting to memorize them as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Transient = always new
Scoped = once per request
Singleton = one
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a useful starting point.&lt;/p&gt;

&lt;p&gt;It isn't enough.&lt;/p&gt;

&lt;p&gt;The real question is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How long should this object live, and what does it depend on?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A singleton depending on state that belongs to an individual request should immediately make you suspicious.&lt;/p&gt;

&lt;p&gt;A service holding mutable shared state needs careful thought.&lt;/p&gt;

&lt;p&gt;An Entity Framework &lt;code&gt;DbContext&lt;/code&gt; has lifetime expectations of its own.&lt;/p&gt;

&lt;p&gt;These problems often don't look dramatic in code.&lt;/p&gt;

&lt;p&gt;The registrations might occupy three lines in &lt;code&gt;Program.cs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The bug can appear somewhere completely different.&lt;/p&gt;

&lt;p&gt;That's why I revisit service lifetimes instead of assuming that because I've used dependency injection for years, every lifetime decision is obvious.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Entity Framework Core Tracking
&lt;/h2&gt;

&lt;p&gt;EF Core makes database work pleasantly simple.&lt;/p&gt;

&lt;p&gt;Sometimes too simple.&lt;/p&gt;

&lt;p&gt;You can write:&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;customers&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Customers&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and move on.&lt;/p&gt;

&lt;p&gt;But what is EF Core doing with those entities afterward?&lt;/p&gt;

&lt;p&gt;By default, queries returning entities are generally tracking them.&lt;/p&gt;

&lt;p&gt;That's useful when you intend to modify them and save the changes.&lt;/p&gt;

&lt;p&gt;If you're loading data purely for reading, tracking may be unnecessary.&lt;/p&gt;

&lt;p&gt;That's where something like this becomes useful:&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;customers&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;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Customers&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm not suggesting throwing &lt;code&gt;AsNoTracking()&lt;/code&gt; onto every query.&lt;/p&gt;

&lt;p&gt;That would just replace one habit with another.&lt;/p&gt;

&lt;p&gt;The point is understanding what the framework is doing for you.&lt;/p&gt;

&lt;p&gt;Abstractions are useful because they hide complexity.&lt;/p&gt;

&lt;p&gt;Experienced developers still need to know enough about the hidden complexity to recognize when it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Exceptions: Catching Everything Isn't Defensive Programming
&lt;/h2&gt;

&lt;p&gt;This looks safe:&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;try&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;ProcessOrder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&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;It isn't.&lt;/p&gt;

&lt;p&gt;You've taken an error and made it invisible.&lt;/p&gt;

&lt;p&gt;A slightly more sophisticated version isn't necessarily much better:&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;try&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;ProcessOrder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&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;What happens now?&lt;/p&gt;

&lt;p&gt;Can the application continue safely?&lt;/p&gt;

&lt;p&gt;Should the operation be retried?&lt;/p&gt;

&lt;p&gt;Should the caller know it failed?&lt;/p&gt;

&lt;p&gt;Should it be logged?&lt;/p&gt;

&lt;p&gt;Is this actually the correct layer to handle the exception?&lt;/p&gt;

&lt;p&gt;Catching an exception should have a reason.&lt;/p&gt;

&lt;p&gt;Sometimes the correct decision is to handle it.&lt;/p&gt;

&lt;p&gt;Sometimes it's to translate it into something meaningful at an application boundary.&lt;/p&gt;

&lt;p&gt;Sometimes it's to log it.&lt;/p&gt;

&lt;p&gt;And sometimes the correct decision is to let it propagate.&lt;/p&gt;

&lt;p&gt;I don't base exception handling on:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can this throw?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I prefer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can this layer do something meaningful if it throws?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That produces very different code.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Collections Are Part of Your Design
&lt;/h2&gt;

&lt;p&gt;Need several objects?&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's often perfectly fine.&lt;/p&gt;

&lt;p&gt;But not always.&lt;/p&gt;

&lt;p&gt;If you're repeatedly checking whether something exists:&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&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="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then the choice between something like a &lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; and a &lt;code&gt;HashSet&amp;lt;T&amp;gt;&lt;/code&gt; can become important as the collection grows.&lt;/p&gt;

&lt;p&gt;If you're constantly retrieving values by key, a &lt;code&gt;Dictionary&amp;lt;TKey, TValue&amp;gt;&lt;/code&gt; may better represent the problem.&lt;/p&gt;

&lt;p&gt;The data structure communicates something about the operation you care about.&lt;/p&gt;

&lt;p&gt;A list says sequence.&lt;/p&gt;

&lt;p&gt;A dictionary says lookup by key.&lt;/p&gt;

&lt;p&gt;A set says uniqueness and membership.&lt;/p&gt;

&lt;p&gt;You don't need to obsess over theoretical complexity every time you create a collection.&lt;/p&gt;

&lt;p&gt;But once data grows or an operation sits inside a hot loop, choosing the right structure can change the equation considerably.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. &lt;code&gt;static&lt;/code&gt; Deserves More Thought Than It Gets
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;static&lt;/code&gt; looks harmless.&lt;/p&gt;

&lt;p&gt;Sometimes it is exactly what you need.&lt;/p&gt;

&lt;p&gt;But static state can quietly create coupling.&lt;/p&gt;

&lt;p&gt;Consider:&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;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CurrentUser&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;static&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That might look convenient in a tiny application.&lt;/p&gt;

&lt;p&gt;Now introduce concurrent users.&lt;/p&gt;

&lt;p&gt;Tests.&lt;/p&gt;

&lt;p&gt;Parallel execution.&lt;/p&gt;

&lt;p&gt;Different request contexts.&lt;/p&gt;

&lt;p&gt;Suddenly that convenience needs much more scrutiny.&lt;/p&gt;

&lt;p&gt;This doesn't mean static members are bad.&lt;/p&gt;

&lt;p&gt;Far from it.&lt;/p&gt;

&lt;p&gt;Pure utility functionality can make perfect sense as static behavior.&lt;/p&gt;

&lt;p&gt;Constants and genuinely application-wide state have legitimate uses too.&lt;/p&gt;

&lt;p&gt;The important distinction is between:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;functionality that doesn't require instance state&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mutable global state that happens to be convenient.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Those are not the same thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Equality Is More Complicated Than &lt;code&gt;==&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This is another fundamental that becomes interesting once domain models become more complicated.&lt;/p&gt;

&lt;p&gt;What does it mean for two objects to be equal?&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;customer1&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;Customer&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;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ayman"&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;customer2&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;Customer&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;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ayman"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Are these equal?&lt;/p&gt;

&lt;p&gt;They contain the same values.&lt;/p&gt;

&lt;p&gt;But they're two separate instances.&lt;/p&gt;

&lt;p&gt;Depending on the type and how equality is implemented, your answer may differ.&lt;/p&gt;

&lt;p&gt;Then records enter the picture:&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;record&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;(&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="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Records give you value-oriented equality semantics that can be extremely useful for certain models.&lt;/p&gt;

&lt;p&gt;The broader lesson isn't "use records."&lt;/p&gt;

&lt;p&gt;It's to define what equality actually means for the thing you're modeling.&lt;/p&gt;

&lt;p&gt;Two references being different doesn't necessarily mean the domain considers the values different.&lt;/p&gt;

&lt;p&gt;And two references pointing to the same object doesn't necessarily tell you anything useful about business identity.&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Nullability Is Better When You Treat It as Design Information
&lt;/h2&gt;

&lt;p&gt;Nullable reference types were one of those C# additions that initially looked like extra compiler noise to some developers.&lt;/p&gt;

&lt;p&gt;But consider:&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="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;versus:&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;?&lt;/code&gt; communicates something.&lt;/p&gt;

&lt;p&gt;The absence of a value is expected.&lt;/p&gt;

&lt;p&gt;That's not merely a compiler detail.&lt;/p&gt;

&lt;p&gt;It's information about your model.&lt;/p&gt;

&lt;p&gt;If a customer must always have an email address, model that intentionally.&lt;/p&gt;

&lt;p&gt;If a middle name is optional, model that intentionally too.&lt;/p&gt;

&lt;p&gt;The goal isn't to silence every nullable warning as quickly as possible.&lt;/p&gt;

&lt;p&gt;The goal is to make the compiler help you identify places where your assumptions about missing values may be wrong.&lt;/p&gt;

&lt;p&gt;The more accurately the type system describes reality, the less defensive guessing the rest of your code needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pattern I Keep Seeing
&lt;/h2&gt;

&lt;p&gt;After years of C# and .NET development, I've noticed something.&lt;/p&gt;

&lt;p&gt;Junior developers often worry about not knowing enough advanced features.&lt;/p&gt;

&lt;p&gt;Experienced developers often worry about misunderstanding simple ones.&lt;/p&gt;

&lt;p&gt;That's a very different concern.&lt;/p&gt;

&lt;p&gt;A clever language feature might save you five lines of code.&lt;/p&gt;

&lt;p&gt;A misunderstanding of object lifetime, async behavior, query execution, mutation, equality, or resource ownership can create a bug that takes hours to find.&lt;/p&gt;

&lt;p&gt;Sometimes days.&lt;/p&gt;

&lt;p&gt;Production software has repeatedly hammered that lesson into me.&lt;/p&gt;

&lt;p&gt;The code that causes the worst problems isn't always complicated.&lt;/p&gt;

&lt;p&gt;Sometimes it's completely ordinary code built on one incorrect assumption.&lt;/p&gt;

&lt;h2&gt;
  
  
  You Don't Outgrow the Fundamentals
&lt;/h2&gt;

&lt;p&gt;Ten years ago, revisiting C# fundamentals would have felt like going backward.&lt;/p&gt;

&lt;p&gt;Today I see it differently.&lt;/p&gt;

&lt;p&gt;I don't need to prove that I remember every detail of the language without checking documentation.&lt;/p&gt;

&lt;p&gt;I need to make good engineering decisions.&lt;/p&gt;

&lt;p&gt;Sometimes that means opening the documentation.&lt;/p&gt;

&lt;p&gt;Sometimes it means writing a tiny console application to verify behavior.&lt;/p&gt;

&lt;p&gt;Sometimes it means reconsidering my position on a pattern I've used for years.&lt;/p&gt;

&lt;p&gt;And sometimes it means returning to something I supposedly "learned" a decade ago and realizing I understand it differently now.&lt;/p&gt;

&lt;p&gt;That's not going backward.&lt;/p&gt;

&lt;p&gt;That's what experience does.&lt;/p&gt;

&lt;p&gt;You stop collecting syntax.&lt;/p&gt;

&lt;p&gt;You start understanding consequences.&lt;/p&gt;

&lt;p&gt;And in a language as mature and capable as C#, there is always another layer underneath something you thought you already knew.&lt;/p&gt;




&lt;p&gt;I'm &lt;strong&gt;Ayman Atif&lt;/strong&gt;, a software engineer with 10+ years of experience building and maintaining production software with &lt;strong&gt;C#, .NET, Python, SQL, APIs, automation, financial systems, CRM platforms, and business applications&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I write about lessons from building real software, including the mistakes, architecture decisions, performance problems, and fundamentals that become more important as applications grow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Portfolio and projects:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ayman-atif.vercel.app/" rel="noopener noreferrer"&gt;Ayman Atif — Software Engineer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>programming</category>
      <category>backend</category>
    </item>
    <item>
      <title>How I Learned Odoo Development From Scratch and Got the Job in 30 Days</title>
      <dc:creator>Ayman Atif</dc:creator>
      <pubDate>Tue, 15 Sep 2026 15:40:21 +0000</pubDate>
      <link>https://dev.to/a95yman/how-i-learned-odoo-development-from-scratch-and-got-the-job-in-30-days-1ld8</link>
      <guid>https://dev.to/a95yman/how-i-learned-odoo-development-from-scratch-and-got-the-job-in-30-days-1ld8</guid>
      <description>&lt;p&gt;In 2024, I applied for an Odoo Developer role even though I had never worked with Odoo before.&lt;/p&gt;

&lt;p&gt;Not “a little experience.”&lt;/p&gt;

&lt;p&gt;Zero.&lt;/p&gt;

&lt;p&gt;I was already a software engineer with more than 10 years of experience building business software, primarily with .NET, alongside Python, APIs, automation, CRM systems, financial software, and production web applications.&lt;/p&gt;

&lt;p&gt;My name is Ayman Atif, and I have been developing software since 2014.&lt;/p&gt;

&lt;p&gt;You can see more of my work and background on my portfolio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ayman-atif.vercel.app/" rel="noopener noreferrer"&gt;https://ayman-atif.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the time, I was looking for a second income stream and applying for remote development jobs.&lt;/p&gt;

&lt;p&gt;Then I found a job post asking for:&lt;/p&gt;

&lt;p&gt;Python&lt;br&gt;
PostgreSQL&lt;br&gt;
Odoo&lt;/p&gt;

&lt;p&gt;Python was familiar territory.&lt;/p&gt;

&lt;p&gt;PostgreSQL was not a problem either.&lt;/p&gt;

&lt;p&gt;Odoo was the strange part.&lt;/p&gt;

&lt;p&gt;I had never developed an Odoo module.&lt;/p&gt;

&lt;p&gt;I had never built an Odoo application.&lt;/p&gt;

&lt;p&gt;I had barely paid attention to the platform before that job post appeared.&lt;/p&gt;

&lt;p&gt;Normally, that sounds like a job you skip.&lt;/p&gt;

&lt;p&gt;I applied anyway.&lt;/p&gt;

&lt;p&gt;That decision eventually led to one of the most useful lessons I have learned in my software career:&lt;/p&gt;

&lt;p&gt;You do not always need to know the technology before you apply. Sometimes you need to prove that you know how to learn it.&lt;/p&gt;

&lt;p&gt;This article explains exactly how I approached that month, what I studied, what I deliberately skipped, and the system I now use whenever I need to learn an unfamiliar technology quickly.&lt;/p&gt;

&lt;p&gt;I Did Not Pretend to Be an Odoo Developer&lt;/p&gt;

&lt;p&gt;This part matters.&lt;/p&gt;

&lt;p&gt;I did not rewrite my resume and pretend that I had Odoo experience.&lt;/p&gt;

&lt;p&gt;I did not exaggerate my background.&lt;/p&gt;

&lt;p&gt;I did not create a fake portfolio project and present myself as something I was not.&lt;/p&gt;

&lt;p&gt;Instead, I based my argument on something I could actually defend.&lt;/p&gt;

&lt;p&gt;I told the employer that I had experience transitioning into unfamiliar technical areas quickly.&lt;/p&gt;

&lt;p&gt;And I backed that claim with a real example.&lt;/p&gt;

&lt;p&gt;Before this Odoo opportunity, I had worked on a news aggregation system that automatically transformed news content into videos.&lt;/p&gt;

&lt;p&gt;That project involved AI-related development.&lt;/p&gt;

&lt;p&gt;At the time, I did not come from an AI background.&lt;/p&gt;

&lt;p&gt;I had to understand an unfamiliar technical area, experiment, solve practical problems, and contribute to a working system.&lt;/p&gt;

&lt;p&gt;That was the evidence behind my claim.&lt;/p&gt;

&lt;p&gt;My message was essentially:&lt;/p&gt;

&lt;p&gt;I may not know Odoo yet, but I have already demonstrated that I can enter unfamiliar technical territory and become productive.&lt;/p&gt;

&lt;p&gt;The letter was not particularly fancy.&lt;/p&gt;

&lt;p&gt;It was not full of corporate language.&lt;/p&gt;

&lt;p&gt;It was just honest.&lt;/p&gt;

&lt;p&gt;And apparently, that was enough to get their attention.&lt;/p&gt;

&lt;p&gt;The Employer Challenged My Claim&lt;/p&gt;

&lt;p&gt;Eventually, they came back with a simple challenge.&lt;/p&gt;

&lt;p&gt;If I believed I could transition into Odoo quickly, I had to prove it.&lt;/p&gt;

&lt;p&gt;I was given roughly one month to learn the basics of Odoo development and build a project.&lt;/p&gt;

&lt;p&gt;The project was an optical module for a clinic.&lt;/p&gt;

&lt;p&gt;That changed the equation completely.&lt;/p&gt;

&lt;p&gt;I no longer needed to convince someone with words.&lt;/p&gt;

&lt;p&gt;I had a real technical target.&lt;/p&gt;

&lt;p&gt;Thirty days.&lt;/p&gt;

&lt;p&gt;A technology I did not know.&lt;/p&gt;

&lt;p&gt;A real project at the end.&lt;/p&gt;

&lt;p&gt;This was exactly the kind of situation where spending three weeks preparing to start would have been a mistake.&lt;/p&gt;

&lt;p&gt;So I did not approach it like a traditional course.&lt;/p&gt;

&lt;p&gt;I approached it like a developer entering an unfamiliar codebase.&lt;/p&gt;

&lt;p&gt;Why I Did Not Start With a Long Odoo Course&lt;/p&gt;

&lt;p&gt;There is nothing inherently wrong with courses.&lt;/p&gt;

&lt;p&gt;The problem was time.&lt;/p&gt;

&lt;p&gt;I did not want to spend several hours watching someone explain how a manifest file works before I had even touched one.&lt;/p&gt;

&lt;p&gt;I needed context first.&lt;/p&gt;

&lt;p&gt;So instead of making tutorials the center of my learning process, I went directly to existing Odoo modules.&lt;/p&gt;

&lt;p&gt;I opened GitHub repositories.&lt;/p&gt;

&lt;p&gt;I looked at small modules.&lt;/p&gt;

&lt;p&gt;I scanned their structure.&lt;/p&gt;

&lt;p&gt;I wanted to see what kept repeating.&lt;/p&gt;

&lt;p&gt;Very quickly, certain pieces appeared again and again:&lt;/p&gt;

&lt;p&gt;manifest files&lt;br&gt;
models&lt;br&gt;
XML views&lt;br&gt;
module initialization&lt;br&gt;
Python classes&lt;br&gt;
fields&lt;br&gt;
actions&lt;br&gt;
menus&lt;/p&gt;

&lt;p&gt;That gave me a map.&lt;/p&gt;

&lt;p&gt;The important difference in my case was the order.&lt;/p&gt;

&lt;p&gt;I did not try to understand everything before writing anything.&lt;/p&gt;

&lt;p&gt;I touched the code first.&lt;/p&gt;

&lt;p&gt;My Learning Loop Was Simple&lt;/p&gt;

&lt;p&gt;My basic loop looked like this:&lt;/p&gt;

&lt;p&gt;Inspect → Rebuild → Modify → Break → Debug → Repeat&lt;/p&gt;

&lt;p&gt;I would open a small module and inspect how it was structured.&lt;/p&gt;

&lt;p&gt;Then I would rebuild part of it.&lt;/p&gt;

&lt;p&gt;Then I would change something.&lt;/p&gt;

&lt;p&gt;Then something would inevitably break.&lt;/p&gt;

&lt;p&gt;And that failure forced me to understand the part I had just touched.&lt;/p&gt;

&lt;p&gt;This was much more useful to me than passively watching hours of content.&lt;/p&gt;

&lt;p&gt;There is a counterintuitive part here.&lt;/p&gt;

&lt;p&gt;At the beginning, I memorized syntax.&lt;/p&gt;

&lt;p&gt;Sometimes almost word for word.&lt;/p&gt;

&lt;p&gt;Not because memorization was the end goal.&lt;/p&gt;

&lt;p&gt;Because it reduced friction.&lt;/p&gt;

&lt;p&gt;When you enter a completely unfamiliar framework, everything feels expensive.&lt;/p&gt;

&lt;p&gt;You forget the file names.&lt;/p&gt;

&lt;p&gt;You forget where things belong.&lt;/p&gt;

&lt;p&gt;You forget the syntax.&lt;/p&gt;

&lt;p&gt;You forget what calls what.&lt;/p&gt;

&lt;p&gt;If you memorize some of those mechanical pieces early, your brain has more room to understand the actual structure later.&lt;/p&gt;

&lt;p&gt;Understanding gradually replaced memorization.&lt;/p&gt;

&lt;p&gt;I Still Used YouTube, Just Not as the Main Learning Method&lt;/p&gt;

&lt;p&gt;I was also watching an Odoo development playlist.&lt;/p&gt;

&lt;p&gt;The playlist was titled:&lt;/p&gt;

&lt;p&gt;How To Configure Odoo15 With Pycharm || Odoo 15 Development Tutorials&lt;/p&gt;

&lt;p&gt;It contained around 189 videos.&lt;/p&gt;

&lt;p&gt;I watched somewhere around 60 of them.&lt;/p&gt;

&lt;p&gt;I did not sit down and consume all 189 videos before building anything.&lt;/p&gt;

&lt;p&gt;That would have defeated the purpose.&lt;/p&gt;

&lt;p&gt;I typically watched around two videos per day.&lt;/p&gt;

&lt;p&gt;Then I reinforced the concepts by working directly with modules.&lt;/p&gt;

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

&lt;p&gt;Watching was supporting the work.&lt;/p&gt;

&lt;p&gt;The work was not supporting the watching.&lt;/p&gt;

&lt;p&gt;A lot of developers accidentally reverse that.&lt;/p&gt;

&lt;p&gt;They spend days collecting information, then tell themselves they will build something once they “know enough.”&lt;/p&gt;

&lt;p&gt;You can easily get stuck there.&lt;/p&gt;

&lt;p&gt;What I Focused on First&lt;/p&gt;

&lt;p&gt;I deliberately narrowed the scope.&lt;/p&gt;

&lt;p&gt;I did not try to become an Odoo expert.&lt;/p&gt;

&lt;p&gt;I needed to become useful.&lt;/p&gt;

&lt;p&gt;So I worked through the structure in roughly this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Manifest Files&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wanted to understand what defined a module.&lt;/p&gt;

&lt;p&gt;What did Odoo need in order to recognize it?&lt;/p&gt;

&lt;p&gt;What information belonged in the manifest?&lt;/p&gt;

&lt;p&gt;What did dependencies look like?&lt;/p&gt;

&lt;p&gt;What resources were loaded?&lt;/p&gt;

&lt;p&gt;I did not need deep architectural knowledge yet.&lt;/p&gt;

&lt;p&gt;I needed orientation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Models&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the module structure felt less foreign, I moved into models.&lt;/p&gt;

&lt;p&gt;This part felt more natural because I already had years of programming experience.&lt;/p&gt;

&lt;p&gt;Classes, fields, business logic, relational data, validation, and procedural problem solving were not new concepts.&lt;/p&gt;

&lt;p&gt;The syntax was new.&lt;/p&gt;

&lt;p&gt;The thinking was not.&lt;/p&gt;

&lt;p&gt;That distinction is incredibly important when learning a new stack.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;XML Views&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then came the UI structure.&lt;/p&gt;

&lt;p&gt;Forms.&lt;/p&gt;

&lt;p&gt;Lists.&lt;/p&gt;

&lt;p&gt;Menus.&lt;/p&gt;

&lt;p&gt;Actions.&lt;/p&gt;

&lt;p&gt;Layouts.&lt;/p&gt;

&lt;p&gt;XML initially created more friction because it was tied closely to Odoo’s conventions.&lt;/p&gt;

&lt;p&gt;But repetition made it predictable.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Modification&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once I understood a small module, I changed it.&lt;/p&gt;

&lt;p&gt;Rename a field.&lt;/p&gt;

&lt;p&gt;Add something.&lt;/p&gt;

&lt;p&gt;Remove something.&lt;/p&gt;

&lt;p&gt;Change a view.&lt;/p&gt;

&lt;p&gt;Alter behavior.&lt;/p&gt;

&lt;p&gt;This was where the learning became real.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Debugging&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Breaking the module was often more educational than successfully copying it.&lt;/p&gt;

&lt;p&gt;When something failed, I had to follow the argument through.&lt;/p&gt;

&lt;p&gt;Why did it fail?&lt;/p&gt;

&lt;p&gt;Was the model wrong?&lt;/p&gt;

&lt;p&gt;Was the XML wrong?&lt;/p&gt;

&lt;p&gt;Was the module not loaded correctly?&lt;/p&gt;

&lt;p&gt;Was the field missing?&lt;/p&gt;

&lt;p&gt;Was the dependency wrong?&lt;/p&gt;

&lt;p&gt;Debugging turned passive familiarity into usable knowledge.&lt;/p&gt;

&lt;p&gt;My Existing Programming Experience Did Most of the Heavy Lifting&lt;/p&gt;

&lt;p&gt;This is one reason I do not think developers should mentally reset themselves to zero when switching technologies.&lt;/p&gt;

&lt;p&gt;Your previous experience is not out of the equation.&lt;/p&gt;

&lt;p&gt;It transfers.&lt;/p&gt;

&lt;p&gt;I already understood:&lt;/p&gt;

&lt;p&gt;procedural programming&lt;br&gt;
object-oriented programming&lt;br&gt;
databases&lt;br&gt;
debugging&lt;br&gt;
business logic&lt;br&gt;
APIs&lt;br&gt;
application structure&lt;br&gt;
data flow&lt;br&gt;
software maintenance&lt;br&gt;
production constraints&lt;/p&gt;

&lt;p&gt;I was learning a framework, not relearning how computers work.&lt;/p&gt;

&lt;p&gt;That dramatically shortened the learning curve.&lt;/p&gt;

&lt;p&gt;The more fundamentals you already understand, the less a new framework feels like starting over.&lt;/p&gt;

&lt;p&gt;My Daily Schedule&lt;/p&gt;

&lt;p&gt;My schedule during that period was fairly structured.&lt;/p&gt;

&lt;p&gt;I worked from around:&lt;/p&gt;

&lt;p&gt;9:00 AM to 6:00 PM&lt;/p&gt;

&lt;p&gt;with approximately a one-hour break.&lt;/p&gt;

&lt;p&gt;Outside of the core work period, I kept reinforcing what I was learning.&lt;/p&gt;

&lt;p&gt;After I got the role, the intensity increased.&lt;/p&gt;

&lt;p&gt;For roughly the next month, I was doing something close to:&lt;/p&gt;

&lt;p&gt;8 hours working&lt;/p&gt;

&lt;p&gt;plus&lt;/p&gt;

&lt;p&gt;4 additional hours learning and practicing&lt;/p&gt;

&lt;p&gt;That is around 12 hours a day connected to the new technology.&lt;/p&gt;

&lt;p&gt;I would not recommend that schedule indefinitely.&lt;/p&gt;

&lt;p&gt;It is difficult to sustain.&lt;/p&gt;

&lt;p&gt;But for a short transition period, it accelerated the feedback loop enormously.&lt;/p&gt;

&lt;p&gt;Every day I was seeing real problems at work, then learning the concepts behind them afterward.&lt;/p&gt;

&lt;p&gt;Work generated questions.&lt;/p&gt;

&lt;p&gt;Study answered them.&lt;/p&gt;

&lt;p&gt;The next day generated better questions.&lt;/p&gt;

&lt;p&gt;That compounded quickly.&lt;/p&gt;

&lt;p&gt;What Happened After the First Month&lt;/p&gt;

&lt;p&gt;At the end of the month, I completed the challenge and earned the role.&lt;/p&gt;

&lt;p&gt;But getting the job was not the end of the learning process.&lt;/p&gt;

&lt;p&gt;That was really when the useful learning started.&lt;/p&gt;

&lt;p&gt;During the first month, I was mainly getting comfortable with:&lt;/p&gt;

&lt;p&gt;module structure&lt;br&gt;
XML&lt;br&gt;
models&lt;br&gt;
views&lt;br&gt;
common patterns&lt;/p&gt;

&lt;p&gt;By the second month, I was moving beyond basic XML customization.&lt;/p&gt;

&lt;p&gt;I was able to work with Odoo OWL and build more custom controls.&lt;/p&gt;

&lt;p&gt;That mattered because it marked a transition.&lt;/p&gt;

&lt;p&gt;At the beginning, I was mostly learning how Odoo wanted things done.&lt;/p&gt;

&lt;p&gt;Later, I could start bending the framework toward actual requirements.&lt;/p&gt;

&lt;p&gt;That is a much better definition of progress than counting tutorial hours.&lt;/p&gt;

&lt;p&gt;The Goal Was Never to Become an Expert in 30 Days&lt;/p&gt;

&lt;p&gt;This is where these stories often become misleading.&lt;/p&gt;

&lt;p&gt;I did not become an Odoo expert in one month.&lt;/p&gt;

&lt;p&gt;That is not the lesson.&lt;/p&gt;

&lt;p&gt;I became useful enough to prove that I could do the work.&lt;/p&gt;

&lt;p&gt;Those are very different claims.&lt;/p&gt;

&lt;p&gt;Being useful means you can:&lt;/p&gt;

&lt;p&gt;understand the basic structure&lt;br&gt;
navigate the framework&lt;br&gt;
build something real&lt;br&gt;
diagnose common failures&lt;br&gt;
research unfamiliar problems&lt;br&gt;
make progress without constant supervision&lt;/p&gt;

&lt;p&gt;Expertise takes much longer.&lt;/p&gt;

&lt;p&gt;That is much closer to how I think developers should approach unfamiliar technology.&lt;/p&gt;

&lt;p&gt;Do not ask:&lt;/p&gt;

&lt;p&gt;How do I master this?&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;p&gt;What would make me useful with this?&lt;/p&gt;

&lt;p&gt;How I Would Learn an Unfamiliar Technology Today&lt;/p&gt;

&lt;p&gt;If I had to repeat the same experience with another framework, platform, or programming language, I would use almost the same process.&lt;/p&gt;

&lt;p&gt;Day 1 to 3: Understand the Shape&lt;/p&gt;

&lt;p&gt;Do not go deep.&lt;/p&gt;

&lt;p&gt;Figure out:&lt;/p&gt;

&lt;p&gt;project structure&lt;br&gt;
entry points&lt;br&gt;
configuration&lt;br&gt;
data model&lt;br&gt;
common terminology&lt;br&gt;
how the smallest working example looks&lt;/p&gt;

&lt;p&gt;Your goal is orientation.&lt;/p&gt;

&lt;p&gt;Day 4 to 7: Read Tiny Real Projects&lt;/p&gt;

&lt;p&gt;Find small repositories.&lt;/p&gt;

&lt;p&gt;Avoid huge production codebases at first.&lt;/p&gt;

&lt;p&gt;Look for repetition.&lt;/p&gt;

&lt;p&gt;What files always appear?&lt;/p&gt;

&lt;p&gt;What patterns repeat?&lt;/p&gt;

&lt;p&gt;Where does logic live?&lt;/p&gt;

&lt;p&gt;Where does configuration live?&lt;/p&gt;

&lt;p&gt;Week 2: Rebuild Examples&lt;/p&gt;

&lt;p&gt;Stop reading so much.&lt;/p&gt;

&lt;p&gt;Build.&lt;/p&gt;

&lt;p&gt;Recreate small features without constantly copying.&lt;/p&gt;

&lt;p&gt;When you forget something, look it up.&lt;/p&gt;

&lt;p&gt;Then continue.&lt;/p&gt;

&lt;p&gt;Week 3: Modify Aggressively&lt;/p&gt;

&lt;p&gt;Take things that work and change them.&lt;/p&gt;

&lt;p&gt;Add fields.&lt;/p&gt;

&lt;p&gt;Remove features.&lt;/p&gt;

&lt;p&gt;Change behaviors.&lt;/p&gt;

&lt;p&gt;Swap components.&lt;/p&gt;

&lt;p&gt;Push the framework outside the exact tutorial scenario.&lt;/p&gt;

&lt;p&gt;Week 4: Build One Real Project&lt;/p&gt;

&lt;p&gt;Pick something with clear requirements.&lt;/p&gt;

&lt;p&gt;Not a demo.&lt;/p&gt;

&lt;p&gt;Not “hello world.”&lt;/p&gt;

&lt;p&gt;Something that forces several concepts to work together.&lt;/p&gt;

&lt;p&gt;That project is where your fragmented knowledge starts becoming a system.&lt;/p&gt;

&lt;p&gt;Do Not Confuse Learning With Content Consumption&lt;/p&gt;

&lt;p&gt;One of the biggest traps in software development is feeling productive because you are consuming technical material.&lt;/p&gt;

&lt;p&gt;Ten hours of video can feel substantial.&lt;/p&gt;

&lt;p&gt;But ask yourself:&lt;/p&gt;

&lt;p&gt;Could you build something without the instructor?&lt;/p&gt;

&lt;p&gt;Could you explain why the project is structured that way?&lt;/p&gt;

&lt;p&gt;Could you diagnose it when it breaks?&lt;/p&gt;

&lt;p&gt;Could you change the requirement?&lt;/p&gt;

&lt;p&gt;If not, you are probably still at the recognition stage.&lt;/p&gt;

&lt;p&gt;Recognition feels like understanding because the code looks familiar.&lt;/p&gt;

&lt;p&gt;But producing it independently is different.&lt;/p&gt;

&lt;p&gt;This is why I prefer a build-heavy learning method.&lt;/p&gt;

&lt;p&gt;The code exposes what you actually know.&lt;/p&gt;

&lt;p&gt;Read Existing Code Earlier&lt;/p&gt;

&lt;p&gt;This is probably the biggest habit I would recommend.&lt;/p&gt;

&lt;p&gt;A lot of developers delay reading other people's code because it feels intimidating.&lt;/p&gt;

&lt;p&gt;I think that is backwards.&lt;/p&gt;

&lt;p&gt;Existing repositories show you things that tutorials often hide:&lt;/p&gt;

&lt;p&gt;real naming conventions&lt;br&gt;
real file structure&lt;br&gt;
repetition&lt;br&gt;
workarounds&lt;br&gt;
patterns&lt;br&gt;
configuration&lt;br&gt;
boring glue code&lt;/p&gt;

&lt;p&gt;That boring code is often exactly what you need to become productive.&lt;/p&gt;

&lt;p&gt;Framework fluency comes from recognizing its patterns repeatedly.&lt;/p&gt;

&lt;p&gt;What About AI?&lt;/p&gt;

&lt;p&gt;My original Odoo transition happened before AI coding assistants became as deeply integrated into everyday development as they are now.&lt;/p&gt;

&lt;p&gt;Today, learning the same framework would probably be faster.&lt;/p&gt;

&lt;p&gt;But there is also a new risk.&lt;/p&gt;

&lt;p&gt;AI can remove the struggle that produces understanding.&lt;/p&gt;

&lt;p&gt;If every error goes directly into an AI assistant and you paste back the fix, you may ship faster while learning less.&lt;/p&gt;

&lt;p&gt;I would use AI today, but I would keep one boundary:&lt;/p&gt;

&lt;p&gt;Never let it remove the need to understand the change you are making.&lt;/p&gt;

&lt;p&gt;Ask it to explain.&lt;/p&gt;

&lt;p&gt;Ask it to compare approaches.&lt;/p&gt;

&lt;p&gt;Ask it where to look.&lt;/p&gt;

&lt;p&gt;Ask it why something failed.&lt;/p&gt;

&lt;p&gt;But if you cannot explain the final solution yourself, you have probably outsourced too much of the learning.&lt;/p&gt;

&lt;p&gt;A Better Way to Think About Technology Switching&lt;/p&gt;

&lt;p&gt;Developers often identify themselves too tightly with one stack.&lt;/p&gt;

&lt;p&gt;“I am a .NET developer.”&lt;/p&gt;

&lt;p&gt;“I am a Java developer.”&lt;/p&gt;

&lt;p&gt;“I am a React developer.”&lt;/p&gt;

&lt;p&gt;There is nothing wrong with specialization.&lt;/p&gt;

&lt;p&gt;I still have deep experience with .NET.&lt;/p&gt;

&lt;p&gt;But your programming language is not your entire professional identity.&lt;/p&gt;

&lt;p&gt;The more experienced you become, the more your value comes from things that survive stack changes:&lt;/p&gt;

&lt;p&gt;debugging&lt;br&gt;
decomposition&lt;br&gt;
architecture&lt;br&gt;
data modeling&lt;br&gt;
reasoning&lt;br&gt;
communication&lt;br&gt;
requirement analysis&lt;br&gt;
tradeoffs&lt;br&gt;
maintainability&lt;br&gt;
learning speed&lt;/p&gt;

&lt;p&gt;That is why experienced developers can sometimes transition faster than they expect.&lt;/p&gt;

&lt;p&gt;The syntax changes.&lt;/p&gt;

&lt;p&gt;The underlying problems are often familiar.&lt;/p&gt;

&lt;p&gt;Should You Apply for Jobs Where You Do Not Match Every Requirement?&lt;/p&gt;

&lt;p&gt;Sometimes, yes.&lt;/p&gt;

&lt;p&gt;But there is a difference between being underqualified and being dishonest.&lt;/p&gt;

&lt;p&gt;I would still apply when:&lt;/p&gt;

&lt;p&gt;I understand the underlying engineering domain&lt;br&gt;
the missing skill is learnable&lt;br&gt;
I have evidence of learning similar things before&lt;br&gt;
I can articulate how my existing skills transfer&lt;br&gt;
I am willing to prove the claim&lt;/p&gt;

&lt;p&gt;I would not claim experience I do not have.&lt;/p&gt;

&lt;p&gt;That distinction probably helped me more than pretending would have.&lt;/p&gt;

&lt;p&gt;I was not selling Odoo expertise.&lt;/p&gt;

&lt;p&gt;I was selling adaptability.&lt;/p&gt;

&lt;p&gt;And then I had to pay up by actually learning it.&lt;/p&gt;

&lt;p&gt;The Repeatable Learning System&lt;/p&gt;

&lt;p&gt;If I reduce the entire experience to one system, it is this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Find the smallest real structure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inspect existing examples&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memorize enough syntax to remove friction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rebuild examples yourself&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modify them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Break them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Debug them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build one real project&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep learning after you become employable&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is the part I still use.&lt;/p&gt;

&lt;p&gt;Not Odoo specifically.&lt;/p&gt;

&lt;p&gt;The learning process.&lt;/p&gt;

&lt;p&gt;I Turned This Experience Into a Practical Guide&lt;/p&gt;

&lt;p&gt;I recently turned the full experience into a short practical PDF:&lt;/p&gt;

&lt;p&gt;I Got an Odoo Job With Zero Odoo Experience&lt;/p&gt;

&lt;p&gt;It includes the learning system, the 30-day structure, how I approached unfamiliar code, how I used existing programming experience, what happened after I got the role, and how to adapt the same process to another technology.&lt;/p&gt;

&lt;p&gt;You can find it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://yaman95.gumroad.com/l/i-got-odoo-job-with-zero-odoo-experience" rel="noopener noreferrer"&gt;https://yaman95.gumroad.com/l/i-got-odoo-job-with-zero-odoo-experience&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The guide is not about promising that someone can become an expert in 30 days.&lt;/p&gt;

&lt;p&gt;It is about becoming useful quickly enough to start doing real work, then continuing to learn from the work itself.&lt;/p&gt;

&lt;p&gt;About Ayman Atif&lt;/p&gt;

&lt;p&gt;I am Ayman Atif, a software engineer from Morocco with more than 10 years of experience building business software.&lt;/p&gt;

&lt;p&gt;I have worked primarily with .NET and C#, alongside Python, Flask, Django, PostgreSQL, REST APIs, automation, CRM systems, financial applications, Android development, and production business platforms.&lt;/p&gt;

&lt;p&gt;My work focuses heavily on understanding business problems, designing practical software around them, improving existing systems, and maintaining applications after they reach production.&lt;/p&gt;

&lt;p&gt;You can see my portfolio, selected projects, services, and other technical writing here:&lt;/p&gt;

&lt;p&gt;Ayman Atif, Software Engineer&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ayman-atif.vercel.app/" rel="noopener noreferrer"&gt;https://ayman-atif.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are learning a new technology, switching stacks, or trying to become productive in an unfamiliar framework, I hope this experience gives you a useful way to approach it.&lt;/p&gt;

&lt;p&gt;Do not wait until everything feels familiar.&lt;/p&gt;

&lt;p&gt;Familiarity often comes after you start building.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>odoo</category>
      <category>career</category>
      <category>hiring</category>
    </item>
    <item>
      <title>10 Years of Building Business Software: What Production Systems Taught Me That Tutorials Didn’t</title>
      <dc:creator>Ayman Atif</dc:creator>
      <pubDate>Sat, 12 Sep 2026 13:53:06 +0000</pubDate>
      <link>https://dev.to/a95yman/10-years-of-building-business-software-what-production-systems-taught-me-that-tutorials-didnt-5hka</link>
      <guid>https://dev.to/a95yman/10-years-of-building-business-software-what-production-systems-taught-me-that-tutorials-didnt-5hka</guid>
      <description>&lt;p&gt;I started developing software in 2014.&lt;/p&gt;

&lt;p&gt;Back then, like most developers, I spent a lot of time thinking about code.&lt;/p&gt;

&lt;p&gt;Was this the right design pattern? Was there a cleaner way to write this method? Should this logic live in another class? Was I using the framework correctly?&lt;/p&gt;

&lt;p&gt;Those questions matter. I still ask them.&lt;/p&gt;

&lt;p&gt;But after more than 10 years of building software, I have learned that they are rarely the hardest questions.&lt;/p&gt;

&lt;p&gt;The difficult part starts when software leaves your development environment and becomes something a business actually depends on.&lt;/p&gt;

&lt;p&gt;A feature can work perfectly and still be the wrong feature.&lt;/p&gt;

&lt;p&gt;A database query can be fine with 500 rows and become a problem with 500,000.&lt;/p&gt;

&lt;p&gt;A workflow that makes perfect sense to a developer can frustrate the people who have to use it every day.&lt;/p&gt;

&lt;p&gt;And a system that looks well designed today can become surprisingly difficult to change two years from now.&lt;/p&gt;

&lt;p&gt;Those are lessons that are difficult to learn from tutorials.&lt;/p&gt;

&lt;p&gt;You learn them by building, maintaining, breaking, fixing and improving real software.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Business Problem Comes Before the Technology
&lt;/h2&gt;

&lt;p&gt;Earlier in my career, I was much more likely to start thinking about implementation as soon as someone described a feature.&lt;/p&gt;

&lt;p&gt;Today, I try to understand the process first.&lt;/p&gt;

&lt;p&gt;What is the person actually trying to accomplish?&lt;/p&gt;

&lt;p&gt;What are they doing manually today?&lt;/p&gt;

&lt;p&gt;Where does the information come from?&lt;/p&gt;

&lt;p&gt;Who is responsible for it?&lt;/p&gt;

&lt;p&gt;What happens when something goes wrong?&lt;/p&gt;

&lt;p&gt;What part of the process is actually expensive or frustrating?&lt;/p&gt;

&lt;p&gt;Sometimes a client asks for a feature, but after following the workflow through, you realize that the requested feature is solving the symptom rather than the underlying problem.&lt;/p&gt;

&lt;p&gt;That changes the equation.&lt;/p&gt;

&lt;p&gt;The job is no longer simply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build what was requested.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Understand why it was requested, then determine what should actually be built.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is especially important with business software because existing processes often contain years of knowledge.&lt;/p&gt;

&lt;p&gt;A spreadsheet, for example, might look messy from an engineering perspective. But hidden inside that spreadsheet can be calculations, exceptions and business rules that employees have developed over years.&lt;/p&gt;

&lt;p&gt;Replacing it with software without understanding those rules can make the new system worse than the spreadsheet it replaced.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production Changes Your Definition of "Working"
&lt;/h2&gt;

&lt;p&gt;During development, it is easy to define success like this:&lt;/p&gt;

&lt;p&gt;The feature works.&lt;/p&gt;

&lt;p&gt;In production, that definition is nowhere near enough.&lt;/p&gt;

&lt;p&gt;Does it work when several people use it at the same time?&lt;/p&gt;

&lt;p&gt;Does it still work when the database becomes much larger?&lt;/p&gt;

&lt;p&gt;What happens when an external service fails?&lt;/p&gt;

&lt;p&gt;What happens when someone uploads unexpected data?&lt;/p&gt;

&lt;p&gt;Can you understand what happened when something breaks?&lt;/p&gt;

&lt;p&gt;Can another developer safely change the code six months later?&lt;/p&gt;

&lt;p&gt;Can the business recover if something goes wrong?&lt;/p&gt;

&lt;p&gt;A production system has responsibilities that a demo does not.&lt;/p&gt;

&lt;p&gt;I have worked on business applications involving financial data, document generation, reporting, CRM workflows, automation, APIs and complex database operations.&lt;/p&gt;

&lt;p&gt;The bugs that take the most time are often not obvious programming mistakes.&lt;/p&gt;

&lt;p&gt;They appear because several individually reasonable decisions interact in an unexpected way.&lt;/p&gt;

&lt;p&gt;That is one reason I have become much more interested in system behavior than isolated pieces of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Problems Are Often System Problems
&lt;/h2&gt;

&lt;p&gt;When an application becomes slow, the tempting response is to look for slow code.&lt;/p&gt;

&lt;p&gt;Sometimes that is exactly the problem.&lt;/p&gt;

&lt;p&gt;Often it isn't.&lt;/p&gt;

&lt;p&gt;The slowdown might involve database queries, indexes, repeated API calls, unnecessary browser work, server memory, large documents, network latency or several of those things compounding each other.&lt;/p&gt;

&lt;p&gt;Optimizing one function might accomplish almost nothing.&lt;/p&gt;

&lt;p&gt;I learned to trace the entire path instead.&lt;/p&gt;

&lt;p&gt;What happens from the moment the user clicks the button until the result appears?&lt;/p&gt;

&lt;p&gt;Where is time actually being spent?&lt;/p&gt;

&lt;p&gt;What data is being transferred?&lt;/p&gt;

&lt;p&gt;What work is repeated?&lt;/p&gt;

&lt;p&gt;What resources are constrained?&lt;/p&gt;

&lt;p&gt;You have to follow the argument through instead of assuming that the most visible part of the application is responsible.&lt;/p&gt;

&lt;p&gt;This mindset has saved me from "optimizing" code that wasn't causing the problem in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Existing Software Deserves Investigation Before a Rewrite
&lt;/h2&gt;

&lt;p&gt;Developers love clean starts.&lt;/p&gt;

&lt;p&gt;There is something satisfying about looking at an old application and imagining how much better it would be if we rebuilt everything using a modern architecture.&lt;/p&gt;

&lt;p&gt;Sometimes a rewrite is justified.&lt;/p&gt;

&lt;p&gt;But I have become much more cautious about recommending one.&lt;/p&gt;

&lt;p&gt;Old software contains knowledge.&lt;/p&gt;

&lt;p&gt;It contains strange conditions because somebody encountered a strange situation five years ago.&lt;/p&gt;

&lt;p&gt;It contains validation rules because something once went wrong.&lt;/p&gt;

&lt;p&gt;It contains workflows that employees have quietly adapted to.&lt;/p&gt;

&lt;p&gt;Some of the code may genuinely be bad. But deleting code is much easier than recovering the business knowledge that was encoded inside it.&lt;/p&gt;

&lt;p&gt;When I inherit an existing application, I prefer to understand it first.&lt;/p&gt;

&lt;p&gt;Find the fragile areas.&lt;/p&gt;

&lt;p&gt;Identify the dependencies.&lt;/p&gt;

&lt;p&gt;Understand the data.&lt;/p&gt;

&lt;p&gt;Fix the highest-risk problems.&lt;/p&gt;

&lt;p&gt;Improve boundaries gradually.&lt;/p&gt;

&lt;p&gt;Then decide whether replacing larger parts of the system is actually worth it.&lt;/p&gt;

&lt;p&gt;A rewrite should be an engineering decision, not an emotional reaction to ugly code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automation Is Mostly About Understanding Repetition
&lt;/h2&gt;

&lt;p&gt;Automation is another area where the programming is often the easy part.&lt;/p&gt;

&lt;p&gt;The real work is understanding the process well enough to automate it safely.&lt;/p&gt;

&lt;p&gt;Imagine someone repeatedly:&lt;/p&gt;

&lt;p&gt;opens a spreadsheet,&lt;/p&gt;

&lt;p&gt;copies information from another system,&lt;/p&gt;

&lt;p&gt;checks several conditions,&lt;/p&gt;

&lt;p&gt;generates a document,&lt;/p&gt;

&lt;p&gt;sends an email,&lt;/p&gt;

&lt;p&gt;and updates a status somewhere else.&lt;/p&gt;

&lt;p&gt;You could automate those steps.&lt;/p&gt;

&lt;p&gt;But first you need to know why each step exists.&lt;/p&gt;

&lt;p&gt;Which decisions require human judgment?&lt;/p&gt;

&lt;p&gt;Which rules are consistent?&lt;/p&gt;

&lt;p&gt;What happens when information is missing?&lt;/p&gt;

&lt;p&gt;What should happen when something fails halfway through?&lt;/p&gt;

&lt;p&gt;What needs to be logged?&lt;/p&gt;

&lt;p&gt;Can the process be resumed?&lt;/p&gt;

&lt;p&gt;Good automation does not simply make something faster.&lt;/p&gt;

&lt;p&gt;It makes a process more structured, repeatable and easier to inspect.&lt;/p&gt;

&lt;p&gt;That distinction has shaped the way I approach business process automation today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintainability Becomes Very Real When You Maintain Your Own Code
&lt;/h2&gt;

&lt;p&gt;There is a particular kind of humility that comes from opening code you wrote two years ago.&lt;/p&gt;

&lt;p&gt;At the time, everything seemed obvious.&lt;/p&gt;

&lt;p&gt;Two years later, you might stare at it wondering why anyone would structure something that way.&lt;/p&gt;

&lt;p&gt;Then you check the Git history.&lt;/p&gt;

&lt;p&gt;Oh.&lt;/p&gt;

&lt;p&gt;It was you.&lt;/p&gt;

&lt;p&gt;That experience changes how you think about maintainability.&lt;/p&gt;

&lt;p&gt;Clean code is not about making code look clever.&lt;/p&gt;

&lt;p&gt;Architecture is not about using as many abstractions as possible.&lt;/p&gt;

&lt;p&gt;Patterns are not achievements by themselves.&lt;/p&gt;

&lt;p&gt;The purpose is to make future changes safer and easier to reason about.&lt;/p&gt;

&lt;p&gt;Sometimes an abstraction helps.&lt;/p&gt;

&lt;p&gt;Sometimes three straightforward functions are better than an elaborate hierarchy.&lt;/p&gt;

&lt;p&gt;Sometimes duplication is temporarily less dangerous than coupling two things that only happen to look similar today.&lt;/p&gt;

&lt;p&gt;The longer I work in software, the less interested I become in rules that say you should "always" structure code a particular way.&lt;/p&gt;

&lt;p&gt;Context matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple Software Is Usually Hard to Build
&lt;/h2&gt;

&lt;p&gt;One of the most counterintuitive lessons I have learned is that simple software can require a lot of engineering.&lt;/p&gt;

&lt;p&gt;Users should not need to understand your database structure.&lt;/p&gt;

&lt;p&gt;They should not need to know that three APIs are involved.&lt;/p&gt;

&lt;p&gt;They should not care that a document is assembled from multiple sources.&lt;/p&gt;

&lt;p&gt;They want to click something and have the correct result appear.&lt;/p&gt;

&lt;p&gt;Making that experience simple often means handling considerable complexity behind the scenes.&lt;/p&gt;

&lt;p&gt;The temptation is to cut corners and expose some of that complexity to the user.&lt;/p&gt;

&lt;p&gt;But every technical responsibility you push onto users makes the system harder for the business to operate.&lt;/p&gt;

&lt;p&gt;Good business software absorbs complexity instead of distributing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Communication Is an Engineering Skill
&lt;/h2&gt;

&lt;p&gt;Ten years ago, if you had asked me what makes someone a strong software developer, I probably would have based my answer mostly on technical ability.&lt;/p&gt;

&lt;p&gt;Today, I would revise my position.&lt;/p&gt;

&lt;p&gt;Technical skill still matters enormously, but professional software development also requires being able to articulate tradeoffs.&lt;/p&gt;

&lt;p&gt;Why are we building this?&lt;/p&gt;

&lt;p&gt;Why this approach?&lt;/p&gt;

&lt;p&gt;What happens if we don't fix this problem?&lt;/p&gt;

&lt;p&gt;Why will this take longer than expected?&lt;/p&gt;

&lt;p&gt;What are we giving up by choosing option A instead of option B?&lt;/p&gt;

&lt;p&gt;Engineers constantly weigh speed against maintainability, flexibility against complexity, and short-term requirements against long-term consequences.&lt;/p&gt;

&lt;p&gt;If those tradeoffs remain inside the developer's head, the business cannot participate in the decision.&lt;/p&gt;

&lt;p&gt;Being able to explain them clearly is part of the engineering work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Best Technical Decision Depends on the Business
&lt;/h2&gt;

&lt;p&gt;I work primarily with .NET and Python today.&lt;/p&gt;

&lt;p&gt;Both are powerful ecosystems, but I don't believe the technology should take precedence over the problem.&lt;/p&gt;

&lt;p&gt;Sometimes ASP.NET Core is an excellent foundation for a long-lived business application.&lt;/p&gt;

&lt;p&gt;Sometimes Python and Flask let you build a focused internal system quickly and maintain it comfortably.&lt;/p&gt;

&lt;p&gt;Sometimes the correct solution is not a new application at all.&lt;/p&gt;

&lt;p&gt;Maybe an existing process can be improved.&lt;/p&gt;

&lt;p&gt;Maybe a small automation is enough.&lt;/p&gt;

&lt;p&gt;Maybe the spreadsheet should stay, but the repetitive work around it should disappear.&lt;/p&gt;

&lt;p&gt;Good engineering is not about finding opportunities to use your favorite technology.&lt;/p&gt;

&lt;p&gt;It is about choosing an appropriate amount of technology for the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Care About After 10+ Years
&lt;/h2&gt;

&lt;p&gt;My definition of software engineering has changed considerably since I started in 2014.&lt;/p&gt;

&lt;p&gt;I still care about code quality.&lt;/p&gt;

&lt;p&gt;I still enjoy learning frameworks, improving architecture and solving difficult technical problems.&lt;/p&gt;

&lt;p&gt;But those things now sit inside a larger picture.&lt;/p&gt;

&lt;p&gt;I care about understanding why the software exists.&lt;/p&gt;

&lt;p&gt;I care about what happens when it reaches production.&lt;/p&gt;

&lt;p&gt;I care about whether someone can safely maintain it.&lt;/p&gt;

&lt;p&gt;I care about whether it remains useful when the business changes.&lt;/p&gt;

&lt;p&gt;And I care about whether the technology is actually making someone's work easier.&lt;/p&gt;

&lt;p&gt;That is the side of software engineering I find most interesting today.&lt;/p&gt;

&lt;p&gt;I write more about these lessons in my &lt;strong&gt;software engineering blog&lt;/strong&gt;, where I cover .NET, backend engineering, architecture decisions, production constraints, technical interviews and lessons from building real systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read my software engineering blog:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ayman-atif.vercel.app/blog/" rel="noopener noreferrer"&gt;https://ayman-atif.vercel.app/blog/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're dealing with a business process that still relies heavily on spreadsheets, an application that has become difficult to maintain, or an idea that needs a technical plan, you can also learn more about my work here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ayman Atif — Software Engineer&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ayman-atif.vercel.app/" rel="noopener noreferrer"&gt;https://ayman-atif.vercel.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>softwaredevelopment</category>
      <category>programming</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>I Was a .NET Developer. Then My Company Told Me to Learn Android.</title>
      <dc:creator>Ayman Atif</dc:creator>
      <pubDate>Fri, 11 Sep 2026 14:10:59 +0000</pubDate>
      <link>https://dev.to/a95yman/i-was-a-net-developer-then-my-company-told-me-to-learn-android-3od6</link>
      <guid>https://dev.to/a95yman/i-was-a-net-developer-then-my-company-told-me-to-learn-android-3od6</guid>
      <description>&lt;h3&gt;
  
  
  Java got me into Android development. Kotlin made me stay. Years later, I still build Android apps for fun.
&lt;/h3&gt;

&lt;p&gt;I did not start my career wanting to become an Android developer.&lt;/p&gt;

&lt;p&gt;For most of my professional life, I was the .NET guy.&lt;/p&gt;

&lt;p&gt;C#, business applications, databases, internal systems, desktop software, APIs. That was the world I knew well.&lt;/p&gt;

&lt;p&gt;Then one day, the company I was working for needed an Android application.&lt;/p&gt;

&lt;p&gt;There was one small problem.&lt;/p&gt;

&lt;p&gt;I did not know Android development.&lt;/p&gt;

&lt;p&gt;And at the time, Android meant Java.&lt;/p&gt;

&lt;p&gt;So I had to learn it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going from C# to Java
&lt;/h2&gt;

&lt;p&gt;Coming from .NET, Java felt familiar enough that I could get moving quickly.&lt;/p&gt;

&lt;p&gt;Classes looked familiar.&lt;/p&gt;

&lt;p&gt;Interfaces looked familiar.&lt;/p&gt;

&lt;p&gt;Object-oriented programming was still object-oriented programming.&lt;/p&gt;

&lt;p&gt;But Android itself was completely new territory.&lt;/p&gt;

&lt;p&gt;Activities.&lt;/p&gt;

&lt;p&gt;Fragments.&lt;/p&gt;

&lt;p&gt;XML layouts.&lt;/p&gt;

&lt;p&gt;The Android lifecycle.&lt;/p&gt;

&lt;p&gt;Permissions.&lt;/p&gt;

&lt;p&gt;Adapters.&lt;/p&gt;

&lt;p&gt;Intents.&lt;/p&gt;

&lt;p&gt;Gradle.&lt;/p&gt;

&lt;p&gt;Suddenly, building a button was the easy part. Understanding everything happening around that button was the interesting part.&lt;/p&gt;

&lt;p&gt;I remember spending a lot of time trying to understand why an application behaved one way when I launched it normally and another way after Android recreated an activity.&lt;/p&gt;

&lt;p&gt;Coming from desktop development, that took some adjustment.&lt;/p&gt;

&lt;p&gt;But something unexpected happened.&lt;/p&gt;

&lt;p&gt;I started enjoying it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Android felt different
&lt;/h2&gt;

&lt;p&gt;Most of the software I had built professionally was business software.&lt;/p&gt;

&lt;p&gt;CRM systems.&lt;/p&gt;

&lt;p&gt;Financial applications.&lt;/p&gt;

&lt;p&gt;Reporting systems.&lt;/p&gt;

&lt;p&gt;Automation tools.&lt;/p&gt;

&lt;p&gt;Software designed to solve operational problems.&lt;/p&gt;

&lt;p&gt;I still enjoy building those systems. In fact, they remain a big part of what I do today.&lt;/p&gt;

&lt;p&gt;But Android development scratched a different itch.&lt;/p&gt;

&lt;p&gt;You build something, install it on a phone, tap the icon, and suddenly your software feels like a physical thing.&lt;/p&gt;

&lt;p&gt;It lives in your pocket.&lt;/p&gt;

&lt;p&gt;You swipe through it.&lt;/p&gt;

&lt;p&gt;You touch it.&lt;/p&gt;

&lt;p&gt;You immediately notice whether an interaction feels smooth or annoying.&lt;/p&gt;

&lt;p&gt;That feedback loop is addictive.&lt;/p&gt;

&lt;p&gt;Android development slowly became something I enjoyed doing even when nobody was asking me to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then Kotlin showed up
&lt;/h2&gt;

&lt;p&gt;Eventually, Android development started moving toward Kotlin.&lt;/p&gt;

&lt;p&gt;At first, I was skeptical.&lt;/p&gt;

&lt;p&gt;Java worked.&lt;/p&gt;

&lt;p&gt;I already knew Java.&lt;/p&gt;

&lt;p&gt;Why introduce another language?&lt;/p&gt;

&lt;p&gt;Then I actually started using Kotlin.&lt;/p&gt;

&lt;p&gt;And my position changed pretty quickly.&lt;/p&gt;

&lt;p&gt;Kotlin removed a surprising amount of ceremony.&lt;/p&gt;

&lt;p&gt;Null safety was better.&lt;/p&gt;

&lt;p&gt;Data classes were convenient.&lt;/p&gt;

&lt;p&gt;Extension functions were useful.&lt;/p&gt;

&lt;p&gt;The syntax was cleaner.&lt;/p&gt;

&lt;p&gt;Coroutines eventually made asynchronous code much nicer to work with.&lt;/p&gt;

&lt;p&gt;Going back to Java after spending enough time with Kotlin started feeling unnecessarily verbose.&lt;/p&gt;

&lt;p&gt;Today, if I am starting an Android project, Kotlin is the obvious choice for me.&lt;/p&gt;

&lt;p&gt;And once Jetpack Compose matured, Android development became even more enjoyable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jetpack Compose changed the experience again
&lt;/h2&gt;

&lt;p&gt;One thing I never particularly loved about traditional Android development was constantly jumping between XML layouts and Java or Kotlin code.&lt;/p&gt;

&lt;p&gt;Compose changed that dynamic.&lt;/p&gt;

&lt;p&gt;Building UI directly in Kotlin feels much closer to the way I naturally think about an interface.&lt;/p&gt;

&lt;p&gt;A screen becomes a composition of components.&lt;/p&gt;

&lt;p&gt;State changes.&lt;/p&gt;

&lt;p&gt;The UI reacts.&lt;/p&gt;

&lt;p&gt;You iterate quickly.&lt;/p&gt;

&lt;p&gt;For someone who has spent years building web applications, desktop applications, and business software, Compose feels surprisingly comfortable.&lt;/p&gt;

&lt;p&gt;It also made Android one of those technologies I regularly come back to simply because I want to build something.&lt;/p&gt;

&lt;p&gt;Not because a client requested it.&lt;/p&gt;

&lt;p&gt;Not because my employer needs it.&lt;/p&gt;

&lt;p&gt;Just because it is fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  My latest Android side project
&lt;/h2&gt;

&lt;p&gt;Recently, I wanted to build a resume builder.&lt;/p&gt;

&lt;p&gt;Nothing revolutionary.&lt;/p&gt;

&lt;p&gt;Just a focused Android application that lets someone create a professional resume without needing an account, a browser, or a complicated setup.&lt;/p&gt;

&lt;p&gt;I started with a simple idea.&lt;/p&gt;

&lt;p&gt;The user should open the app and immediately understand what to do.&lt;/p&gt;

&lt;p&gt;So instead of one giant form, I broke resume creation into steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Personal details&lt;/li&gt;
&lt;li&gt;Professional summary&lt;/li&gt;
&lt;li&gt;Work experience&lt;/li&gt;
&lt;li&gt;Education&lt;/li&gt;
&lt;li&gt;Skills and additional information&lt;/li&gt;
&lt;li&gt;Template selection&lt;/li&gt;
&lt;li&gt;Preview and PDF export&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also jump directly between sections instead of repeatedly pressing Next.&lt;/p&gt;

&lt;p&gt;That small detail matters more than it sounds.&lt;/p&gt;

&lt;p&gt;Once a resume already exists, users usually know exactly what they want to change.&lt;/p&gt;

&lt;p&gt;They should not have to weave through five screens just to edit their education.&lt;/p&gt;

&lt;h2&gt;
  
  
  The PDF part became the interesting problem
&lt;/h2&gt;

&lt;p&gt;The editor itself was straightforward.&lt;/p&gt;

&lt;p&gt;The PDF renderer was where things became more interesting.&lt;/p&gt;

&lt;p&gt;A resume looks simple until you have to generate one dynamically.&lt;/p&gt;

&lt;p&gt;What happens when an experience description is too long?&lt;/p&gt;

&lt;p&gt;What happens when a section starts at the bottom of the page?&lt;/p&gt;

&lt;p&gt;Do you split an education entry between two pages?&lt;/p&gt;

&lt;p&gt;How do you make the preview match the exported PDF?&lt;/p&gt;

&lt;p&gt;How much spacing should exist between sections?&lt;/p&gt;

&lt;p&gt;How do you wrap text based on its actual rendered width instead of guessing based on character count?&lt;/p&gt;

&lt;p&gt;Those details compound quickly.&lt;/p&gt;

&lt;p&gt;I ended up building pagination directly into the PDF renderer so longer resumes can naturally continue onto additional pages.&lt;/p&gt;

&lt;p&gt;The preview is also rendered from the same PDF engine used for export.&lt;/p&gt;

&lt;p&gt;That means the preview is not pretending to represent the final document.&lt;/p&gt;

&lt;p&gt;It is the final document.&lt;/p&gt;

&lt;h2&gt;
  
  
  I also wanted two very different resume styles
&lt;/h2&gt;

&lt;p&gt;The app currently has two templates.&lt;/p&gt;

&lt;p&gt;The first is a clean ATS-oriented resume.&lt;/p&gt;

&lt;p&gt;Simple structure.&lt;/p&gt;

&lt;p&gt;Easy to scan.&lt;/p&gt;

&lt;p&gt;Traditional presentation.&lt;/p&gt;

&lt;p&gt;The second is the one I enjoyed building the most.&lt;/p&gt;

&lt;p&gt;It is a two-column design with a blue sidebar containing contact details, skills, languages, and certificates.&lt;/p&gt;

&lt;p&gt;The main area contains the summary, experience, and education.&lt;/p&gt;

&lt;p&gt;Getting that layout to paginate properly was much more interesting than simply drawing a nice-looking page.&lt;/p&gt;

&lt;p&gt;A template can look great with perfect demo data and completely fall apart once a real user enters twice as much content.&lt;/p&gt;

&lt;p&gt;That is the part of development screenshots rarely show.&lt;/p&gt;

&lt;h2&gt;
  
  
  The app became something I wanted to release
&lt;/h2&gt;

&lt;p&gt;Originally, this was another Android project I was building because I enjoy Android development.&lt;/p&gt;

&lt;p&gt;But once it reached the point where it had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local resume storage&lt;/li&gt;
&lt;li&gt;Automatic saving&lt;/li&gt;
&lt;li&gt;Multiple resumes&lt;/li&gt;
&lt;li&gt;Resume duplication&lt;/li&gt;
&lt;li&gt;ATS and two-column templates&lt;/li&gt;
&lt;li&gt;PDF preview&lt;/li&gt;
&lt;li&gt;Automatic text wrapping&lt;/li&gt;
&lt;li&gt;Multi-page PDF export&lt;/li&gt;
&lt;li&gt;AdMob integration&lt;/li&gt;
&lt;li&gt;A proper guided editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I realized there was no reason to leave it sitting in one of my project folders.&lt;/p&gt;

&lt;p&gt;So I packaged the complete Android Studio project.&lt;/p&gt;

&lt;p&gt;The source code is now available as &lt;strong&gt;Resume Builder Premium&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you are an Android developer, indie developer, or someone learning Kotlin and Jetpack Compose, you can use it as a starting point instead of rebuilding the entire foundation yourself.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://yaman95.gumroad.com/l/resume-builder-premium" rel="noopener noreferrer"&gt;Resume Builder Premium Android Source Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is built with Kotlin, Jetpack Compose, Material 3, local JSON persistence, Android's PDF APIs, and Google Mobile Ads.&lt;/p&gt;

&lt;p&gt;The idea is simple.&lt;/p&gt;

&lt;p&gt;Take the working foundation, change the branding, customize the templates, replace the AdMob IDs, and go from there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I still build Android apps
&lt;/h2&gt;

&lt;p&gt;Android development is not my only area of software development.&lt;/p&gt;

&lt;p&gt;Far from it.&lt;/p&gt;

&lt;p&gt;I have spent more than a decade working with software, particularly .NET, Python, business applications, financial systems, automation, APIs, databases, and reporting tools.&lt;/p&gt;

&lt;p&gt;But Android has remained one of those things I genuinely enjoy.&lt;/p&gt;

&lt;p&gt;There is something satisfying about watching an application go from an empty project to something you can hold in your hand.&lt;/p&gt;

&lt;p&gt;Maybe that is why I keep coming back to it.&lt;/p&gt;

&lt;p&gt;I originally learned Android because a company needed me to.&lt;/p&gt;

&lt;p&gt;I kept building Android apps because I liked it.&lt;/p&gt;

&lt;p&gt;Sometimes your employer pushing you outside your normal stack ends up introducing you to something you would never have pursued on your own.&lt;/p&gt;

&lt;p&gt;That happened to me with Android.&lt;/p&gt;

&lt;p&gt;And I am pretty glad it did.&lt;/p&gt;

&lt;h2&gt;
  
  
  About me
&lt;/h2&gt;

&lt;p&gt;I'm &lt;strong&gt;Ayman Atif&lt;/strong&gt;, a software engineer focused on building practical software for businesses.&lt;/p&gt;

&lt;p&gt;Over the years, I've worked on business applications, CRM systems, financial and reporting software, automation tools, APIs, and mobile applications using technologies including .NET, Python, Kotlin, and Java.&lt;/p&gt;

&lt;p&gt;If you'd like to see more of my work, projects, and what I build:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://ayman-atif.vercel.app/" rel="noopener noreferrer"&gt;Visit my software engineering portfolio&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if you are interested in the Android project discussed in this article:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://yaman95.gumroad.com/l/resume-builder-premium" rel="noopener noreferrer"&gt;Get Resume Builder Premium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ll probably keep building Android apps whether they become products or not.&lt;/p&gt;

&lt;p&gt;At this point, it is partly software development and partly a hobby.&lt;/p&gt;

&lt;p&gt;And those are usually the projects I have the most fun building.&lt;/p&gt;

</description>
      <category>androiddev</category>
      <category>career</category>
      <category>kotlin</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Ayman Atif: How I Build Software Around Business Problems</title>
      <dc:creator>Ayman Atif</dc:creator>
      <pubDate>Tue, 08 Sep 2026 17:17:03 +0000</pubDate>
      <link>https://dev.to/a95yman/ayman-atif-how-i-build-software-around-business-problems-359g</link>
      <guid>https://dev.to/a95yman/ayman-atif-how-i-build-software-around-business-problems-359g</guid>
      <description>&lt;p&gt;I'm &lt;strong&gt;Ayman Atif&lt;/strong&gt;, a freelance .NET and Python software engineer.&lt;/p&gt;

&lt;p&gt;I've been building software since 2014, and over the years I've learned something that changed how I approach development:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Businesses don't really need more code. They need their problems solved.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A company rarely says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“We need an ASP.NET Core API.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They usually say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“We're still doing this manually in Excel.”&lt;/p&gt;

&lt;p&gt;“Our application has become painfully slow.”&lt;/p&gt;

&lt;p&gt;“Nobody understands this old codebase anymore.”&lt;/p&gt;

&lt;p&gt;“Every change seems to break something else.”&lt;/p&gt;

&lt;p&gt;“We need to automate this process.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are the problems I enjoy solving.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I do as a freelance software engineer
&lt;/h2&gt;

&lt;p&gt;My work focuses on &lt;strong&gt;business software development, .NET development, Python development, and business process automation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I work with businesses that need someone who can understand the problem, plan the solution, build it, and stay involved after deployment.&lt;/p&gt;

&lt;p&gt;That can mean building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business web applications&lt;/li&gt;
&lt;li&gt;Backend systems and APIs&lt;/li&gt;
&lt;li&gt;Internal tools&lt;/li&gt;
&lt;li&gt;Dashboards&lt;/li&gt;
&lt;li&gt;Automation systems&lt;/li&gt;
&lt;li&gt;Data processing pipelines&lt;/li&gt;
&lt;li&gt;Document workflows&lt;/li&gt;
&lt;li&gt;PDF and Excel processing&lt;/li&gt;
&lt;li&gt;Database-driven applications&lt;/li&gt;
&lt;li&gt;Existing software improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My main technologies include &lt;strong&gt;C#, .NET, ASP.NET Core, Python, Flask, Django, SQL, JavaScript, and REST APIs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But technology is usually not where the project starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  I start with the business problem
&lt;/h2&gt;

&lt;p&gt;One thing I've become increasingly deliberate about is avoiding the temptation to code immediately.&lt;/p&gt;

&lt;p&gt;Before writing the first feature, I want to understand:&lt;/p&gt;

&lt;p&gt;What is the business trying to accomplish?&lt;/p&gt;

&lt;p&gt;Who uses the system?&lt;/p&gt;

&lt;p&gt;What is currently taking too much time?&lt;/p&gt;

&lt;p&gt;Where do mistakes happen?&lt;/p&gt;

&lt;p&gt;What happens when something goes wrong?&lt;/p&gt;

&lt;p&gt;Which parts of the existing system actually need to change?&lt;/p&gt;

&lt;p&gt;And perhaps most importantly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What problem are we really trying to solve?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes the answer is a new application.&lt;/p&gt;

&lt;p&gt;Sometimes it's an automation workflow.&lt;/p&gt;

&lt;p&gt;Sometimes it's a database optimization.&lt;/p&gt;

&lt;p&gt;Sometimes it's a relatively small change to an existing system.&lt;/p&gt;

&lt;p&gt;And sometimes the right answer is &lt;strong&gt;not&lt;/strong&gt; a rewrite.&lt;/p&gt;

&lt;p&gt;That's an important distinction when you're working on production software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building business software is different from building a demo
&lt;/h2&gt;

&lt;p&gt;A demo can work perfectly with three records.&lt;/p&gt;

&lt;p&gt;Production software has to deal with reality.&lt;/p&gt;

&lt;p&gt;Users make unexpected decisions.&lt;/p&gt;

&lt;p&gt;Data is messy.&lt;/p&gt;

&lt;p&gt;Imports are imperfect.&lt;/p&gt;

&lt;p&gt;Multiple people can modify the same information.&lt;/p&gt;

&lt;p&gt;Servers have limited resources.&lt;/p&gt;

&lt;p&gt;Requirements change.&lt;/p&gt;

&lt;p&gt;And suddenly a feature that looked simple on paper becomes an engineering problem.&lt;/p&gt;

&lt;p&gt;I've worked on production business software involving financial analysis, document generation, confidential information, controlled sharing, spreadsheet and PDF processing, imports, exports, and complex business workflows.&lt;/p&gt;

&lt;p&gt;The interesting engineering wasn't simply choosing a framework.&lt;/p&gt;

&lt;p&gt;It was making the system &lt;strong&gt;reliable when things stopped being simple&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real example: improving an existing business system
&lt;/h2&gt;

&lt;p&gt;One production platform I worked on combined financial analysis, document drafting, sharing, exports, and deal workflows.&lt;/p&gt;

&lt;p&gt;It had been built for real business use and continued evolving for years.&lt;/p&gt;

&lt;p&gt;That meant dealing with things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Legacy imports&lt;/li&gt;
&lt;li&gt;Shared document state&lt;/li&gt;
&lt;li&gt;Permission-aware workflows&lt;/li&gt;
&lt;li&gt;PDF generation&lt;/li&gt;
&lt;li&gt;Spreadsheet processing&lt;/li&gt;
&lt;li&gt;Print-ready documents&lt;/li&gt;
&lt;li&gt;Performance constraints&lt;/li&gt;
&lt;li&gt;Database access&lt;/li&gt;
&lt;li&gt;Production deployment&lt;/li&gt;
&lt;li&gt;Ongoing maintenance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At one point, limited server resources exposed performance problems that weren't obvious from looking at individual features.&lt;/p&gt;

&lt;p&gt;The solution wasn't simply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Buy a bigger server.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The system needed to be understood as a whole.&lt;/p&gt;

&lt;p&gt;Application behavior, concurrency, data access, architecture, and infrastructure all mattered.&lt;/p&gt;

&lt;p&gt;That's the kind of problem I like working on.&lt;/p&gt;

&lt;h2&gt;
  
  
  I also build automation
&lt;/h2&gt;

&lt;p&gt;Another area I focus on is &lt;strong&gt;business process automation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A surprising amount of business work still looks like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spreadsheet → copy/paste → email → another spreadsheet → manual verification → repeat&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is a good candidate for automation.&lt;/p&gt;

&lt;p&gt;For example, I built &lt;strong&gt;InvoiceFlow&lt;/strong&gt;, a Python toolkit that converts PDF invoices into structured invoice data and clean Excel workbooks.&lt;/p&gt;

&lt;p&gt;The workflow is straightforward:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PDF invoices → extraction → structured data → Excel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But reliable automation requires more than making the happy path work.&lt;/p&gt;

&lt;p&gt;You need validation.&lt;/p&gt;

&lt;p&gt;You need error handling.&lt;/p&gt;

&lt;p&gt;You need logging.&lt;/p&gt;

&lt;p&gt;You need to think about larger workloads.&lt;/p&gt;

&lt;p&gt;You need predictable output.&lt;/p&gt;

&lt;p&gt;And you need a system that another developer can understand six months later.&lt;/p&gt;

&lt;p&gt;That's why I think good automation is less about “using Python” and more about &lt;strong&gt;turning a messy manual process into a repeatable system people can trust&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  My approach to software projects
&lt;/h2&gt;

&lt;p&gt;My process is deliberately simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discuss → Challenge → Plan → Build → Deploy → Maintain&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, I understand the business problem.&lt;/p&gt;

&lt;p&gt;Then I challenge assumptions where necessary.&lt;/p&gt;

&lt;p&gt;Then we agree on the architecture, workflow, scope, and tradeoffs.&lt;/p&gt;

&lt;p&gt;Then I build.&lt;/p&gt;

&lt;p&gt;After that, I deploy the system and remain available for improvements and maintenance.&lt;/p&gt;

&lt;p&gt;I prefer this approach because software decisions compound.&lt;/p&gt;

&lt;p&gt;A shortcut that saves two hours today can create weeks of maintenance six months later.&lt;/p&gt;

&lt;p&gt;Likewise, spending time understanding the problem before coding can prevent an entire feature from being built in the wrong direction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why work with me?
&lt;/h2&gt;

&lt;p&gt;I'm not trying to position myself as someone who knows every new framework.&lt;/p&gt;

&lt;p&gt;My value is elsewhere.&lt;/p&gt;

&lt;p&gt;I can take a business problem, break it down, understand the technical constraints, and turn it into software that can actually be used.&lt;/p&gt;

&lt;p&gt;I can work on a new application.&lt;/p&gt;

&lt;p&gt;I can join an existing codebase.&lt;/p&gt;

&lt;p&gt;I can investigate a performance problem.&lt;/p&gt;

&lt;p&gt;I can automate a repetitive workflow.&lt;/p&gt;

&lt;p&gt;I can help modernize software that has become difficult to maintain.&lt;/p&gt;

&lt;p&gt;And I can stay involved after the initial build.&lt;/p&gt;

&lt;p&gt;Most importantly, &lt;strong&gt;you work directly with me&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No unnecessary layers between the business problem and the engineer doing the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking for a freelance software engineer?
&lt;/h2&gt;

&lt;p&gt;I'm &lt;strong&gt;Ayman Atif&lt;/strong&gt;, a freelance &lt;strong&gt;.NET and Python software engineer available for remote work worldwide&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If your business has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a manual process that should be automated,&lt;/li&gt;
&lt;li&gt;an application that has become difficult to maintain,&lt;/li&gt;
&lt;li&gt;a slow backend,&lt;/li&gt;
&lt;li&gt;a business idea that needs a technical plan,&lt;/li&gt;
&lt;li&gt;or software that needs to be built from scratch,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd be happy to discuss it.&lt;/p&gt;

&lt;p&gt;You can see my projects, services, engineering approach, and production experience here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://ayman-atif.vercel.app/" rel="noopener noreferrer"&gt;Ayman Atif — Freelance .NET &amp;amp; Python Software Engineer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you have a software problem that you've been putting off because it looks complicated, &lt;strong&gt;let's talk about it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;— &lt;strong&gt;Ayman Atif&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>python</category>
      <category>softwareengineering</category>
      <category>freelance</category>
    </item>
    <item>
      <title>I Built a $1,500 Dashboard. I Learned a Lesson Worth More Than $1,500.</title>
      <dc:creator>Ayman Atif</dc:creator>
      <pubDate>Mon, 07 Sep 2026 14:12:54 +0000</pubDate>
      <link>https://dev.to/a95yman/i-built-a-1500-dashboard-i-learned-a-lesson-worth-more-than-1500-42n</link>
      <guid>https://dev.to/a95yman/i-built-a-1500-dashboard-i-learned-a-lesson-worth-more-than-1500-42n</guid>
      <description>&lt;p&gt;Three months.&lt;/p&gt;

&lt;p&gt;One client.&lt;/p&gt;

&lt;p&gt;A complete agency dashboard.&lt;/p&gt;

&lt;p&gt;And $200 paid out of an agreed $1,500.&lt;/p&gt;

&lt;p&gt;I didn't lose those three months because the project was technically difficult.&lt;/p&gt;

&lt;p&gt;I lost them because I approached freelancing like a developer instead of a business owner.&lt;/p&gt;

&lt;p&gt;There was no signed contract.&lt;/p&gt;

&lt;p&gt;There was no clearly documented payment schedule.&lt;/p&gt;

&lt;p&gt;And when the project was finished, I didn't push for the remaining balance.&lt;/p&gt;

&lt;p&gt;I simply moved on.&lt;/p&gt;

&lt;p&gt;A year later, I still haven't received it.&lt;/p&gt;

&lt;p&gt;Surprisingly, I'm not writing this article because I'm angry about it.&lt;/p&gt;

&lt;p&gt;I'm writing it because the experience changed how I approach freelance web development.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project
&lt;/h2&gt;

&lt;p&gt;The client ran an agency and wanted an internal dashboard to make some of their day-to-day work easier to manage.&lt;/p&gt;

&lt;p&gt;The project involved several areas of their business.&lt;/p&gt;

&lt;p&gt;There was client management.&lt;/p&gt;

&lt;p&gt;There was blog management.&lt;/p&gt;

&lt;p&gt;There was work related to SEO.&lt;/p&gt;

&lt;p&gt;And there was the usual collection of smaller workflows that appear once you start building software around an actual business.&lt;/p&gt;

&lt;p&gt;We agreed on a price of $1,500.&lt;/p&gt;

&lt;p&gt;I received $200 upfront.&lt;/p&gt;

&lt;p&gt;Then I started building.&lt;/p&gt;

&lt;p&gt;From a development perspective, this was the kind of project I enjoyed.&lt;/p&gt;

&lt;p&gt;It wasn't just a landing page or a simple CRUD application.&lt;/p&gt;

&lt;p&gt;The software had to reflect how the agency actually worked.&lt;/p&gt;

&lt;p&gt;That meant understanding their workflow, translating it into features, building the dashboard, adjusting things along the way, and making the application useful for the people who would actually use it.&lt;/p&gt;

&lt;p&gt;So I kept going.&lt;/p&gt;

&lt;p&gt;And I kept improving it.&lt;/p&gt;

&lt;p&gt;For roughly three months, I worked on the project.&lt;/p&gt;

&lt;p&gt;Eventually, the work was finished.&lt;/p&gt;

&lt;p&gt;The application existed.&lt;/p&gt;

&lt;p&gt;The features were there.&lt;/p&gt;

&lt;p&gt;The client had what we had discussed.&lt;/p&gt;

&lt;p&gt;But there was still one problem.&lt;/p&gt;

&lt;p&gt;The remaining $1,300 never arrived.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Was Too Easygoing About It
&lt;/h2&gt;

&lt;p&gt;This is the part where I could simply blame the client.&lt;/p&gt;

&lt;p&gt;But that wouldn't tell the whole story.&lt;/p&gt;

&lt;p&gt;The client was responsible for paying the agreed amount.&lt;/p&gt;

&lt;p&gt;I was also responsible for how I handled the business side of the project.&lt;/p&gt;

&lt;p&gt;I didn't sign a contract.&lt;/p&gt;

&lt;p&gt;I didn't establish a formal payment schedule.&lt;/p&gt;

&lt;p&gt;I didn't clearly define what would happen if payment was delayed.&lt;/p&gt;

&lt;p&gt;And perhaps most importantly, I didn't make payment a condition of continuing the work.&lt;/p&gt;

&lt;p&gt;I was focused on building the software.&lt;/p&gt;

&lt;p&gt;I thought:&lt;/p&gt;

&lt;p&gt;"Let's get the project done."&lt;/p&gt;

&lt;p&gt;That mindset is useful when you're trying to be a reliable developer.&lt;/p&gt;

&lt;p&gt;It's not enough when you're running a freelance business.&lt;/p&gt;

&lt;p&gt;Being easy to work with is good.&lt;/p&gt;

&lt;p&gt;Being so easygoing that important business details become vague is not.&lt;/p&gt;

&lt;p&gt;That's a distinction I didn't fully understand at the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Developer Mindset vs. The Business Mindset
&lt;/h2&gt;

&lt;p&gt;As developers, we're trained to think in terms of problems.&lt;/p&gt;

&lt;p&gt;A client has a problem.&lt;/p&gt;

&lt;p&gt;We come up with a solution.&lt;/p&gt;

&lt;p&gt;We build it.&lt;/p&gt;

&lt;p&gt;We test it.&lt;/p&gt;

&lt;p&gt;We fix bugs.&lt;/p&gt;

&lt;p&gt;We deliver it.&lt;/p&gt;

&lt;p&gt;That's the part we naturally focus on.&lt;/p&gt;

&lt;p&gt;But freelance development has another layer.&lt;/p&gt;

&lt;p&gt;There is scope.&lt;/p&gt;

&lt;p&gt;There are milestones.&lt;/p&gt;

&lt;p&gt;There are payments.&lt;/p&gt;

&lt;p&gt;There are approvals.&lt;/p&gt;

&lt;p&gt;There are deadlines.&lt;/p&gt;

&lt;p&gt;There are responsibilities on both sides.&lt;/p&gt;

&lt;p&gt;None of these have much to do with whether you can write good code.&lt;/p&gt;

&lt;p&gt;But they can determine whether a freelance project is actually successful.&lt;/p&gt;

&lt;p&gt;That was the counterintuitive part for me.&lt;/p&gt;

&lt;p&gt;I used to think that being professional mostly meant doing excellent work and being dependable.&lt;/p&gt;

&lt;p&gt;It does.&lt;/p&gt;

&lt;p&gt;But professionalism also means making expectations clear.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Didn't Need a Complicated System
&lt;/h2&gt;

&lt;p&gt;Looking back, I didn't need some sophisticated legal or financial system.&lt;/p&gt;

&lt;p&gt;I needed basic structure.&lt;/p&gt;

&lt;p&gt;Before starting the project, I should have had a written agreement covering things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What exactly I was building&lt;/li&gt;
&lt;li&gt;What was outside the scope&lt;/li&gt;
&lt;li&gt;The total project price&lt;/li&gt;
&lt;li&gt;The payment schedule&lt;/li&gt;
&lt;li&gt;What the upfront payment covered&lt;/li&gt;
&lt;li&gt;When the remaining balance was due&lt;/li&gt;
&lt;li&gt;How additional work would be handled&lt;/li&gt;
&lt;li&gt;What happened if the project was paused&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this has to make a client relationship cold or transactional.&lt;/p&gt;

&lt;p&gt;In fact, I think the opposite is true.&lt;/p&gt;

&lt;p&gt;Clear expectations make collaboration easier.&lt;/p&gt;

&lt;p&gt;When both sides know what they agreed to, there's less room for confusion later.&lt;/p&gt;

&lt;h2&gt;
  
  
  The $200 Changed How I Look at Upfront Payments
&lt;/h2&gt;

&lt;p&gt;The $200 upfront payment was important for another reason.&lt;/p&gt;

&lt;p&gt;It showed that the client was willing to invest in the project.&lt;/p&gt;

&lt;p&gt;But it wasn't enough to protect me from continuing too far without another payment milestone.&lt;/p&gt;

&lt;p&gt;If I were handling the same project today, I would structure the payments around the work.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initial payment → project begins&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Milestone payment → major functionality completed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final payment → final delivery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The exact percentages aren't the important part.&lt;/p&gt;

&lt;p&gt;The principle is.&lt;/p&gt;

&lt;p&gt;Don't let the entire financial risk sit on one side of the relationship.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Also Learned Not to Confuse Kindness With Avoiding Difficult Conversations
&lt;/h2&gt;

&lt;p&gt;This was probably the hardest lesson.&lt;/p&gt;

&lt;p&gt;I didn't confront the situation.&lt;/p&gt;

&lt;p&gt;Not because I thought the remaining payment was unimportant.&lt;/p&gt;

&lt;p&gt;I just didn't want to create conflict.&lt;/p&gt;

&lt;p&gt;So I stayed quiet.&lt;/p&gt;

&lt;p&gt;Eventually, enough time passed that I stopped thinking about it.&lt;/p&gt;

&lt;p&gt;A year later, the project is simply something I remember as an expensive lesson.&lt;/p&gt;

&lt;p&gt;And honestly, I'm okay with that.&lt;/p&gt;

&lt;p&gt;I would rather take the lesson than keep resentment over the money.&lt;/p&gt;

&lt;p&gt;But if I could go back, I would handle the conversation differently.&lt;/p&gt;

&lt;p&gt;Being respectful doesn't mean avoiding uncomfortable conversations.&lt;/p&gt;

&lt;p&gt;You can be polite and still be assertive.&lt;/p&gt;

&lt;p&gt;You can value the relationship and still set a boundary.&lt;/p&gt;

&lt;p&gt;You can be flexible without making the agreement one-sided.&lt;/p&gt;

&lt;p&gt;That's something I understand much better now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project Still Taught Me Something Technically
&lt;/h2&gt;

&lt;p&gt;It's easy to focus on the unpaid balance and forget the actual development experience.&lt;/p&gt;

&lt;p&gt;But the project itself was valuable.&lt;/p&gt;

&lt;p&gt;I got to work closely with an agency and build software around its internal workflow.&lt;/p&gt;

&lt;p&gt;I worked on client management.&lt;/p&gt;

&lt;p&gt;I worked on content and blog-related functionality.&lt;/p&gt;

&lt;p&gt;I was involved in SEO-related work.&lt;/p&gt;

&lt;p&gt;And I learned more about how businesses actually use software than I would have from another isolated personal project.&lt;/p&gt;

&lt;p&gt;That's one reason I don't consider those three months completely wasted.&lt;/p&gt;

&lt;p&gt;The money was never recovered.&lt;/p&gt;

&lt;p&gt;The experience was.&lt;/p&gt;

&lt;p&gt;And I still use what I learned from it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd Do Differently Today
&lt;/h2&gt;

&lt;p&gt;If I started the same project today, my approach would be different.&lt;/p&gt;

&lt;p&gt;I'd still listen carefully to the client.&lt;/p&gt;

&lt;p&gt;I'd still try to understand the business before writing the first feature.&lt;/p&gt;

&lt;p&gt;I'd still go out of my way to make the software useful.&lt;/p&gt;

&lt;p&gt;But I'd also make the business side explicit from the beginning.&lt;/p&gt;

&lt;p&gt;I'd document the scope.&lt;/p&gt;

&lt;p&gt;I'd agree on milestones.&lt;/p&gt;

&lt;p&gt;I'd use written communication for important decisions.&lt;/p&gt;

&lt;p&gt;I'd make payment expectations clear.&lt;/p&gt;

&lt;p&gt;And I'd stop treating conversations about money as something separate from professionalism.&lt;/p&gt;

&lt;p&gt;Because they're not.&lt;/p&gt;

&lt;p&gt;If you're providing a professional service, getting paid is part of the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lesson Was Worth More Than $1,500
&lt;/h2&gt;

&lt;p&gt;I didn't get the remaining $1,300.&lt;/p&gt;

&lt;p&gt;I can't go back and change that.&lt;/p&gt;

&lt;p&gt;But I can make sure I don't repeat the same mistake.&lt;/p&gt;

&lt;p&gt;The biggest lesson wasn't "don't trust clients."&lt;/p&gt;

&lt;p&gt;It wasn't "always expect people to avoid paying."&lt;/p&gt;

&lt;p&gt;And it definitely wasn't "be difficult to work with."&lt;/p&gt;

&lt;p&gt;It was much simpler:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good relationships need clear expectations.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A good client relationship isn't built by one person constantly being flexible.&lt;/p&gt;

&lt;p&gt;It works when both sides understand their responsibilities and respect them.&lt;/p&gt;

&lt;p&gt;That's reciprocity.&lt;/p&gt;

&lt;p&gt;And that's something I wish I'd understood earlier.&lt;/p&gt;

&lt;p&gt;Today, when I build software for a client, I think about more than whether the feature works.&lt;/p&gt;

&lt;p&gt;I think about whether the scope is clear.&lt;/p&gt;

&lt;p&gt;Whether expectations are documented.&lt;/p&gt;

&lt;p&gt;Whether both sides know what happens next.&lt;/p&gt;

&lt;p&gt;And whether I'm taking care of my responsibilities as both a developer and a business owner.&lt;/p&gt;

&lt;p&gt;Because becoming a better freelance developer isn't only about writing better code.&lt;/p&gt;

&lt;p&gt;Sometimes, it's about learning when to stop coding, have the conversation, and protect the work you've already done.&lt;/p&gt;

&lt;p&gt;That lesson cost me $1,300.&lt;/p&gt;

&lt;p&gt;I think it was worth learning.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&amp;gt; I'm Ayman Atif, a backend engineer and full-stack developer building production-ready web apps and tools. You can explore my work and latest projects at &lt;a href="https://ayman-atif.vercel.app/" rel="noopener noreferrer"&gt;ayman-atif.vercel.app&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>freelance</category>
      <category>webdev</category>
      <category>career</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Feature Worked. Then the Business Grew.</title>
      <dc:creator>Ayman Atif</dc:creator>
      <pubDate>Fri, 04 Sep 2026 12:35:45 +0000</pubDate>
      <link>https://dev.to/a95yman/the-feature-worked-then-the-business-grew-42i2</link>
      <guid>https://dev.to/a95yman/the-feature-worked-then-the-business-grew-42i2</guid>
      <description>&lt;p&gt;I’m Ayman Atif, a freelance software engineer focused on business software, backend systems, automation, and applications that have to survive real-world use.&lt;/p&gt;

&lt;p&gt;A lot of my work starts with a deceptively simple sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The application works, but something is becoming a problem.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes it is performance.&lt;/p&gt;

&lt;p&gt;Sometimes it is a workflow that still depends on spreadsheets.&lt;/p&gt;

&lt;p&gt;Sometimes a codebase has become difficult to change without breaking something else.&lt;/p&gt;

&lt;p&gt;And sometimes the application works perfectly well in development, but production tells a different story.&lt;/p&gt;

&lt;p&gt;One of the most interesting examples I’ve worked on started with something that didn’t look like a performance problem at all.&lt;/p&gt;

&lt;p&gt;It was a business application.&lt;/p&gt;

&lt;p&gt;The users needed to work with a lot of data, switch between different sections quickly, edit records, generate documents, process financial information, and keep several parts of their workflow open at the same time.&lt;/p&gt;

&lt;p&gt;The application worked.&lt;/p&gt;

&lt;p&gt;Until it didn’t feel fast anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  The deceptive phase of a successful application
&lt;/h2&gt;

&lt;p&gt;There is a counterintuitive stage in software development where an application becomes a victim of its own success.&lt;/p&gt;

&lt;p&gt;At the beginning, everything looks reasonable.&lt;/p&gt;

&lt;p&gt;A database contains a few hundred records.&lt;/p&gt;

&lt;p&gt;Pages load quickly.&lt;/p&gt;

&lt;p&gt;Queries finish almost immediately.&lt;/p&gt;

&lt;p&gt;The server has plenty of room.&lt;/p&gt;

&lt;p&gt;Developers make decisions based on what exists today.&lt;/p&gt;

&lt;p&gt;Then the business grows.&lt;/p&gt;

&lt;p&gt;A few hundred records become thousands.&lt;/p&gt;

&lt;p&gt;Users spend more time inside the application.&lt;/p&gt;

&lt;p&gt;More tabs are opened.&lt;/p&gt;

&lt;p&gt;More documents are processed.&lt;/p&gt;

&lt;p&gt;More people interact with the same data.&lt;/p&gt;

&lt;p&gt;Nothing is necessarily “broken.”&lt;/p&gt;

&lt;p&gt;The problem is that the assumptions behind the original implementation are no longer true.&lt;/p&gt;

&lt;p&gt;That changes the equation.&lt;/p&gt;

&lt;p&gt;A query that was perfectly acceptable with 200 records might become expensive with 20,000.&lt;/p&gt;

&lt;p&gt;A page that felt instant when it loaded 50 objects might become noticeably slower when it loads thousands.&lt;/p&gt;

&lt;p&gt;A workflow that worked beautifully for one person might behave differently when several users are modifying shared state.&lt;/p&gt;

&lt;p&gt;The code didn't suddenly become bad.&lt;/p&gt;

&lt;p&gt;The environment changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The requirement that made everything harder
&lt;/h2&gt;

&lt;p&gt;One requirement in particular made the problem interesting.&lt;/p&gt;

&lt;p&gt;The users wanted the application to behave more like a desktop application.&lt;/p&gt;

&lt;p&gt;They didn't want to constantly navigate between pages.&lt;/p&gt;

&lt;p&gt;They wanted to open different sections, switch between them, keep their context, and work with large datasets directly inside grids.&lt;/p&gt;

&lt;p&gt;And in some areas, they wanted thousands of records visible without traditional pagination.&lt;/p&gt;

&lt;p&gt;From a user's perspective, that makes perfect sense.&lt;/p&gt;

&lt;p&gt;If you're working with financial or business data all day, constantly clicking through pages can become friction.&lt;/p&gt;

&lt;p&gt;You want to search, sort, inspect, edit, and move on.&lt;/p&gt;

&lt;p&gt;But every convenient interaction has a cost somewhere else.&lt;/p&gt;

&lt;p&gt;The browser has work to do.&lt;/p&gt;

&lt;p&gt;The server has work to do.&lt;/p&gt;

&lt;p&gt;The database has work to do.&lt;/p&gt;

&lt;p&gt;And memory has to go somewhere.&lt;/p&gt;

&lt;p&gt;The more desktop-like the web application becomes, the more important it is to understand what is actually happening underneath the interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  I stopped looking at the page
&lt;/h2&gt;

&lt;p&gt;The first instinct when a page becomes slow is often to look at the page.&lt;/p&gt;

&lt;p&gt;Maybe the JavaScript is inefficient.&lt;/p&gt;

&lt;p&gt;Maybe the rendering is expensive.&lt;/p&gt;

&lt;p&gt;Maybe the browser is struggling.&lt;/p&gt;

&lt;p&gt;Those things can certainly happen.&lt;/p&gt;

&lt;p&gt;But I learned to resist fixing the first thing that looks suspicious.&lt;/p&gt;

&lt;p&gt;Instead, I started following the entire path.&lt;/p&gt;

&lt;p&gt;Database.&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;p&gt;Backend.&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;p&gt;Serialization.&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;p&gt;Network.&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;p&gt;Browser.&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;p&gt;DOM.&lt;/p&gt;

&lt;p&gt;↓&lt;/p&gt;

&lt;p&gt;User interaction.&lt;/p&gt;

&lt;p&gt;That sounds obvious, but it changes how you investigate a performance problem.&lt;/p&gt;

&lt;p&gt;If you only look at the frontend, you can spend hours optimizing something that represents a small percentage of the actual problem.&lt;/p&gt;

&lt;p&gt;The same is true in reverse.&lt;/p&gt;

&lt;p&gt;A database query might be fast in isolation while the application still feels slow because too much data is being transferred, processed, or rendered afterward.&lt;/p&gt;

&lt;p&gt;Performance is a chain.&lt;/p&gt;

&lt;p&gt;The user experiences the slowest part of that chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  More data exposed the real problem
&lt;/h2&gt;

&lt;p&gt;As the amount of data increased, some operations that had previously been invisible became measurable.&lt;/p&gt;

&lt;p&gt;Queries mattered more.&lt;/p&gt;

&lt;p&gt;Object loading mattered more.&lt;/p&gt;

&lt;p&gt;Serialization mattered more.&lt;/p&gt;

&lt;p&gt;Browser rendering mattered more.&lt;/p&gt;

&lt;p&gt;Memory usage mattered more.&lt;/p&gt;

&lt;p&gt;And suddenly, “just load the records” wasn't a harmless instruction anymore.&lt;/p&gt;

&lt;p&gt;Every record had a cost.&lt;/p&gt;

&lt;p&gt;Every relationship had a cost.&lt;/p&gt;

&lt;p&gt;Every extra field had a cost.&lt;/p&gt;

&lt;p&gt;Every duplicated piece of state had a cost.&lt;/p&gt;

&lt;p&gt;This is one of the lessons I now try to keep in mind when designing business applications:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Data volume is part of the architecture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It shouldn't be treated as something that will magically take care of itself later.&lt;/p&gt;

&lt;p&gt;If an application is expected to grow, the question isn't only:&lt;/p&gt;

&lt;p&gt;“How do we make this work?”&lt;/p&gt;

&lt;p&gt;It is also:&lt;/p&gt;

&lt;p&gt;“What happens when this becomes ten times larger?”&lt;/p&gt;

&lt;h2&gt;
  
  
  The server has a vote too
&lt;/h2&gt;

&lt;p&gt;There was another constraint that made the problem more interesting: the server wasn't unlimited.&lt;/p&gt;

&lt;p&gt;The application had to operate within a relatively small amount of memory.&lt;/p&gt;

&lt;p&gt;That changes how you think about architecture.&lt;/p&gt;

&lt;p&gt;You can't simply throw more infrastructure at every problem.&lt;/p&gt;

&lt;p&gt;Sometimes the right answer is optimization.&lt;/p&gt;

&lt;p&gt;Sometimes it is changing when data is loaded.&lt;/p&gt;

&lt;p&gt;Sometimes it is reducing unnecessary work.&lt;/p&gt;

&lt;p&gt;Sometimes it is processing things differently.&lt;/p&gt;

&lt;p&gt;And sometimes you have to question the original design.&lt;/p&gt;

&lt;p&gt;This is where I think business software differs from many toy projects and tutorials.&lt;/p&gt;

&lt;p&gt;In a tutorial, you can say:&lt;/p&gt;

&lt;p&gt;“Let's add another server.”&lt;/p&gt;

&lt;p&gt;In production, someone has to pay for it.&lt;/p&gt;

&lt;p&gt;And even if you can afford it, more infrastructure doesn't automatically fix inefficient data access or excessive memory usage.&lt;/p&gt;

&lt;p&gt;You still need to understand the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then there was shared state
&lt;/h2&gt;

&lt;p&gt;Performance wasn't the only problem.&lt;/p&gt;

&lt;p&gt;Once multiple people are working with the same information, another category of problems appears.&lt;/p&gt;

&lt;p&gt;Who owns this change?&lt;/p&gt;

&lt;p&gt;What happens if two users edit the same thing?&lt;/p&gt;

&lt;p&gt;Which version should win?&lt;/p&gt;

&lt;p&gt;When should state be saved?&lt;/p&gt;

&lt;p&gt;What happens if the browser closes halfway through an operation?&lt;/p&gt;

&lt;p&gt;What happens if a user opens several sections and modifies information in one while another section still contains an older representation?&lt;/p&gt;

&lt;p&gt;These aren't UI questions anymore.&lt;/p&gt;

&lt;p&gt;They're system-design questions.&lt;/p&gt;

&lt;p&gt;A business application is full of shared state.&lt;/p&gt;

&lt;p&gt;That means reliability depends on more than making individual functions work correctly.&lt;/p&gt;

&lt;p&gt;You have to think about the relationships between those functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lesson I took from it
&lt;/h2&gt;

&lt;p&gt;The biggest lesson wasn't a particular optimization technique.&lt;/p&gt;

&lt;p&gt;It was a change in how I think about software.&lt;/p&gt;

&lt;p&gt;A feature doesn't exist in isolation.&lt;/p&gt;

&lt;p&gt;It exists inside a business.&lt;/p&gt;

&lt;p&gt;The business grows.&lt;/p&gt;

&lt;p&gt;The data grows.&lt;/p&gt;

&lt;p&gt;Users change their behavior.&lt;/p&gt;

&lt;p&gt;Requirements evolve.&lt;/p&gt;

&lt;p&gt;Infrastructure has limits.&lt;/p&gt;

&lt;p&gt;And eventually, assumptions that looked completely reasonable during development are challenged by reality.&lt;/p&gt;

&lt;p&gt;That's why I prefer investigating a system before proposing a rewrite.&lt;/p&gt;

&lt;p&gt;When something becomes slow, fragile, or difficult to maintain, the answer isn't automatically “replace it.”&lt;/p&gt;

&lt;p&gt;First, understand it.&lt;/p&gt;

&lt;p&gt;Find where the real constraint is.&lt;/p&gt;

&lt;p&gt;Measure what is actually happening.&lt;/p&gt;

&lt;p&gt;Then change the smallest thing that meaningfully improves the situation.&lt;/p&gt;

&lt;p&gt;Sometimes that leads to a refactor.&lt;/p&gt;

&lt;p&gt;Sometimes it leads to a database change.&lt;/p&gt;

&lt;p&gt;Sometimes it requires changing how data moves through the application.&lt;/p&gt;

&lt;p&gt;Sometimes the architecture itself needs to evolve.&lt;/p&gt;

&lt;p&gt;But you should know why you're making the change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Software gets interesting when it meets reality
&lt;/h2&gt;

&lt;p&gt;I've been building software since 2014, and most of the lessons that stayed with me didn't come from writing the first version of an application.&lt;/p&gt;

&lt;p&gt;They came afterward.&lt;/p&gt;

&lt;p&gt;When users started depending on it.&lt;/p&gt;

&lt;p&gt;When the database became larger.&lt;/p&gt;

&lt;p&gt;When a server had less memory than expected.&lt;/p&gt;

&lt;p&gt;When two people changed the same data.&lt;/p&gt;

&lt;p&gt;When a feature that looked simple turned out to affect five different parts of the system.&lt;/p&gt;

&lt;p&gt;That's the point where software engineering becomes less about making something work and more about making something people can continue to rely on.&lt;/p&gt;

&lt;p&gt;That's also the kind of work I enjoy most.&lt;/p&gt;

&lt;p&gt;I build and improve business applications, backend systems, automation workflows, APIs, and existing software that has reached the point where it needs careful engineering rather than another quick patch.&lt;/p&gt;

&lt;p&gt;If you're dealing with a business process that has outgrown spreadsheets, an application that has become difficult to maintain, or software that needs to become more reliable as it grows, you can find my work and get in touch with me at &lt;strong&gt;&lt;a href="https://ayman-atif.vercel.app/" rel="noopener noreferrer"&gt;ayman-atif.vercel.app&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The goal isn't just to write software.&lt;/p&gt;

&lt;p&gt;It's to build something the business can actually rely on.&lt;/p&gt;

</description>
      <category>saas</category>
      <category>webdev</category>
      <category>startup</category>
      <category>python</category>
    </item>
  </channel>
</rss>
