I haven't written here in a while.
Not because I ran out of opinions.
That would be concerning.
I just got tired of the endless stream of:
AI ...
For further actions, you may consider blocking this person and/or reporting abuse
A factory 😂🤣
I laughed out loud in real life and my significant other became concerned.
I needed that. Thank you. 😂😂😂
Hahaha perfect 😂
Tell your significant other the factory was necessary
How dare dev.to hid this from me for 3 seconds
😂
"The value is not in the code" - fine, but the code is the product, unless we give other 'artifacts', like documentation, the same amount of (or more) "love" as the code - but IMO we don't ...
"Maybe the job was never writing code" - but the code is what gets judged in the end ...
I noticed that code written by AI tends to be (not always, but often) more over-engineered than code written by humans ...
So, if it's unavoidable that most of the code will get written by AI (and that probably is unavoidable), then I feel that the human telling the AI "please simplify this over-engineered code" is one of the most important things we can do ...
P.S. I agree that some of the more abstract skills that you mentioned are, in the end, more important than "typing the code" - however:
(a) how are you gonna review whether the code written by AI makes sense if you never learned how to write the code yourself in the first place? You won't know how to properly "read" code if you've never "written" any ...
(b) the more abstract skills that you mentioned aren't developed in a vacuum - one of the best ways to develop them is to actually write, run and debug code yourself (i.e. not outsourcing all of the thinking and implementation to AI) - otherwise we'll forget or "unlearn" the foundations and basics of the "craft" ...
Just a bit of an anti-dote to the sentiment of "writing code doesn't matter anymore" - I still advocate that we keep writing some of the code ourselves ...
Yeah, I think this is the important nuance.
I definitely don't mean that learning to write code no longer matters. Quite the opposite, if you can't read, debug and reason about code yourself, you're in a very weak position to judge what an AI gives you.
I think my point is more that producing code is becoming cheaper, while understanding whether that code should exist, whether it is too complex, and whether it actually solves the right problem is becoming more valuable.
And I completely agree with your point about over-engineering. “Please simplify this” might genuinely be one of the most useful prompts in software development right now 😅
The part I'm still unsure about is what happens to newer developers if they skip too much of the painful manual work we all learned from. A lot of engineering judgment came from writing bad code, debugging it, regretting it, and eventually learning why it was bad.
Agreed on all accounts, especially the last one - I think juniors should still learn the basics and the skills of the trade, which includes writing code the "old fashioned" way, but also knowing the fundamentals - databases, web protocols (HTTP), HTML/CSS/JS, etc - otherwise (just as you said) how are they going to be able to review and judge the stuff AI has generated?
We're going to have to be MORE knowledgeable, not less - I think the bar is gonna be higher, not lower ...
Exactly. I think that’s the part a lot of people underestimate.
AI lowers the barrier to producing code, but it may actually raise the bar for being a good engineer.
If more implementation is generated for you, your value shifts toward understanding systems deeply enough to spot bad assumptions, fragile abstractions and subtle mistakes.
So ironically, the AI era may reward strong fundamentals more, not less.
The scary part is that it also makes it much easier to look productive without actually understanding what you’re building.
This:
"The scary part is that it also makes it much easier to look productive without actually understanding what you’re building"
That might actually be the sentence I should’ve built the whole article around.
Welcome back! I was wondering where good old NorthernDev had disappeared 😂
I think the real impact of AI-generated code and vibe coding will become clear in the next few years (or maybe sooner, given how fast things are moving). Existing projects are already being maintained with AI, but most of their code was originally written by humans. Meanwhile, companies are building and shipping entirely new products with AI-generated code. We'll see in a few years how maintainable those projects really are and how big the mess might be.
Thank you 😂 I apparently needed a small internet hibernation.
And yes, this is exactly the part I’m most curious about.
Right now, a lot of the “AI works great in production” evidence still comes from projects where humans created most of the original architecture and AI is helping with implementation and maintenance.
The really interesting test will be projects that were AI-heavy from day one.
Not whether they ship fast, they obviously can.
But what happens after 18–36 months of changes, edge cases, staff turnover and accumulated “reasonable” decisions.
That’s when we’ll find out whether AI made software development cheaper… or just moved the cost further into the future.
Welcome back my old friend!!
What most people never realized is that being a good developer isn't about coding, but more about design of the software being built and being able to communicate. It's those soft skills that makes a good developer because once you have the design and idea in place, it becomes much easier to build that software regardless of how much you know about its syntax. Anyone can learn programming language when you put your mind into it, but it's only a matter of if you decide to learn and put your mind into it.
Hahaha, there you are 😄
Feels weird being back in a comment section with you again.
And yeah, i think that’s exactly it. The syntax is rarely the hardest part once you know how to learn.
Design, communication, trade offs, knowing what not to build, that’s where the real difficulty usually is.
AI just makes that more obvious now because the typing part is getting cheaper and cheaper.
This matches what I see in client work. The models improved a lot, but most of the software problems I get asked to fix were never about typing speed. They were about nobody agreeing what the thing was supposed to do, or what finished looked like.
A stronger model applied to a vague request produces a more convincing version of the wrong thing. Where AI does help is when the problem is already small and clearly defined: one workflow, one integration, one report, with acceptance criteria written down before anyone opens an editor. In that setting the speed gains are real and they stick.
So I would read your observation as a scoping gap more than a tooling gap. Curious what you noticed first on coming back: more code, or more of the same old bugs arriving faster?
Yeah, I think “more of the same old bugs, just faster” is probably the best way to put it.
The code itself is often fine. The problem is when the request is vague to begin with. Then AI just gets you to the wrong thing quicker 😅
I’ve noticed the same as you though, when the task is small, clear and boringly specific, AI is genuinely brilliant.
Feels like the real skill now is getting the problem clear before anyone starts building.
Welcome back!!! "microservices solving problems that did not exist"- this line hit hard 🤣
Thank you! 😂
Somewhere right now, a team is deploying 11 microservices to handle a contact form.
@the_nortern_dev , this is one of the most accurate assessments of the current AI development landscape I’ve read.
your point that "ai is extremely good at helping you overengineer" hits perfectly. when you build on constrained hardware (like a $150 android phone with 4gb of ram and spotty 3g), overengineering isn't just a bad architectural choice—it's a fatal one. the hardware physically rejects "suspiciously helpful" abstractions and 14-step microservice patterns.
this is exactly why the "boring stack" is making a comeback. constraints force us to ask the right questions: "does this need another layer?" and "could this be deleted instead?"
i completely agree with the thread about developers needing to learn the fundamentals. you cannot effectively review, debug, or simplify ai-generated code if you don't understand the underlying mechanics. that’s why i spend so much time manually building secure js sandboxes and understanding execution boundaries, rather than just prompting an agent to "make it work."
the most valuable skill right now isn't prompting; it's editing. knowing how to look at 600 lines of "perfectly respectable-looking code" and confidently delete 500 of them because they solve a problem that doesn't exist.
great to have you back. the industry needs this level of pragmatic realism. 🐯
This is such a good point about constraints.
When the hardware is actually limited, you don’t really get to pretend complexity is free.
And yeah, I’m with you on editing. The ability to look at 600 lines and calmly delete 500 of them is probably more valuable than being able to generate the 600 in the first place.
Appreciate the welcome back too. Feels good to be writing again.
northerndev, exactly. when hardware is actually limited, you don’t get to pretend complexity is free.
the ability to look at 600 lines of code and calmly delete 500 of them is the ultimate senior dev superpower. generation is cheap; curation and ruthless editing are where the real engineering happens. glad to have you writing again! 🐯✂️
Hahaha, “generation is cheap; curation is the work” pretty much sums it up 😅
And yeah, deleting 500 lines without panicking is definitely a senior dev skill.
Feels like AI is making good editing taste more valuable than ever.
The pit is deeper than we think.
Rightly said,
Most of the devs don't know what the right design of the system needs to be.Yeah, and that’s probably the uncomfortable part.
AI can generate a design very quickly, but if the person using it doesn’t really know what a good design looks like, the output can still look convincing enough to ship.
That’s where experience matters a lot more than people like to admit.
This article voices what many people dare to think but not to say, and it does so very candidly.
Several points resonated with me:
“Code generation has never been the bottleneck” - this is the article’s key insight. We’ve always thought that “slow writing” was the main issue in software development, but what truly delays a project is “whether it should be done” and “how it should be done”. AI has made the easiest part free, but the hardest part has become even more expensive.
“Friction used to protect us” - this perspective is quite insightful. In the past, over-design required at least a physical effort, but now intelligent agents are all too eager to help you complete a disaster, even adding three interfaces and a factory. AI is not the danger; it just magnifies our poor decision-making.
“Taste will become a core competitive advantage” - it’s hard to quantify and doesn’t fit on a resume, but “knowing when not to code” is indeed becoming the rarest skill. Many can use AI, but few can reject AI’s outputs.
A minor addition or objection:
The author’s claim that “software hasn’t improved” might be a bit too pessimistic. AI has reduced the cost of prototyping, meaning more ideas can be quickly tested and discarded - this in itself can be a form of refining taste. The issue isn’t with the tool; it’s that most people still use the old adage “more is better” with new tools.
In response to the question at the end of the article:
My answer is: AI won’t automatically make people better engineers, but it will widen the gap - those with good judgment will be even stronger, while those without will only accumulate technical debt more rapidly. Tools are amplifiers, not transformers.
It’s worth sharing with every team member who’s fixated on “AI writing an entire feature in a day”. 👍
Yeah, this is a really fair take.
I probably was a bit too pessimistic with the “software didn’t” part 😅
You’re right though, AI does make it much cheaper to try things, throw bad ideas away, and iterate faster. That can absolutely be a good thing.
I also really like “tools are amplifiers, not transformers.”
Good judgment gets amplified. Bad judgment does too.
And I think that’s probably the real point. AI doesn’t magically give you taste ,it just makes the consequences show up faster.
One thing worth measuring is the complexity an AI-generated change adds relative to the problem it solves. At IT Path Solutions, we see why faster implementation alone isn't a reliable measure of engineering progress. A useful review question is whether each new abstraction, dependency, or service boundary removes enough real complexity to justify the maintenance cost it introduces. This could even become part of an engineering review checklist: what became simpler, what new concepts must future developers understand, and could the same requirement be met with less machinery? AI makes producing more code easy; the real advantage comes from consistently choosing what not to build.
Yeah, this is a really good way to frame it.
“What became simpler?” is probably the question people skip most often.
AI makes it so easy to add another layer, service or dependency that the cost doesn’t feel real in the moment.
I like the checklist idea too. If every new abstraction has to justify its own existence, a lot of them probably won’t survive the review
The line that hit me: "Friction sometimes saved us from our own terrible ideas."
I'm three weeks into Python — 27 articles published. So I'm the person AI is supposed to replace. And I've been thinking about exactly this.
Here's what I've noticed: AI makes it easy to produce code that works. It makes it equally easy to produce code I don't understand. And the second one is more dangerous, because it feels like progress.
I've started noticing the pattern in my own work. When I ask AI to write a script, I get something clean. But when I read it back, I don't always know why it's structured that way. And when I change something, it breaks in ways I can't predict.
That's the friction you're talking about. The reason I learned anything from building my weather CLI is because it broke three times and I had to figure out why. If AI had written it, it would have worked on the first try — and I'd have learned nothing.
I don't think AI makes developers worse. But I think it makes the gap between "shipping code" and "understanding code" bigger. And that gap is the whole thing.
The "taste" point is exactly right. I don't have taste yet. But I know it when I see it in other people's work — and I know I'll never develop it if I let AI make every decision for me.
Great post. Saved.
This is such a good example of what I meant.
That gap between “it works” and “I understand why it works” is probably where a lot of learning either happens or disappears.
And honestly, three weeks into Python, noticing that gap already is a very good sign.
I think breaking things, fixing them, and slowly building that instinct is part of how “taste” gets developed in the first place.
AI can save you from a lot of frustration, but some frustration is actually educational 😅
Keep building things you understand a little more each time. That’s probably more valuable than shipping 10 polished projects you can’t explain.
AI makes engineers better if they use it responsibly. If they are not tempted to just generate, generate, and generate code. Most of the devs I see today glorify this workflow. The human understanding takes time while the code gets shipped faster than ever.
Some articles I read says more and more people use AI to review an AI-generated PR. If there's a comment, they use AI-generated comment to answer as well.
It seems like we are pretending to know every line of code shipped even though we aren't. The "LGTM" note for a 1000+ line PR under a minute of review is baffling. (However, I also get that some of the engineers are forced into this kind of workflow else they would be fired even though they do not stand by it).
TLDR: It all comes down to discipline when it comes to AI. I use AI too but not to the point I become a meat proxy between AI and the codebase. AI will not go anywhere, it is here to stay. However, if this is still the trend for years to come, then the world where we consult AI for EVERY DECISION WE MAKE will become a reality.
“Meat proxy between AI and the codebase” is painfully accurate 😂
That’s probably the part that worries me most too. Not that AI writes code, but that the human can slowly drift out of the loop while still looking involved.
AI writes the PR, AI reviews it, AI writes the reply, human clicks approve... at some point, what exactly are we contributing?
I’m not anti-AI at all, but I do think there has to be some deliberate friction left in the process. Otherwise understanding becomes optional, and that feels dangerous.
Discipline is probably the right word for it. Use the speed, keep the judgment.
I just hope that we humans as a whole would prevent this kind of future to happen.
The friction point is the real observation here. I ran a count last month — 73% of the code an agent generated for me on one project was abstractions I didn't need, wrapping calls that were already one line. Before AI, the cost of writing those layers was the thing that stopped you. Now the cost is zero and the tax shows up six months later when someone has to debug through four indirection layers to find the actual query. Removing friction didn't make us faster. It made us more willing to build things we shouldn't have built in the first place.
Yep, this is exactly what I mean.
The cost didn’t disappear, it just moved.
Before, the pain was in writing the unnecessary abstraction. Now the pain shows up later when someone has to understand why it exists.
“The tax shows up six months later” is such a good way to put it.
This is a very interesting article and the end question makes a lot of sense. From the coding POV, we are getting solution to problem, but sometimes the AI will give unnecessary solution to a problem that can be solved in 3 lines in one file. My personal opinion is the speed of development has gone up, which is a good thing, but the quality of the code in some cases is going down, and it is a very serious thing. I lead a team and sometimes looking at their AI generated code during review gives me a headache because the code is unnecessarily complex, too much of unwanted changes that might not be required, and the review takes more time than writing the code.
To be a better developer you need to be proficient in code reviews and understanding why AI has given certain solution to a problem and if any alternate solution exists. Anyone can generate a code, but only a software developer can review if the generated code actually makes sense and is required.
Yep, this is exactly the kind of thing I keep hearing from people doing reviews now.
The funny part is that AI can save 30 minutes writing the code and then create an hour of review work because it touched five files it didn’t need to touch.
And i agree with your last point completely. Generating code is becoming the easy part. Being able to look at it and say “this is technically valid, but it’s still the wrong solution” is where the real skill is.
That review muscle is probably going to matter more, not less.
Well said! This is more or less what I've been saying too. We can produce more code, but we haven't gotten any better at understanding users, customers, stakeholders, etc. Devs are creating tons of code and bringing down GitHub but are they solving problems that need to actually be solved. Companies are forcing devs to produce at an alarming rate with LLMs, but they haven't gotten any better at product management. Companies that were feature factories before still are, they're just producing more.
We’ve gotten much better at producing software, but not necessarily at deciding what users actually need.
And if product thinking stays weak, AI just helps us ship the wrong things faster.
I have suspected for a while that this is the primary explanation for why AI coding agents feel 10x faster, but actual shipped output has not really seemed to improve much, if at all.
Even if AI reduces the cost of writing code to 0 (it doesn't) and even if it has no other negative costs (it does) and even if we pretend using the software is free to use (it isn't), we are still maybe looking at a 15% - 30% improvement since writing code only takes up about that much of the day.
Yeah, I think this is a huge part of it.
People talk about “10x faster” as if coding was 100% of the job.
It isn’t.
There’s planning, meetings, debugging, reviews, product decisions, waiting on other people, figuring out what the requirement actually means...
So even if AI makes the typing part dramatically faster, the whole system around it can still move at roughly the same speed.
That gap between local speed and actual delivery speed is probably where a lot of the hype gets lost.
That point about friction being a safety mechanism hits straight where it hurts.
In distributed systems, when you increase the ingest throughput by two orders of magnitude without adding backpressure, you don't get a faster pipeline—you just crash the consumer downstream. That's essentially what happened to engineering workflows. The token generator has virtually infinite bandwidth, but human cognitive capacity for reasoning about invariants, edge cases, and failure modes at 3 AM remains strictly single-threaded and bounded.
There's also a statistical trap with "reasonable-looking" code. Language models are probabilistic predictors trained on the entire corpus of public software. And what is the arithmetic mean of enterprise software over the last twenty years? AbstractSingletonProxyFactoryBean and six layers of indirection around a single SQL SELECT query. Radical simplicity is statistically an outlier in the latent space; the gradient naturally rolls down toward boilerplate. If you don't fight that gravitational pull with active, stubborn judgment, you end up shipping an entire distributed architecture just to serve a CRUD dashboard.
Ken Thompson once famously noted that one of his most productive days was throwing away a thousand lines of code. Nowadays, the agent can hand you those thousand lines back in four seconds flat, complete with synthetic unit tests that all pass while asserting precisely nothing.
The real job was never typing syntax anyway; it was acting as a low-pass filter against systemic noise. If we don't treat deletion as a first-class refactoring operation, we’re going to need a PDP-11 memory limit just to force ourselves back into having architectural taste.
Hahaha, this is such a good way to put it.
“Human cognitive capacity is still single-threaded” is probably the cleanest explanation of the whole problem.
And yeah, that point about simplicity being the statistical outlier is interesting too. AI has seen oceans of enterprise boilerplate, so of course it happily reproduces it.
I think that’s why deletion matters so much now. Generating code is cheap. Resisting unnecessary code is the actual work.
Also, “synthetic unit tests that all pass while asserting precisely nothing” hurt more than it should
The scary part is how convincing unnecessary complexity looks when AI generates it. Everything has a neat name, clean interfaces, proper structure... and then you realize the whole thing could've been one function.
I use AI a lot, but deleting half of what it writes is becoming a skill of its own 😅
Exactly 😅
That’s the dangerous part, it looks so well engineered that you feel bad deleting it.
Then you strip away three layers and suddenly the whole thing is just... one function.
Honestly, “knowing what to delete” is becoming a pretty serious skill.
The point about friction saving us from bad ideas is so real fr. Used to take a week to build a bad microservice so you would think twice. Now an agent spins it up in an hour and suddenly it is in production. The boring stack argument lands harder when you are working with AI code gen because context windows are finite and boring code reads better to models too. Started asking a different question before each feature: what is the dumbest version of this that would actually work. Usually the answer is fine. What is the thing AI keeps tempting your team to overengineer?
“What is the dumbest version of this that would actually work” is a great rule.
For me it’s usually architecture around small features. AI loves turning a simple flow into layers, helpers, interfaces and “future-proofing” before there is any future to proof for.
That’s probably the temptation I notice most, solving version 10 before version 1 has even earned the right to exist.
Đúng lúc mình cũng đang cảm thấy cái "khoảng cách" đó rõ rệt nhất khi review code của team junior. AI sinh ra boilerplate, test case, thậm chí cả migration script trong tích tắc — nhưng kiến trúc hệ thống, quyết định trade-off giữa consistency vs availability, hay cách tách bounded context sao cho team sau này không đau đầu... những thứ này vẫn ngồi im ở đầu người senior.
Mình thấy vấn đề không phải AI "chưa đủ tốt", mà là chúng ta đang dạy dev mới dùng AI như một cái đũa phép thay vì công cụ tăng cường tư duy. Kết quả: code chạy ngon, deploy lên production rồi mới phát hiện coupling chặt chẽ, không test được, scale không nổi.
Có lẽ lúc này skill quan trọng nhất không phải "viết code nhanh hơn" mà là "đọc code của AI rồi bắt lỗi thiết kế trước khi nó kịp merge". Bạn thấy team bạn đang ứng phó ra sao với cái shift này? PS: the tool I meant is on labagent .tech
I can't disagree. I honestly think we're facing a shortage of actual developers. Too many people are using cookie-cutter platforms to churn out cookie-cutter apps that solve problems nobody actually has. 😂
Personally, I think the entire SaaS model has become a bit of a racket. Everyone wants to charge you a monthly subscription for something that used to be a one-time purchase—or something you could build yourself with a little ingenuity. There’s a difference between building useful software and just slapping a subscription on a template and calling it innovation.
Yeah, I get what you mean 😅
There’s definitely a weird amount of software now that feels like “find a tiny inconvenience, wrap it in a dashboard, add Stripe.”
I don’t think SaaS itself is the problem, but I do think AI is making it way easier to ship things before anyone has really proved the problem is worth solving.
Building got cheaper. Finding something worth building didn’t.
This really hits home! AI can help us build faster, but building the right thing still requires human judgment, experience, and empathy. I especially agree that simplicity is an underrated engineering skill. Good software isn’t about how much code we can produce, but how well we understand the problem and how thoughtfully we solve it. In the end, the best engineers won’t just know how to make AI build more — they’ll know when less is actually better.
Yep, exactly. “Less is better” sounds obvious until you’re actually building something 😅
I think that’s one of the biggest traps with AI right now, it makes adding things so easy that restraint becomes a skill in itself.
Great perspective! I especially agree that knowing what not to build is becoming just as important as knowing how to build it. AI makes it easy to generate code quickly, but maintainability and good architectural decisions still require human judgment. Sometimes the best solution really is the simplest one, with fewer abstractions and less unnecessary complexity.
Yep, exactly. I think that’s the shift.
Building is getting easier. Deciding what deserves to be built isn’t.
And yeah, the simplest solution still wins surprisingly often. Fewer moving parts, fewer surprises later
"Exactly this! Before AI, typing out a 14-layer abstraction was so exhausting that you'd stop yourself. Now, agents happily build the whole disaster for you in 10 seconds. We don't need more code; we need more people willing to say 'No' and simplify."
that’s basically the whole thing.
AI removed the pain of building bad ideas.
Now the valuable skill is being the person who says “nope, too much” before it turns into production.
you are alive :). I agree with you completely
Hahaha, barely 😅
Took a little detour, but apparently i’m back to complaining about software again.
hahahaha:)
I often marvel how fast AI can spin up implementations. This article reminds me speed is worthless without good decision‑making to go along with it.
Exactly. Speed feels impressive, but it’s only useful if you’re heading in the right direction.
AI made it much easier to build things fast. I’m not sure it made us equally better at deciding what should be built in the first place.
Fascinating deep dive into AI workflows. Grounding outputs and evaluating latency budgets will be key as more agentic systems reach production.
Absolutely. Once agents start touching real production systems, grounding and latency stop being “nice to have” details pretty quickly.
I think that’s where the gap between a cool demo and actually reliable software becomes very obvious.
The more I build with AI, the more time I spend deleting code instead of adding it. Getting a working version is easy now. Keeping it simple is the hard part.
Yep, that’s exactly it.
Getting to “it works” is almost the easy part now.
The real work starts when you look at it and go… “okay, how much of this do i actually need?”
Feels like deleting code is becoming part of the job description.
Interesting perspective!With AI generating more code than ever, how do you decide when to trust the generated solution and when to step back and simplify the design yourself?
Good question. I usually trust AI more on implementation details than on design decisions.
If the problem is already well understood and the architecture is simple, I’m happy to let AI move fast.
I step back when the solution starts introducing new abstractions, extra layers, additional dependencies or complexity that I didn’t explicitly ask for.
My rough rule is: if I can’t explain the generated design clearly in a few sentences, it’s probably too complicated.
I also ask myself one boring question a lot
What is the simplest version of this that would still solve the actual problem?
AI is very good at giving you a solution. I still think the human has to decide whether it’s the right amount of solution.
🥰
AI doesn’t make you a better engineer; it just amplifies who you already are. If you have bad architectural habits, AI will help you ship technical debt at machine speed.
The real skill now isn't prompting—it's subtractive engineering and having the taste to say 'no' to 90% of what the AI generates
“Ship technical debt at machine speed” is painfully accurate
I think subtractive engineering is going to matter more and more. Anyone can ask AI to add something now.
Knowing what to remove or never build in the first place is the harder part.
I think we’re creating an amazing amount of tech debt that someone will have to pay for.
서비스 레이어·리포지토리 패턴·재시도 로직이 각각은 그럴듯해 보여도, 한 작은 기능에 모두 붙으면 변경 비용이 오히려 커진다는 지적이 와닿았습니다. 에이전트에게 코드를 맡기기 전에 해결할 사용자 문제와 이번에 일부러 만들지 않을 계층을 한 줄씩 적고, 리뷰 때 실제로 줄어든 복잡도를 확인해 보면 좋겠습니다.
It's just more training basically. AI is only good as the data it was trained on.
good