20 Years of Programming (2020)
flooey.org
flooey.org
- I don't think of myself as a {language} programmer. People will ask what language you code in, and I will throw out a few current ones. But I don't think of them as some particular skill that's hard to acquire. If I need a new language, I'll read the tutorials, and then I'm able to find my way. Only exception is c++, that one I still regard as a bit of a skill, where if you haven't tried it you have a lot of concepts to learn.
- A lot of the skill isn't coding, it's domain knowledge. Not knowing what you are building is the greatest impediment to building it.
- Another huge barrier to becoming a good coder is not respecting the craft of coding. Typically if you come from domain expertise, you are prone to this problem. "I know how trading works, I just need this coded up". This attitude will get you crappy code. In fact just needing something coded is code for not actually knowing what you want.
- Satisfying things can often be closer to the code than the domain. Things like finally figuring out how to get the most out of a lock free ring. Nothing to do with the domain, but oddly satisfying. Another one is being able to reduce the size of the code.
- There's a bunch of ancillary skills that you don't think of as programming, but you need to know them. Version control, devops-type stuff like how to provision a server. Feel tedious but again you can't really do the job without doing all of the job.
As someone who first coded seriously 40 years ago, and who keeps in practice on side-projects, this is where I find it hardest to keep up: the complex tooling and processes around actually deploying your code in a production environment. Reading HN has been invaluable in maintaining some sort of awareness of what is current.
For one interview, the take home challenge was to write a bit.ly clone. I decided I would show off my abilities to do load balancing on the web server and horizontally scale a database.
I wrote my application with a dockerfile for ease of deployment. I set up multiple A records to point to each docker container's IP for a simple DNS round robin load balancing. Each container had a unique hash string printed in the bottom right corner of the website so you could demonstrate to yourself that load balancing was occurring.
I set up 3 postgres databases with simple modulo hashing for each shard; I use an 8 character hashing function (forget which) and did a modulo on the number of shards. This directed each shortened link to its relevant shard, with the shortened form of the link as the key (note: this is not the best solution to the problem; look up consistent hashing if you want a better solution). Which database connection string to use depended on the result of this modulo
All this was deployed with relevant kubernetes service and deployment yaml files, with ci/cd hooks provided by my VPS (I think vultr or digitalocean)
When I was explaining all this in the interview, I was actually interviewing with someone who was lower ranked than the job I was interviewing for (she was a junior engineer with maybe 2 or 3 years of experience, I was interviewing for a mid level role with 5 years of experience)
She said "so, it seems like you're more interested in devops than application development?"
I said "no, I actually really hate devops, but these are the skills I get interviewed on most so its what I practice".
I didnt end up taking that job.
That's probably for the best. If a company's using their junior devs to run the interviews, it probably also has a number of other pitfalls, hidden during the interview process...
Sure! For the past 10 years I've been making a 2D skeletal animation tool. It's a desktop app built with Java, so I get all the nice Java tooling, hotswap, etc. There's no Swing junk and it's not built like most productivity apps. It's built like a game using OpenGL and runs at 60+ FPS. It uses a lot of my own OSS, like libgdx and my 2D UI framework scene2d.ui. NIH is a thing but there is also a lot to be said about not needing to rely on others and wade through their messes. With this setup my productivity is super high.
Instead of scaling up the company and moving from a dev role to one of those nasty spreadsheet people, I stayed doing what I like. Even after 10 years I'm still the only developer on the desktop app, so all the code is mine from the start. No cruft! It's either pristine or my own uglies. I ran the company lean as long as possible. That was something like 5-6 years working long days, but I like working on it. Nowadays it's more relaxed and a handful of others work on runtimes and customer support.
I wrote this blog post 10 years ago, just after the app first saw some success: http://esotericsoftware.com/blog/building-spine
The trick for me was to fill a niche that I was familiar with and leverage the tools and libraries I had already been working on for a long time. There were competitors already established in the niche. The now defunct Spriter had a 9 month head start. Flash actually comes close to competing, but you need to extract the animation data from it and write your own runtimes.
That is probably another reason Spine is successful. There are many tools for doing animation: Blender, After Effects, Moho, Toon Boom, etc. Those can be impressive if you're exporting video (eg making cartoons) but they aren't easy to bring into a game. Spine is similar in that you can make animation, but it also provides runtimes to render the animations in games/apps. Only a few competitors do that, and they do it pretty poorly as an add-on, while it's a main feature for Spine.
Spine is also set apart with a focus on good (if nonstandard) UI/UX, workflow, and polish. There are no right click context menus anywhere. That was a sort of experiment, but I like it. It forces placing functionality in UI that is discoverable. One reason UI is so important is that Spine succeeds by making the workers happy. Make a tool people love to use and they'll naturally push the businesses they work for to buy it, if only so they don't have to suffer some other tools. Couple that with Robin Hood style pricing so you are affordable for individuals but more expensive for businesses who can both afford a higher price and stand to gain more from using the tool.
I greatly dislike subscriptions. I won't buy any software that is subscription only, absolutely not ever. Given that, I also won't sell my software that way. Instead I sell to individuals a perpetual, lifetime license that gives ALL future updates. Some think that is crazy, leaving money on the table. It costs to bugfix and develop new features right? IMO it doesn't matter. It's more important to have many individuals using the latest version who will be proponents at their jobs. That leads to the next part, which is businesses pay annually. It's the same software, but the cost is per year per seat for a business. That gives recurring revenue and makes up for not gouging individuals with a bullshit subscription.
TL;DR is something boring like: find a niche, find ways to do things better, add value in new ways, and structure pricing to encourage individuals while taxing businesses.
So I know it's possible and it was nice reading your writeup reminding me I wasn't just lucky. (My father's industry is very niche and basically had zero competitors for the segment of the market (20-50 employees).
My plan is to try again soon with something I am way more passionate about.
The end game is to either sell out or hire others to handle the drudgery. Ideally you can work or not work as you choose and everything runs smoothly regardless. How much revenue you divert to that cause is up to how much you can stomach doing yourself. It took me 5-6 years to reach burn out and need assistance. Now I'm in that ideal zone and it's much more comfortable. I doubt I'll ever sell as I'd have too much free time.
I do think it's possible to have a product you hate and lots of reasons selling and supporting it can be horrible. I just wanted to point out that even if you loved it, you'd still have some of those aspects. Finding a successful toehold is difficult. You might try and fail a number of times before doing it again. I'd be wary about giving up on a success unless you're super sure the annoying bits can't be massaged enough to be tolerable.
One thing I haven't had to deal with is marketing. I started the business with a Kickstarter but otherwise never had to actively peddle my wares. That's mainly due to it being a niche market, that the nature of animation is flashy/appealing and doesn't need to be explained, and by focusing on UI/UX/polish so users enjoy using it.
Cloud deployment and CI/CD and networking and all that stuff absolutely matter, and must be done right to avoid a world of pain, but often it's largely a one-time setup - and then you focus on the same old tried-and-tested coding techniques and principals to Get The App Done.
For example you spend a month on the infra, then a year building, maintaining and enhancing "the app".
Maybe I'm wrong but so much tech discussion here and elsewhere seems to be on the infra part, lately. But coding well, including interacting efficiently with resources such as DBs, just isn't as prominent I don't think?
Maybe there's nothing to say of course. Or maybe the old microservices-vs-monoliths is exactly that...
In my experience, this is not true. At any large company with thousands of engineers hammering the CI/CD/development thingys, a CI/CD failure is an incident unto itself. And it often requires A LOT of maintenance.
And you can't just offload it to gitlab or whatver because you WILL need to build abstractions over it.
What I have found particularly infuriating is large companies with billions of dollars in revenue choose to completely ignore the productivity decline that comes from poor CI/CD, and then demand faster work from engineers who are hamstrung by poor infrastructure.
But usually, I would expect that "Project ABC" will build all its infra and CI/CD usage early on and then just proceed to consume that CI/CD as a commodity service, with ad-hoc changes needed to continue playing nicely with that service.
>> What I have found particularly infuriating is large companies with billions of dollars in revenue choose to completely ignore the productivity decline that comes from poor CI/CD
I hear you :-(
That's what success looks like. Not everybody is successful, and from how people talk about it, it looks like a lot of people have never experienced it at all.
I agree. But in a professional settings, this is usually less of an issue. Everything is set up when you join. You still need to learn about the tools but you don't need to set up things for scratch like you would do for a personal project.
I remember how I was struggling to learn about Docker, renting instances on AWS, setting up services my app would need. This killed all the joy of my project. In my company, I routinely deploy hundreds of servers in data centers across the world, use all the managed DBs and various services available. Much simpler.
I’ve also been pretty impressed with the serverless framework - particularly when used as a wrapper round traditional frameworks like flask or express.
# sudo useradd -r -s /bin/false userofservice
# sudo cp thisfile.systemd /etc/systemd/system/nameofservice.service
# sudo systemctl enable nameofservice || sudo systemctl daemon-reload
# sudo systemctl start nameofservice
[Unit]
Description=What the service dose
Wants=network-online.target
After=syslog.target network.target network-online.target
[Service]
User=userofservice
Group=userofservice
WorkingDirectory=/srv/nameofservice/
ExecStart=/usr/bin/runtime somescript.xyz
ExecStopPost=+/srv/crashreport/report.xyz %n
Restart=always
[Install]
WantedBy=multi-user.targetI strongly believe that learning different languages will make you an overall better developer if those languages make you learn different concepts.
Such as learning pointers vs garbage collection, imperative vs declarative, single-threaded vs concurrent, dynamically vs statically typed, highly specialized syntax vs generalized syntax (s-expressions) and so on.
Increasingly, it's about current paradigms and frameworks. Concepts are potentially buried in these.
At first I thought the most important thing about a language is its popularity.
Then I thought it's compiler vs interpreter.
Then I thought it's OOP vs functional.
Then I thought it's static typing vs dynamic typing.
Now I think the 3 most defining priorities of a language is:
1. The culture and community around it (not necessarily == popularity)
2. What's its default way to handle memory: GC? RC? Borrow? Just write unsafe code?
3. How its macro works? Is it so powerful that people all writing their own DSLs?
In this order, cause obviously 1 can "overwrite" 2 and 3.
I took the opposite direction; I went deep into Scala, and while I was productive from week 1, I'd say I was probably learning useful generally-applicable stuff even 7 years in. You can write Java in any language, and many people have successful careers doing so, but IMO for a rewarding career you want to learn something that's not easy; getting deep into a particular language or framework isn't the only option but it's one that's easy to explain.
100% agree. Am a consultant, and its frightening how many FTE's of my client, don't know what business their employer is engaged in. They aren't even beginning to learn the business vocabulary.
They are all frogs in the Terraform pond.
True, but being fluent in a language still takes a bit of time, especially when you work with large codebases where all sort of obscure language features are used. Besides, languages tend to be associated to some domains. For instance, your frontend javascript developer may need more than just learning a bit of C if they want to write some code for embedded devices.
I almost always have a look at some thing or other on the weekends, home projects, problems I think I solved badly at work during the week or experiments on ideas for things coming up.
You know what is kinda wacky? I still feel exactly the same as I did when I started. Things I have done before get done very quickly or better and then I hit a challenging new thing. I love this shit.
My greatest fear is to reach a point where I don’t feel like "I love this shit" as I do right now, I hope I’ll feel the same as you in 40 years!
By the time I was in college for two years, I found other things I enjoyed much more than programming. From 1994 to the present, coding has become no more than a method to exchange labor for money to support my addiction to food and shelter.
I spent the first decade and a half of my adult life as a fitness instructor and running with friends as a hobby.
My wife and I now travel half the year, “nomadding” flying between cities every three weeks.
I still spend of time after work at the gym of whatever hotel I’m at.
In programming, if you have a modern IDE like the Jetbrains ones, you have all local source code indexed for auto imports, autocomplete and enhanced code search, no braces errors at compile time because the closing one is added automatically and if you still manage to put it wrong, there's an instant notification about it and a one-click smart autofix, also there's full local history if you mess up, without even taking the time to make small commits, then there's CI/CD pipelines depending on what you're building, you can also use Sonar in IDE and in CI, also Sourcegraph, and even if some of this was already possible with good ol' grep, it was not the same IMO.
Then there's Copilot and ChatGPT, for many uses including prototyping stuff you don't even want to take the time to RTFM.
But yeah, I can recognize that the workflow looks the same, because it's the same job, we still use keyboards and monitors, and we edit files on drives hoping that it produces some expected result, and get disappointed in our lives when it doesn't.
And lots of us are still using the basic UNIX tools in their GNU versions like grep, awk, sed, vi/vim, etc., aged 30 (vim, ssh) to 50 years (grep, sed).
Including myself. That's sort of my point. It's always fun reminding the Junior Engineers that, unlike whatever flavor of the month library the blogosphere calls The Next Big Thing, the majority of the stuff that comes preinstalled into their multiarch container image is older than they are.
I'm not a dinosaur, I'm a native.
But some things are quite different in the last 40 years. The standard libraries are much better. If I need a map, I don't have to implement a map; I just use the one in the standard library unless there's good reason not to. The amount of code that I don't have to write, but can still use, has gone way up.
Debugging tools are better. Code sanitization tools are better. Unit testing tools are better. Type checking is better (for statically typed languages).
Oh, yeah, and the monitors these days don't bathe you in soft x-rays.
Those may not be the same level of change as moving from octal to assemblers to compilers with punched cards to terminals with monitors, but they still add up to a significant amount of change.
Not that much has changed. Sometimes I put on a bathrobe for Zoom calls now.
The amount of code that needs to be done is the same it just does a lot more.
I started in 8085 assembly language. Everything had to be done from scratch. It was still similar; see a problem, work out how to solve it, write it and debug it.
It is certainly much better now. I am not sure about debugging. There were years at a time when I only used IDE based debuggers, but now, with much more containerisation I probably do as much visual code inspection to solve issues as I ever did.
Now I can stand up an entire data center with databases, unlimited storage, etc by creating a yaml file.
Even 25 years ago I was optimizing code by using inline assembly to get the performance I needed.
I have a temperature controller and a platinum temperature sensor with a dedicated 3 wire board controlled by SPI, 30 bucks. Controlling 12V 5A motors with PWM another 30. All in C++ on the board, integrated with mqtt, nodered and Caddy for the UI SSL. So easy with parts from Ali and datasheets available. (Sometimes even useful existing libraries).
I reflect back on my earlier days and also realize my changing views. I used to take joy in solving problems in any way possible. I now take joy in solving problems with as little future headaches as possible for everyone.
Eventually the dot-com crash hit, I went back to school, and got back into programming a few years later and kept going.
I’ve tried going down the management path for a few years but made the swing back to programming full time. Now I’m at another peak where I can’t see what’s on the other side: do I have another twenty years in me?
It’s fantastic. And users don’t care what your stack is, a long as it woks.
Now,
I have to diverge here, and say that I'm a fan since F-Company days (which was ColdFusion wasn't it?), and a customer of DistroKid (well, my own kid took over the subscription and I need to get another one now).
Seems to be alive.
Some of my thoughts:
- Having the theoretical background is most definitely worth it. I often notice a lack of very basic knowledge on data structures in people who do not have that background.
- Having come into contact with multiple programming paradigms (imperative, object-oriented, declarative, logic, ...) gives you access to more techniques to solve problems and to more ways to think about problems. I believe this is useful even if you only "tasted" these other techniques.
- I notice that people with a theoretical background are often more fluent in learning new techniques and concepts, and in applying techniques and concepts that they know from one language in another language. Understanding concepts and techniques and being able to apply them in other languages is important.
- I believe the field of programming is very big and one person cannot have deep knowledge on every domain in that field. So you have to make choices. In that context I really believe in focusing on broad knowledge in a certain domain and very deep knowledge on a subset of that domain. For example, I personally have broad knowledge on backend development, and deep knowledge on C# and ASP.Net Core.
I really do think that deep knowledge is useful. Developers should try to obtain deep knowledge of their main programming language. Deep knowledge means that you know how to write something in a clean and compact way, that you are familiar with the language's idioms, that you are aware of all mechanisms that the language offers you to write code in a clean and compact way. The same goes for deep knowledge of libraries. Deep knowledge is something that you obtain through experience and by keeping yourself updated on the evolution of the language or library.
The reason I mention "deep knowledge" explicitly is because I have the impression that deep knowledge is not valued that much anymore. Developers jump to the new hot library before they get a full (or even mediocre) understanding of the previous hot library, or they simply do not take the time to learn the language or libraries that they work with. This can then be seen in the code: bad custom code for things that are built-in in the library, using the library in a non-conventional way, ...
I would honestly take a 50k paycut if I didn't have to play management games to do my work.
I don't get it. Please someone explain this line to me.