How do I know if I'm good at programming?
danielslater.net
danielslater.net
The best advice on the profession that I was ever given was simply, "Learn to learn."
The vast majority of this profession is just being interested in figuring out how to solve different problems. Sometimes that means it's all you and sometimes it means learning new things or doing research.
You know that you are not a good programmer when you don't see any problems that need to be solved.
I'm sure others can do a better job elaborating on this process. I only recently made a mental switch to treat programming as a thing in itself that I enjoy, and it really has made me a happier person. I'm learning faster and more than ever before (even with coding as my only source of income, which should have provided incentive), I'm having an amazing time exploring things for the sake of just exploring and learning.
And as a bonus, it has made me both enjoy and do better at my job as well! I feel like my toolset has rapidly expanded, and as a result I can (justifiably) use those tools to help clients (and get paid), scratch actual code-solvable itches I've had for years, and see potential ways to generate recurring income. And, with some trepidation, I even think I've learned at least some things that I can use to 'make the world a better' place!
EDIT: more specifically, aside from looking for problems to solve, I decided to create my own problems, or consider them worth solving, and then went and solved them.
The first is the “rockstar” developer type who is great at prototyping, hitting deadlines no matter what and delivering functionality, albeit full of bugs. They will write 80% of the code and will drive the support team up the wall by breaking the build, causing customer issues in production, security holes and basically seriously degrading the code base. But their boss will love them because they deliver the shiny when required.
The second type are the ones who can sort out the mess created by the first type without making things even worse. They tend to be less visible, less well paid and less in demand but every company needs them.
The whizz kids and the grown-ups basically. Companies who only have the first will burn bright but not be able to scale. Companies who have only the second type tend to move too slowly to get to market or pivot.
So ideally there is a symbiotic relationship between the two types and someone who is a combination of the two is very rare indeed, because the first either needs an ability to place limitations on awareness of the big picture (and it’s very difficult to create a blind spot on demand once you have experience) or they need to be incredible at both analysis and full stack execution. Those people are few and far between so a process that gets the best out of the two types is, in my experience, the way that most companies work.
Thankfully I'm pretty sure the startup would've failed no matter what, so I don't feel too guilty about it. But it taught me a valuable lesson.
Looking through some repositories of programs I like, some of them were prototyped in very little time, but with a surprisingly excellent first revision.
I had the pleasure to work with Zed Shaw quite some time ago, and even though his code might not be perfect, he writes a lot better code than the vast majority, in a lot less time.
Anyway, I think you need to look up the words "tirade" and "incomprehensible"
tldr: Welcome to the Internet
I have no idea if I write code better or faster than other people. Maybe I do, but I always think that I don't write very good code most of the time so I have to be extra careful. I spent a lot of time writing code very slowly and being extra careful so that I could make sure it's good quality. I guess after focusing on quality for so long I just got faster at it compared to others. But, I'm going to guess that I actually am not much faster than other people.
Lots of us are good at being excited, moving fast, when something grabs our focus. Some of us are just as excited at the quality of our "how" as we are the size and shape of the finished "what".
I feel this may be too specific to your personal experience / work history.
Unfortunately for us mere mortals, programming is not quite a performance art (despite the existence of /r/watchpeoplecode), so there's not anything to point at globally as this is what a great programmer looks like.
Moreover, a company's culture is the culture - if they put up with assholes who can program a little bit, they'll also put up with assholes in be other positions for different reason.
Personally I'd choose somewhere else to work.
Showing results for /r/watchpeopledie.
Search instead for /r/watchpeoplecodeIt seems the boss is really the problem then :)
If you want to be a great startup engineer you have to exercise judgement; knowing when to do something quick and dirty, what to polish, what code is likely to live a long time, when and how to address various aspects of scalability, etc. Someone who just has one mode of operation and does not consider the context is always a liability unless their role is very rigidly defined and management knows what they're doing.
I've worked as a freelancer, lead front-end developer, and contractor, and ranging from 'stuck in the nineties' to 'use whatever HN talks about for the front-end' companies. One of the most important lessons I learned is to use the right tool for the right job. Also to not let 'purity' or 'elegance' get in the way of getting it done (which is difficult for me). But also to never confuse 'getting things done' with laziness.
I think most developers naturally become more cautious with experience (the bitter experience of debugging long into the night usually), while some never grok maintainability or documentation but can still be highly productive net contributors if you have a great testing team between their code and your customers
A big issue for AutoCAD was "don't lose the user's work". Customers were not forgiving of that. New features were less important.
Autodesk is still around, market cap around $26 billion. They're still selling expensive software that works, and have been profitable for over 30 years.
3d apps especially seem to suffer from bloat, which then leads to competitors getting the leg up and the original dying off; then repeat for the competitors.
You don't have to be "good". You have to solve the right problem efficiently. Find the right problem and be the solution. If you need to write a program, make an easy one. Easy to use and easy to maintain. You'll get what that means after a few years of maintaining. Nobody ever cares if you're a "good programmer" or how you feel about yourself.
Ideally you walk the line between them both. Personally, I'm in the former camp, but I'm more a business owner than a coder, so deliverables are more important than the best programming methodologies. It depends on what the priority of the business/department/team is.
What is this deliverable for? TechCrunch Demo? The only metric a demoable build, and even then people understand it'll have bugs.
There are still places where there's a drop dead date for code (firmware; physical media) but continuous deployment on the web turns that on its head - the software is constantly evolving; there's no single deliverable that's set in stone and can never ever be changed.
Developer hours is a very limited resource, better to launch the product with slow code and parallelize thanks to the cloud and optimize once hotspots are identified.
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil." -Donald Knuth.
I've worked for a startup where the plans changed enough to have significant effect on the code. Rewriting a lot of it ended up being necessary and actually well-justified.
As a more careful programmer, I wasted everyone's time making 'the right choices' when in this particular context, in hindsight, I could've known that rewriting the whole thing was a likely scenario.
If I'd get the same job now, years later and (I hope) wiser, I'd have built a much quicker, dirtier, buggier version (essentially a prototype/alpha) instead.
A problem is not only defined by stuff like the core routines of the program, but also everything surrounding it, like the structure of the code and of the program as a whole, the environment the program is supposed to be running in, and how to collaborate or manage the other people who are working on the program. Though at this point it's probably better to use a broader term like "software engineer".
A programmer who has enough experience across the whole stack for a certain problem is going to be able to deliver good, readable and efficient code in a timely fashion.
Likewise, they also tend to produce more desirable side effects - things that maybe weren't described in the spec but are a noticeable improvement (e.g., responsive UI behavior)
In security and high-availability related environments – where I've spent most of my time – it is important that you validate all ins and outs, system and function returns, check if writes succeed, in short, not unlike a chess player, to be able to fit all possible moves and scenarios that could go wrong inside your head. You probably need to naturally possess a mind that is precise and can find all loopholes.
Another way is to see efficiency through layers of algorithms and realities of real-life systems. Universities focus too much on mathematical formulas in my opinion; real systems are not clean and simple like a math function with few variabes. To understand by experience where complex systems with remote databases, shared disks and network can go wrong and write code that foresees, prevents or deals with unexpected complications is an important skill that sadly enough is hard to quantify on a resume. A lot depends on experience and knowledge, but you need to have interest and curiosity to get there.
And finally, you have those programmers that can create a more-or-less working mock-up in mere hours. In my experience, those are not always the people that want to spend a year ironing out all the bugs, but it is a valuable skill to be able to adapt and churn out something fast and iterate on it. Dare I say, the Javascript mindset. You probably need to be pretty enthusiastic about new technologies and quick on your feet.
To find not only a motivated person but the right "type" for a job position is probably not an easy task, just as it is hard for a programmer to find the right job that fits your own particular strengths and way you like to work. You might be a good programmer, but end up in the wrong environment. If you are a thorough and perfectionistic person, you're probably not going to be happy in a mockup-a-day start-up.
How many variables your functions consume depends on how much you split them up, although you'll of course end up with thousands of functions for a real application, if they each consume ~3 arguments. So, in other words, the limitation is to what degree your language enables you to split up your application in tiny, obviously simple fragments.
Mathematical functions can describe anything. Haskell consists of mathematical functions, and is Turing-complete, and because of its purity makes it easy to split up your functions into tiny ones (or at least sufficiently small).
For example, this[1] module is a Bitcoin payment channel server I'm writing in Haskell. The module describes, mostly at the type-level, three different Bitcoin networks (live, test, test-derive), and presents an interface to the Bitcoin network, which either fetches information from the Blockchain or deterministically derives test transactions.
Everything can be split up into tiny pieces like this, it just takes time, as the purity prevents you from utilizing loopholes that later turn out to be unmaintainable. It forces you to understand the essence of what you're trying to describe, because otherwise you can't capture all the invariants properly without too much duplicate code.
[1] https://github.com/runeksvendsen/rbpcp-handler/blob/master/s...
There is little correlation between theory and practice of a complex system when it comes to performance and reliability. For example, big-O notation tells you very little about the myriads of wonderful ways systems and networks can crash and burn. Disks never failed in my university classes. The more you know about the difference between a perfect theoretical system and the harsh randomness of a real one, the foresight of experience, the better a programmer you are, and this is not generally knowledge that comes from formal education.
In short, to be a better programmer, you need to know the difference between the best case ideal scenario and what is actually going to happen, usually when you least expect it...
Along the way, you'll develop a curiosity about solutions other people developed, so you'll read code more. Simultaneously, you'll develop curiosity about different tools, e.g. programming languages. This will lead you to explore them more.
It's all enjoyment feeding curiosity and lots of practice.
I'm watching my daughter's friend become a great basketball player. She's not inherently great at the game. She loves it and practices several hours daily in a disciplined manner. When it rains she puts on rain gear to practice. When it snows she shovels the driveway to keep practicing. She carries a notebook everywhere to diagram plays when she thinks of them.
Great programmers practice even when no computer is in front of them.
Being a good coder is different from being a rock star coder. In fact, rock star coders can be terrible coders and yet have large followings. Most rock star coders became popular through blogging, tweeting, hacking and/or writing trivial software modules that are widely used. Coders who work on difficult problems don't usually become rock stars.
The one and only metric is: how quick do you ship. I know what you think: this leads to unmaintainable code. That is wrong because a programmer who produce unmaintainable code doesn't ship quickly, by definition. Thats because programming works by iteration, and then it doesn't matter you can ship one iteration quickly, what matters is that you ship iterations quickly, over and over again.
Now, the game is simple, you can do two kind of mistakes: you can ship too "quickly" by writing rushed code, or you can ship too "slowly", by writing over-engineered code, for a given iteration. If you rush one iteration, you will have technical debt for the next iterations, and if you over-engineer one iteration, you are wasting time AND you are piling supposedly well written code which has no value and gonna stand in your way on later iterations (it always do, thats what level 2 programmers dont get). Of course, and thats the best part, programmers in practice tend to do both mistakes, which confuses them squared: they have a fair amount of technical debt in an over-engineered codebase.
Programmers in their career though tend to first do mostly rushed code (level 1 programmers) and then they do over-engineered code for the rest of their life (level 2 programmers). So you know you are a good programmer when you know what over-engineered code is.
Is the code readable?
Sorry this is just way to subjective. What you want is a code that's easy-to-learn. The difference? Easy-to-learn is really powerful while "readable" is not. That's because programming doesn't happen on your screen, programming happens between your ears. But first, a spectrum again, at one end you don't know anything about the code you have in front of you which means you cant do nothing; at the other end, you know the whole source code in which case you can do everything: fix, rewrite, extend, debug, run, anything.
A code that's absolutely obfuscated by all standard isnt easy-to-learn, so dont worry, yes "readability" matters of some sort. But a super readable code can be crap too, because it can just be as obfuscated as the former, it's just another form of obfuscation: flood.
A code written to be easy-to-learn means it has been written to help you getting closer to "you can do anything in the code" as quickly as possible. And guess what, the closer and quicker you are from being able to do anything in the code, the faster you ship. Rinse and repeat.
Back to programming, I feel that web development gets more credit, and as a web developer I can say that most of the development is just boilerplate configuration, made complicated by layers upon layers of unwanted but unavoidable complexity. On the other hand system programmers and game developers do more hardcore programming stuff, but may not be as much recognised outside their closed community.
So in other words depending upon the domain, a good programmer might mean a person who can figure out the configuration better and keep things nice and tidy (read 'standard') while at some other domains it might mean hardcore analytical capability and number crunching..
Um no.. what boilerplate project provides universal data management, business logic, and performance optimization that your project needs?
Coding is not enough. Is your code maintainable, interoperable? Did you ship?
What are the priorities of the project? Is your code formally verified not to have bugs? ETH just had such a bug. Has it been tested at scale? Twitter used to have fail whales.
Does your product have a community? Do you manage teammates well?
People live lives, companies build products. Ask yourself, "is my company building a good product?"
To me, someone who is "good" is just someone who has learned the language and main paradigms / tools for it, and can pick up new stuff fast. It's like a native speaker of English who can understand what you're saying and write a book on a new topic that goes over well.
Good means less bugs, maintainable code and playing well with others.
But you can know if you're bad at it. It's kind of like testing and other forms of QA in software -- usually they can attest to the presence of bugs, but not their absence.
If you find yourself not falling into the pitfalls of a bad programmer... odds are you're not programming enough but if you are doing it and avoiding those pitfalls, you have a chance at being considered good. If you have enough self-awareness to watch out for pitfalls you might fall into and avoid them in the future, you will become better than you are now. And that's really all I can promise you.
That can be difficult on the Web.
When learning electronics searching the Web for help quickly showed how useless it is. There were many explanations but no teaching and often the explanation begun at a level too far past the level of the question asked.
My guess is well over 95% of explanations I saw were just people posturing to show off their knowledge. Wordy explanations that went on for paragraphs never teaching just saying things.
I craved brief answers that taught not explained. I know 2+2 = 4 but how do you know that how do I learn to know that!
Not just electronics. When you're dealing with any kind of non-trivial problem, searching for help with sensible solutions from internet is an exercise in frustration and futility. The answers, when you find any, tend to be out of date, ill-informed or just flat out wrong. Often all three at the same time.
Simply put: most of the technical information on the internet is written by helpful idiots.
The answer of one single problem is of no use. Another simple example imagine you want to know about multiplication say 5x5 but each example tells you the answer but not how to determine the answer. Knowing allows you to find any problem one example done for you does not.
Sites like the stackexchange network were OK although quite a bit of posturing as I call it and verbose rambling answers. Or worse a good tutorial but closed for apparently no reason.
I ended up at allaboutcircuits.com it was nicely laid out and with video tutorials. It supplemented what I was learning in class.
> I know 2+2 = 4 but how do you know that how do I learn to know that!
Did you miss some punctuation?
Meanwhile, there are countless grateful, happy customers who think the kid who slapped together some PHP templates hosted on a slow, insecure $2/mo shared WordPress host is a genius rockstar. This is a more defensible position; it's just also a landmine if the business grows a lot, because any mass of PHP has a limit of how much complexity it can absorb before breaking.
Enterprise customers are particularly hard to generalize over, because each enterprise's software is like a factory, where all the equipment is totally custom made, with all kinds of quirky weirdness that may be part of the secret sauce that makes things work, and no-one really knows if it is, but just keep things working. (Actually it may be larger than a factory, including multiple factories and some supporting supply chains a la Shenzhen).
If some % of changes you make to your code are towards a simplification, I believe you are on the right track.
Not so good programmers fix their assumptions (because they need some ground to stand on) and then let a project ossify - these become legacy systems, burden, technical debt, and so on.
Another angle: A good programmer will save you from problems you didn't even know you are going to have (and you will probably never noticy it, because she or he will have your back).
Yet another take: A good programmer will find a solution to a program which is either perfect or not perfect but so clear, that another person can use it as a basis for a better solution. A good programmer shortens the way to the things you want to achieve, in any way (perfect solution, good solution and clear problem picture, communication, better documentation, explanation, more performance, rethinking, disruption, calm night shifts, and so on).
Besides: Programming and development is actually very hard, many brilliant and curious minds haven't searched for another occuption after they started programming.
Did you get a computer science degree? Did you land a job at a good company to write code after an extensive interview? Have you been able to keep that job for a few years? Have you written code other people find valuable? Do other engineers you respect commend you on your contributions?
If you've answered yes to all of the above or at least some then congratulations you're a good enough programmer. If not then there's room to grow and you can become one. Either way I laud you in your choice of career. It's a good one, and there's no reason to be handwringing about where you fit in the spectrum of engineering skills.
Just always be learning.
It's easy to fool yourself if you're just getting by work day to day thinking everything is going well until one day it isn't.
Validation might be vanity but feedback is important. Trying to figure if you are a good programmer is the first step to actually being good, willingness to continuously learn and self-improvement is a key trait of good programmers IMO.
But others, including myself, ask the question because we want to, as you say, 'always be learning'. We might be insecure, for example, about getting stuck at some equilibrium that isn't optimal, and just fishing for where to go next.
For example, it was through similarly-themed threads on HN that I learned about functional programming. I learned how important immutability might be, and to try and keep my functions and methods pure, even if I'm not going all in on the functional stuff.
Hell, even just thinking in terms of separating data from code was a revelation that I might have missed without HN functional weenies constantly submitting articles that boiled down to that as a point.
Anyways, not disagreeing with you necessarily, just nuancing.
Who cares about good code ? good code doesn't mean anything, the only thing that is important is working code. If your program works but the code is not "good" people will still use it.
A good programmer is someone who is able to write code that works
in general you cannot even prove, whether a program does the right thing...
Sure, come code you write once and never have to touch again. But that's usually the exception; popular programs always have more feature requests and bugs and have to keep up with the changing input/output environment. If it's bad code it will fall behind and be forgotten, because it's just too hard to maintain.
You may have a piece of code that works now. But if it is rigid changing anything will be hell and require touching almost every part of the code. This of course will eat up time.
If it works but it is fragile, changing something in one place may break something else in very different place.
If your code works but is immobile, you will have to rewrite it if there is similar need in another system, but your code is not easy to reuse.
If your code works but has high viscosity future changes will be most likely done as the ugly hacks which won't help with any of the features listed above.
(I've omitted three more characteristics, because they are more of the result going overboard trying to avoid these four).
So to answer who cares about good code: anyone who will have to deal with it later.
The programmers who don't respect these principles tend to not being able to produce a code that works, so I agree with you
> Is the code readable?
Readable code may not be good code. More readable code almost always means less efficient code. Readability is a trade off.
> Is it easy to extend?
Changing requirements are a thing for sure. But in almost every cases I came across, planning for shifting requirements always misses the point. It is much better to stick to your current requirements and keep your code simple, than introduce things that complicate your code for requirements that may or may not happen. Extending simple code is simpler than undoing code and replace.
> Is your code efficient?
It's very hard to self determine whether one own's code is efficient. Almost every one will think their code is efficient.
> can you write it quickly?
Again people tend to think that they are fast at writing code whatever their actual speed.
-- the reality is that it's really hard to qualify good or bad code. Self assession is particularly useless.
Can you give examples? I'm not sold that the "low hanging fruit" of readability improvement (empty lines to break up "paragraphs", breaking up unintelligible one-liners into several lines, etc.) degrades performance. My intuition is that the compiler/interpreter ends up producing almost identical runtime code and therefore similar performance.
Unless you mean more along the lines of expressivity (i.e Python and Ruby can get a lot done with fewer statements compared to C), but to me this effect is in a different category than readability.
foreach (var item in items) {
if (items.Where(item2 => item.Upc == item2.Upc).Count() != 1) {
item.Duplicate = true;
}
}
This is the most readable and straightforward code I could come up with for the task; it's also not particularly efficient, since it does at least twice as many comparisons as necessary (more if there are actually duplicate items). To make it more efficient would require extra loops and manually indexing them to skip over comparisons that had already made; in this context I decided against this because the performance impact was minimal since there are other far less efficient portions of the code which would best be addressed first if the program turns out to be too slow.Note that this was conceived in just a few minutes of reading your code, deciphering syntax only remotely familiar, and figuring out what was it supposed to do, all with cold start (I haven't written much today yet). Something went wrong with your thought process.
if (items.Count(item2 => item.Upc == item2.Upc) != 1)
With that correction out of the way, here's the code if I used a HashSet (you suggest 'a. k. a. "dictionaries"' but that is slower and I don't need the other half of the mapping which they would provide): var set = new HashSet<string>();
foreach (var item in items) {
if (set.Contains(item.Upc)) {
item.Duplicate = true;
} else {
set.Add(item.Upc);
}
}
To my eye, this is less readable; in addition to having twice as many lines and an extra variable, it also takes extra work to figure out what it does; whereas my version does exactly what it says: if the UPC appears more than once, it marks the item as a duplicate.For a final comparison, here's an implementation of the extra loops and manual indexing I suggested:
for (var i = 0; i < items.Count; i++) {
for (var j = i + 1; j < items.Count; j++) {
if (items[i].Upc != items[j].Upc) continue;
items[i].Duplicate = true;
items[j].Duplicate = true;
break;
}
}
This isn't significantly longer than the HashSet-based version, but it is even faster to run (I just benchmarked it) and also doesn't use an extra object which takes memory and needs to be managed and garbage-collected later.In conclusion, while I appreciate your suggestion for a possible alternative implementation, I do not appreciate your impugning of my abilities with the suggestion that "something went wrong with your thought process", and implying that I may not be aware of basic data structures.
Not to menion that:
> you suggest 'a. k. a. "dictionaries"' but that is slower
In what way you think mappings are different in implementation than sets that makes them slower? They only need to carry one more pointer, and you're already writing in a language quite detached from bare metal.
One more thing, since you decided to "correct" yourself instead of letting the mistake slip: your "working" code is still wrong, unless something very weird happens in the data (but then calling it more readable this way is fundamentally wrong).
O(n^2) I do not dispute. "Landmines," however, I take offense at: my naive implementation can still check 10,000 items in less than three seconds; should this ever become a bottleneck I assure you that I will adjust the implementation accordingly. Considering that hitting this number would require expanding the entire company at least tenfold, and knowing how other portions of the code work, I feel justified in saying that this is likely to be the least of their problems.
> you're now justifying them by linecount and readability (actually more like familiarity with using sets and mappings).
The entire point of this thread was justifying by readability, so yes, I am. I'm well familiar with sets and mappings, I just don't think that they're the best solution for this particular task.
> In what way you think mappings are different in implementation than sets that makes them slower?
I don't know the internal implementation details, but having just benchmarked it I can tell you that Dictionary<string, Item> is roughly 8% slower than HashSet<string> for two otherwise identical implementations of this method.
> You have just proved my intuition about your abilities.
Likewise. From the preceding conversation, I conclude that you are inclined to prematurely optimize at the cost of maintainability and that you tend to look down on and make fun of anyone who you believe knows less about a topic than you, without taking the time to consider their point of view, or even basic politeness. You may not think that this description accurately depicts you; but then I don't think your opinion of me seems to be correct either.
Considering that I have now spent far more time than this code will ever run for arguing the point, I'm going to step away from this discussion now. I feel that I have made my point; increasingly heated argument seems unlikely to affect the outcome of the debate.
If you're satisfied that the loop you presented runs for a time comparable with three seconds for merely 10000 elements, it says plenty enough about your craft.
> [...] I can tell you that Dictionary<string, Item> is roughly 8% slower than HashSet<string> for two otherwise identical implementations of this method.
Ah yes, benchmark comparing non-implementation (abstract class) with an implementation (concrete class).
> From the preceding conversation, I conclude that you are inclined to prematurely optimize at the cost of maintainability
No. I just tend not to leave behind ridiculous algorithms, especially when an acceptably efficient solution is of comparable code complexity.
> [...] You may not think that this description accurately depicts you; but then I don't think your opinion of me seems to be correct either.
Parts of it, yes, they do match. I'm an asshole that laughs openly whenever sees statements that look ridiculous made by somebody who considers themselves an expert (note that it doesn't matter whether they are or are not actually an expert). But then, it's not my code that takes three seconds to walk through ten thousands elements when -- as napkin calculations show -- it should take under a millisecond.
Incorrect. Most practices like meaningful variable names, logically separated functions and classes, comments where appropriate, etc have absolutely no impact on performance. Principles like DRY and KISS and YAGNI typically also lead to better performance. Only in rare isolated cases might there be a conflict, eg. where a more cryptic algorithm have better performance than the straightforward.
The right way is to write modular code, where each class/function has simple and clear responsibilities. In that kind of code, changes are usually isolated and clear.
A programmer who thinks that they are bad at programming is almost certainly correct.
On a team, one of these people is more dangerous than the other. Knowing which is the greatest wisdom.
If the problem is a common one and nobody else is able to solve it people will use your code... even if the code isn't good.
If you want to generalize, follow the 80/20 rule - 20% of the effort results in 80% of the benefit. Think like a business owner. Identify what the one or two key metrics are and come up with ways to efficiently ship ideas to test to improve them. Write code that is easy to test. Add high value tests. Avoid perfectionism.
I've observed that especially correctness is the main line that separates a master programmer from a mediocre one.
If you are constantly making errors and not testing properly, not checking the integrity of your data, etc. You are just mediocre and are probably being held at your position against your will.
Software development is hard. Unlike many other building tasks that humans run into, software is rarely "done". Launch of software for most of us means the code we've written has just been promoted to a point where now it's important, and will likely be what we work on for the near term future.
So, what makes a good software developer? Generally, programming's the smallest part of that puzzle. Working effectively with others ranks up there. Business acumen. Communication skills, both written and verbally. Understanding release cycles, revision methods, standards, etc. All the things that developers don't want to care about because they aren't writing code, those are the things that make good software developers.
That is a bold statement. All the things you list are true, but it also depends on what you are doing. For most Web/Mobile/Enterprise apps you are probably right. But then there are also some areas like graphics programming or AI were the algorithms can absolutely be the hard part.
I consider myself fairly good in my domain (Fullstack but mostly backend) but when i see what some people in graphics programming (or Games in general) or AI are doing, i feel like a newbie. In my domain, i rarely have to deal with complex math, it's more about writing readable, clean and well tested code that is well designed in terms of architecture. But in some other areas you actually regularly have to face pretty complex problems where the stuff i just listed kind of becomes the easy part.
On the other hand if you're building a service for a business, like an auth layer or a payment system, the mistakes you make will live on and on and on. And usually you only get one shot at creation before it's in support for a very long time.
But to be a good at programming/developer. I would say know enough too know what questions to ask and make sure you talk with people on the client side often. Focus on whats important to them, and get change management and security onside before going near prod.
Chess is easy. You get the chess board, learn a set of rules, and over time learn how to pick the right piece to play the game fairly well.
Being good at chess/programming would be totally different from knowing "whats happening programming/chess".
type I = kernels, database query engine/optimizers, compiler internals. type II = glue libraries together with a high level language to solve business goals. type II often rely on type I's work.
The only difference is, the type I's "business" is algorithms and optimizations instead of yet another CRM or crunching some sales data. The underlying science behind what they are doing with it is difficult - just like dealing with business problems are, and most of them will succeed or fail in their efforts for the same reasons - ability to communicate and work with others.
What.
There is one rule I try to go back to, especially when work starts to pile up and things fall by the wayside. YAGNI.
First, it is far too broad. What does "good" mean? Good enough? The opposite of bad? Compared to whom? And even "programming" is a ridiculously vague thing-- everyone who has worked even a year in the SW development profession will know that programming is only part of the job and that there are many different roles, many different kinds of skills.
Next, what is the intent of even asking that question? What can one do with "the answer"?
Also learning from someone better than you will help you get better at least 10x more than practicing yourself.
Computer science is a branch of mathematics and it is all about solving problems on whiteboard in front of peers.
I beg to differ. I did http://loup-vaillant.fr/projects/ussm/ only for myself. Its release, documentation, and the few external users multiplied its usefulness accordingly, but even if I didn't release it, it would still be useful.
- It keeps workings
- It's not hard to explain to a new team member how
Then you are an excellent programmer.