Good code is working code, code that pays the bills. Focus instead on writing code you can throw away easily, code that you are wholly unattached to and is isolated enough that rewriting it won’t cost absurd hours.
Good code is working code, code that pays the bills. Focus instead on writing code you can throw away easily, code that you are wholly unattached to and is isolated enough that rewriting it won’t cost absurd hours.
The problem with believing that "good code" is good enough to deliver business value is short-sighted.
Good code is highly maintainable so that you can continue to meet business objectives in a timely manner without regressions. Often this means (ironically) taking a little bit of extra time early on to think about how to make your code readable and "simple enough" for someone else to be able to jump in and maintain it.
> Good code is highly maintainable so that you can continue to meet business objectives in a timely manner without regressions.
I think you essentially agree on what people should do, regardless of whether you call this 'good code' or just maintainable code.
Write tests. Give things good names. Use comments to explain why you're doing something, not how to program. Don't copy and paste the same implementation x times because that way there's only one place to fix it.
But also sometimes it makes more sense to copy and paste over trying to fit an abstraction where it shouldn't be. :)
I think the purpose of questions like the ones by OP is not to figure out "rules" (which are useful only for beginners) but to figure out where and why rules were broken. Sometimes (often) the answer is time, but that in and of itself is a useful example.
Good intermediate (I suppose Sr. in our industry) level code is notoriously difficult to find examples of and mentor toward.
depends on goals. diverging modules should be copy-pasted, two modules that rely on the same functionality should be consolidated (not necessarily abstracted, but synchronized somehow). Those are both two common cases, so there's no general advice on which is better.
>Good intermediate (I suppose Sr. in our industry) level code is notoriously difficult to find examples of and mentor toward.
so much industry code and knowledge is proprietary, so I imagine that is by design. even intermediate code has a bunch of value to a company, even if the company lets go of that engineer to make their earnings report 0.1% higher.
I find that's a smell of limited languages: Maybe a language has poor error handling semantics, maybe it's not expressive enough to make a parameter generic.
It can also be a smell of not understanding the language well enough, too. Maybe there is no need to copy and paste, but the programmer didn't understand the language well enough to make a generic abstraction.
But you can only do what your tools allow you to do.
Seems not ideal for end users, unless you're working with microservices or something with well defined specifications that people are actually paying attention to.
Beside, "rewrite" here doesn't mean "new repo, new project, new everything" it means reimplementation, usually based on the lessons learned from the previous implementation, and that does include edge case handling, as well as expanded functionality to "underwrite" or justify the effort spent on the rewrite.
If you design your app as a collection of subsystems, it's sometimes faster to destroy and rebuild one of them than it is to refactor.
A good interface limits the blast radius of my refactor.
and that paradigm is exactly why my domain is the start opposite of front end web development. Code I write may be used by thousands of other engineers over decades. I can't take into account every edge case, but I do try to write with the assumption that one day some archeologists will uncover that code as some Rosetta Stone. Of course, modern demands never let me reach that ideal, but it teaches care and good documentation.
Congratulations on figuring out how to create a massive churn rate among your actual good engineers.
If that’s what you need to do to solve the problem, do that. The point is to stop focusing on the code as the work product, and instead focus on the solution as the work product, of which code is one part.
Good code should always solve the solution, to be considered good code. Bad code might solve the solution, it might not.
Writing bad code that just "gets it done" is the proverbial broken window. It's how you end up with shitty code-bases that get shittier with every change, until it all collapses under its own issues.
Doing this on established code-bases is basically what the classical duct tape programmer does. Sure, you deliver "business value" in the short term (normally to claim credit and gain favor) but at the expense of everything and everyone else.
Not saying one is better than the other. Sometimes being first across the line is make or break for a company. But I wish companies could be more honest about what they want.
But in a way you're right; if there is no to ensuring your code follows more conventions, go for it. That's exceedingly rare, however, as a situation to be in.
Is it because it's perfectly abstracted and encapsulated and SOLID and DRY?
Or is it because it's written in a manner, easy to understand, easy to extend, and easy to throw away and rewrite if necessary?
I'm guessing solid and dry are a big part, but lack of cleverness, language choice that doesn't require cleverness, and heavy reuse with libraries and frameworks, and choice of feature complete libraries is probably a lot of the speed.
Something in C is going to be more work than JS or Python or Dart and work takes time. Code you write takes more time than code that already exists, unless the code that exists disappears one day.
This. But IME when you write for this purpose you tend to end up with code that is in fact confusing, not documented, and not test covered. So you need to slow down even if your goal is to one day completely re-write that module.
Perfect abstractions are never perfect unless you completely architect out the product, down to every single edge case. That's virtually impossible with a large codebase, be it due to an API or even compiler level bug.
This is not relevant to the vast majority of developers, realistically (and is an important caveat to your original comment).
The first is the business problem, most important.
The second is the problem of maintaining and iterating on the solution to 1…
Without solving the first problem, the business dies and you don’t even need to care about the second problem… however the second problem can also kill the business if not solved eventually…
As I said, it depends on the project. I'm not going to approach a leaky faucet the same way I would an industrial sewage pipe. Fortunately the industry is big and I can choose to work on larger problems where longevity is valued over throughput. You're fine whipping together a React App in a weekend While I'd be more the end of maintaining the React repository. To each their own.
> Your “craft” is not to write code, it’s to solve problems.
Writing code is part of solving problems.
The quality of code has an impact on the various aspects of how a group of people solve problems.
As a small example - consider onboarding time for a codebase/system. Longer onboarding time means - lower profits end of the day for the organization (I'd also argue that longer onboarding times correlates higher talent attrition). And code quality has a strong influence on onboarding time.
Code quality has an impact on the "debuggability" of your systems. How quickly can you fix stuff when things go wrong?
Code quality has an impact on the "deployability" of your systems. If your code is well-done it is easy to deploy, redeploy, etc.
I can cite maybe 10 more properties crucial to org health, which are influenced at least partly by code quality.
So, "the problem" is not as simple as it may seem at first glance.
This is why the pursuit of “high quality code” is pointless; you are not an artist, you are aligned to solve a problem. If you do that, code or not, you are doing good work as an engineer. If you are not, you are not. Whether the code fits some arbitrary definition of “good” separate from your ability to solve a problem doesn’t play into it.
The second issue is that you think it is impossible to define an "abstract good" in code quality given a specific context (team, product, market). The "abstract good" stems on its own for the given internal culture and market situation. Through some common sense examples, it is easy to see how "abstract good" wields influence on "practical parameters" critical to business survival/thriving.
As an analogy, I can say the "body is healthy". I am aggregating a bunch of metrics to say - "this is healthy". It doesn't mean the term "healthy" is meaningless. The term "healthy" has useful meaning although not at a mathematically precise level. One could even argue that the term "healthy" captures something even precise mathematics cannot capture (it's abstracted at a higher level). Apply similar argument to the term "code quality".
Edit: Maybe it is better to explore the idea of code quality "via-negativa". Find what's actively harming beneficial outcomes. And remove it. If you cannot find many harmful things, then it has high code quality.
You can call that good code if you want, but my argument is to stop caring about the code’s “quality”, as a value it carries independent of the problem.
The physician - operates "via negativa". He tries to find faults with the given body, tries his best, and when can't find - he calls it "healthy".
The engineer/businessman can look at the code from an empirical point of view.
If onboarding is bad -> code is bad
If understandability is bad -> code is bad
If deployment is bad -> code is bad
And so on. As you eliminate these issues, your "code quality" increases (just like as you eliminate disease, the body becomes more healthy).
Look into say, Taiichi Ohno's Toyota Production Management - one associates "zero defect" ~= "quality". So, the term quality alludes to a continuous elimination of faults and shortcomings.
The aggregate placeholder/banner term 'code quality' stems from very firm practical sources, that can be inspected, amended and improved.
> make it work, then make it pretty, then make it performant
Solve the problem first, then improve the solution
On the other hand, those aren't the only two choices, by a long shot.
A painter might study and practice enough to be as good as Michealangelo, but the attempt to be 'more good' or 'better than Michaelangelo' stops as soon he starts a serious painting. He has to finish the painting with the skill he has at that point.
I agree code should be unattached and you can throw it away. As soon as you start coding a program for a client, your attempts to become 'more good' as a coder and to write more ideal code, have stopped and it's time to make some code you can throw away or sell to the client.
But all the 'training' paintings you made on the journey to becoming 'good' have to be kept, because you trashed thousands of attempts along the way in pursuit of an ideal painting. The good painting is framed and hung on my wall. The commercial painting is sold to the client or trashed.
Yes, give up on 'good code' at work. Keep the ideal of good code as a direction to improve towards, not an end result in commercial works.
As soon as 'good' became explictly defined/bike-shedded it died anyway..... it's an infinite direction, not a limited thing that can be defined and boxed up.
Code that works is, usually, acceptable. But code that is acceptable while making no unnecessary maintenance trade-offs is much better. Good code is code that uses standard techniques in standard ways to achieve a result without being verbose or inefficient. But that is a much higher bar than code that is literally good enough.
I mean, juniors can do this. Once you're a senior, there will inevitably be come coupling you need to make in order to "pay the bills". Or you may make the first part of a system that will be a pain to re-write, even if it's the most elegant, readable code ever.
Nothing wrong with preparation.
But hey, they do justify it in responses. So maybe they are indeed playing to their philosophy of "work fast"