close

DEV Community

Cover image for What "best practice" did you quietly stop following?

What "best practice" did you quietly stop following?

Mika Flowers on October 05, 2026

Every dev picks up a pile of rules early on. Write tests first. Never commit to main. Keep functions under 20 lines. DRY everything. Comment your c...
Collapse
 
pengeszikra profile image
Peter Vivo • • Edited
  1. Coding by hand which is seems long long time to a best practice to make a program, right now I can vibe code near anything.

  2. The next best practice is the UI and mouse intensive application. I moved to the terminal handler direction, so my frequently used IDE is pure VIM. I can work in my MacBookPro terminal or my 6 years old company windows11 laptop, wsl install ubuntu |> ubuntu console ( technically windows CMD program )

  3. React |> no framework |> do not care of which programming langague are using - even I completly not familiar of them like a Go or Rust

  4. OOP |> functional programming |> minimal functional programming
    The problem with OOP is to tigh linked the data and the code. Functional programming can be unreadable very sortly like using of ramda. The big question is who would like to code by hand, I am very advice to do that at least hobby level. On your work you can use as many AI as would like to help your project.

  5. Care about money |> My advice is: don't need to care too much, the life is important!

Collapse
 
beusebiu profile image
Eusebiu Balan •

Never commit to main. Working solo, a branch per change was a review step with nobody on the other side, so small changes go straight to main now, one commit each.

I still branch for anything that stays half-built for days. A paywall experiment and guest accounts both lived on their own branch until they were ready, so main stayed shippable the whole time.

Collapse
 
dsiacci profile image
Dominique Siacci •

100% aligned with this

Collapse
 
mikachu profile image
Mika Flowers •

Mine's "make it reusable from the start."

I build the specific thing first and let it be a little messy. With Mochi, my Linux desktop pet, I got one actual pet working (its animations, moods, and little behaviors) before thinking about reuse at all.

Once it worked, I pulled the systems that had proven themselves out into their own runtime, Deskling: animation, the state machine, the event bus, movement and boundaries, dragging, scheduling. I didn't rewrite any of it from scratch. I extracted code that already worked, and by then I knew which parts deserved to be reusable because Mochi was already using them.

Where I do design for reuse now is Deskling itself, since the whole point is letting other people make pets. Community pets ship as data-only .deskling packages with no arbitrary code, so "reusable" there means "safe for strangers to share." That's a much more specific problem than "maybe I'll need this someday."

Curious if anyone went the other way and got burned by NOT abstracting early.

Collapse
 
csm18 profile image
csm •

I was looking at some parsing logic in a codebase for a simple custom format. I wanted to understand how it worked, so I decided to implement it myself.

I wrote my own version, found a few bugs, fixed them, and eventually got it working. It behaved exactly like the original, and I even tested it against the real code.

The original implementation used some efficient looping techniques. Mine was simpler, and it was actually the first time I had written something like that. Even though it worked, I kept doubting myself: Is my approach really as efficient as the original?

So I gave both versions to AI. It brutally told me that mine wasn't good practice.

I spent an entire day trying to prove that my version worked the same way. Finally, I asked the AI to compare both implementations line by line and loop by loop, with actual data.

In the end, they were doing the same thing.

That whole experience taught me something: sometimes, just because code looks different from an experienced developer's code doesn't mean it's less efficient.

Collapse
 
rahul_r15 profile image
Rahul R •

Great Article!
I’m new to Dev.to and have recently started writing about data pipelines and AI. I’ve published a few blogs so far. If you have a moment, please take a look I’d really appreciate your feedback! 😊

Collapse
 
adamthedeveloper profile image
Adam - The Developer ✨ •

Abstracting everything just because it makes the code look “cleaner,” even when the abstraction adds nothing to functionality or improves the overall developer experience.

Collapse
 
sinarezaei profile image
Sina Rezaei •

One I quietly stopped following is “abstract it early so it can be reused later.”

I used to see two similar pieces of code and immediately think they should become a shared service or utility. The problem is that similar code doesn’t always mean the same concept. I’ve had cases where two API flows looked almost identical at first, then their validation and error handling started evolving differently. The shared abstraction ended up needing flags and special cases just to keep both behaviors alive.

Now I’m fine with a little duplication until I see the same rule changing for the same reason. For example, if two endpoints both calculate pricing but one is for checkout and the other is for internal reporting, I’d rather keep them separate until the domain relationship is actually proven.

For me, DRY became less about removing repeated code and more about avoiding duplicated knowledge. The abstraction should earn its place in the architecture, not get promoted because two functions happen to look alike.

Collapse
 
ygritte profile image
ygritte •

What "best practice" did you quietly stop following?

I stopped following even 2 in fact:

Two small ground rules so this stays useful.

1) I am as general as possible.
2) I disagree with everything in your post.
-2147483648) Less talking, more raiding

Collapse
 
carlosmartinezt profile image
Carlos Martinez Tuanama •

I have always been pragmatic which at times it meant to go agains best practices. So things I have done in the past many times and I may continue doing when necesary:

  • Skipped unit tests
  • Never learned how to use vim
  • I refactored whole applications over and over
  • I use the same password everywhere!
Collapse
 
loren_sl profile image
Loren •

"Reproduce it Locally First" A crash minidump from the customer's machine, loaded with matching symbols, usually tells me more in ten minutes than days of trying to reproduce it.

Collapse
 
maltsev-dev profile image
Anatolii Maltsev •

"Ship it raw and grow from feedback"

Collapse
 
shubhradev profile image
Shubhra Pokhariya •

Commenting what the code does. I used to put comments on nearly every block, and later found comments describing code that no longer existed. These days I mostly comment on the why, especially when there’s a workaround, a business rule, or something that looks wrong but is actually intentional. If I feel the urge to explain a line, I’d rather rename the variable.

I still add a short what-comment when the code is genuinely hard to read at a glance, though.

Collapse
 
sreno77 profile image
Scott Reno •

I ignore some parts of PEP 8. Tabs over spaces 4lyfe!

Collapse
 
shieldxbot profile image
shieldx •

I stopped following the rule of "perfect code coverage" during the initial development phase. Early on, I used to obsess over hitting 90% or 100% coverage on every single utility function and edge case, which often felt like I was just testing the language's implementation rather than my own logic. It became a massive bottleneck that slowed down prototyping.

Now, I focus on testing the critical business logic and the "happy paths" that actually prevent regressions in production. If a piece of code is just a simple data transformation or a standard wrapper, I let it go without a dedicated test suite until it proves it needs one. It’s a tradeoff between immediate velocity and long-term stability, but I've found that over-testing trivial code often leads to brittle test suites that you end up refactoring more than the actual application code. Have you found that strict coverage requirements end up making your refactoring process harder instead of easier?

Collapse
 
codearea_shop_1f1def9b532 profile image
Codearea •

One best practice I quietly stopped following is "DRY everything."
I used to extract shared logic as soon as I noticed similar code. But sometimes two pieces of code only look similar at first and later start changing for completely different reasons. The abstraction then becomes harder to maintain than a little duplication.

Now I prefer to keep simple duplication until the relationship between the pieces is clear. If the same logic changes together several times, that's when I extract it.

I also like using CodeArea.net to experiment with and test small code snippets before introducing a new abstraction into a project. It helps me keep the solution simple instead of overengineering it too early.

Collapse
 
sameerqaisar17 profile image
Sameer Qaiser •

The best practice I've already quietly dropped: "Don't repeat yourself."

I'm three weeks into Python — 24 articles published. And in my first few scripts, I followed DRY obsessively. If two lines looked similar, I extracted them into a function. If three functions looked similar, I made a class. I felt like a real engineer.

Then I read my own code a week later and couldn't understand it. The functions were abstract, the classes were unnecessary, and the flow was buried under layers I'd built to avoid repeating three lines of code.

I've started doing the opposite now. If I need to write the same thing twice, I just write it twice. If I write it three times, then maybe I'll abstract it. Maybe.

The thing I realized: DRY was written for teams maintaining code for years. For a 40-line script I'm writing on a Tuesday to generate a password, DRY is just extra work. I'd rather have obvious code that repeats a bit than clever code I can't read.

Still following it sometimes — when I'm building something bigger than a script. But not by default anymore.

Collapse
 
priyasantos001 profile image
Priya Santos •

Forcing password changes every 90 days. For years, I set it up by default on every Microsoft 365 tenant I looked after, and all it really did was teach people to add a number to the end of the same password. These days I would rather enforce MFA everywhere, block known weak passwords, and only force a reset when there is a sign the account is compromised. Fewer helpdesk calls and genuinely better security.

Collapse
 
koda2026 profile image
Harun - solo dev •

"never use a global state object."

every tutorial screamed to use redux, zustand, or react context to avoid global mutable state.

but i code on a $150 android phone with 4gb of ram. loading those state libraries + a UI framework bloats the bundle and literally crashes my mobile browser.

so i quietly dropped the rule. my entire ai web app runs on a single global const state = {...} object, and i just call explicit renderMessages() functions when things change.

people call it an anti-pattern. but it keeps my app at 92kb with zero npm dependencies, and it loads in 400ms on a 3g network.

sometimes the "worst" practice is the only way to survive your hardware constraints. would love to hear if anyone else broke this rule for performance reasons. 🐯

Collapse
 
build996 profile image
build996 •

Mine was "the local copy is the source of truth, deploy from it." On a small site I kept the theme files in a local folder and pushed them up whenever I changed something. Then I found the server copy had been edited directly a few days earlier, so pushing my local file would have silently undone those changes and nobody would have noticed until something broke. Now I pull the live file first, diff it against local, and only then edit. I still keep the local copy, but as a backup, not as the thing I trust.

Collapse
 
cleverhoods profile image
Gábor Mészáros •

Odd, I actually started using new (?) best practices and started enforcing them programmatically

Collapse
 
theodore_ashford_688c0ea3 profile image
Theodore Ashford • • Edited

I stopped chasing 100% test coverage everywhere, now I focus tests on critical logic and edge cases where they provide the most value. Mobile home parks across the city rely on our junk removal Hemet service for sheds, carports, and worn furniture. Compact haul trucks let us fit tight lots and narrow lanes.

Collapse
 
artemooon profile image
Artem •

Hopefully not too much people listen best practices for AI ENGINEER with 2 months experience in this field

Collapse
 
mikachu profile image
Mika Flowers •

? I’m not an AI engineer, nor have I claimed to be one. This post is just a discussion about engineering practices people have reconsidered

Collapse
 
artemooon profile image
Artem •

I didn't mean you personally. I was speaking in general terms and current trends.

Collapse
 
anh_nguynvn_0478e614ba profile image
Anh Nguyễn Văn •

Tôi từng tuân thủ nghiêm ngặt "write tests first" (TDD thuần túy) cho mọi feature mới. Sau vài năm làm product thực tế, nhận ra nó khiến tốc độ iterate chậm chết người khi domain còn mơ hồ — đặc biệt giai đoạn tìm product-market fit. Chuyển sang "test behavior, not implementation" sau khi code ổn định: viết integration test cho happy path, unit test chỉ cho logic phức tạp/risk cao. Kết quả: coverage thực tế cao hơn, refactor thoải mái hơn, team ship nhanh hơn. Nguyên tắc còn lại: test phải fail trước khi fix bug — cái đó không bao giờ bỏ PS: the tool I meant is on labagent .tech

Collapse
 
vitaliy_dmitriev profile image
Vitaliy Dmitriev •

If I'd remember that I will start following it back 🫠