
How I became a better programmer (2017) - _ttg
https://jlongster.com/How-I-Became-Better-Programmer
======
jaequery
About a decade ago when OOP was just booming in the PHP world, I wrote my own
database abstraction layer because I was a bit tired of the ORM's that existed
at the time (Doctrine, Propel, ZF). Taught me what makes a beautiful fluent
interface and the difficulties of achieving them. Helped me to think about UX
experience at a code level, trying to achieve an interface for developers that
fits all ages. That was an eye opening experience.

Then I wrote an MVC framework from scratch because I thought others were too
heavy (ZF, Symfony, etc). It helped me understand an application development
at a deeper level, figuring out the best strategy for code modularization,
organization, and performance. It helped me to learn creating something that
looks so painlessly easy to use is a pretty difficult task (there will always
be something ugly sticking out). It took me on a ride of what happens with
extreme level of abstractions breaking up code for each roles and a simpler
route much like the Sinatra / Express bootstrap approach.

I've found a new level of respect for those who develops codes at a macro-
level (frameworks / libraries). There are lot of thoughts and love been
applied to them. DHL (Rails) is up there, as well as John Resig (jQuery). I'll
also give a shout out to Sequel (Jeremy Evans) while at it for creating an ORM
that is almost perfect. Vue.js (Evan You) also particularly deserves a lot of
credit for what he is doing in the front-end world. I like React too, can be
fun, but I did not like the whole Redux experience.

I think what makes a great programmer is that they are able to think at a
macro-level, thinking about how 'others' will use and apply the code, and
making it look deceptively simple.

~~~
acemarke
> I did not like the whole Redux experience

Out of curiosity, anything specific that concerned you?

If you haven't looked at Redux lately, a lot of stuff has changed. We have a
new official Redux Toolkit package [0] that is now our recommended approach
for writing Redux logic, our new React-Redux hooks API [1] is easier to work
with than the classic `connect` API, and we have an updated list of
recommended patterns in practices in our Style Guide docs page [2] that should
result in simpler and easier to understand code.

[0] [https://redux-toolkit.js.org](https://redux-toolkit.js.org)

[1] [https://react-redux.js.org/api/hooks](https://react-
redux.js.org/api/hooks)

[2] [https://redux.js.org/style-guide/style-guide](https://redux.js.org/style-
guide/style-guide)

~~~
tobr
I’ve used Redux for years, and tried many different approaches to it. But when
I look at Redux Toolkit I don’t see much of what I’ve enjoyed about Redux.

To me, Redux is just a pattern for how to handle immutable updates. Redux
itself isn’t even important. Every layer of abstraction over these plain, pure
functions and serializable objects just obscure the simplicity of the
architecture, in my opinion. Some of the recommendations expressed in the docs
are reasonable, but you don’t need a library for that, just the patterns.

In my experience a lot of the confusion beginners have with Redux is because
they think it is a framework that will do things for them. In that light, it
looks like there is an unnecessarily large number of parts to understand. I
think they often miss the fact that there is no magic, just function
composition. The clearer that is, the easier it will be to work with the code.

~~~
apotheon
Before Redux was probably even an idea, when Flux was reasonably new, my boss
at the time basically said this new Flux thing looked like what we needed for
a project and told me to learn about what made Flux tick and start building
the project on that pattern.

I dug around, I looked at Facebook's documentation and propaganda for the
pattern, and I came to the conclusion that Facebook people didn't know how MVC
worked and decided to invent their own thing as a replacement. Then, I started
building something, and realized that Facebook's Flux dispatcher library was
getting in the way.

I built my own from scratch, and suddenly I understood the elegance of the
pattern. It was not at all what Facebook's marketing about it said. It was not
an MVC replacement at all. It was something else entirely, and should never be
treated as an MVC replacement. The explanations about how it solved problems
with MVC were nonsense: it was just a different pattern, for wildly different
use cases, and the MVC-replacement propaganda I read still made it seem like
people at Facebook just didn't understand how to use MVC.

My dispatcher was lightweight and clean. It was one of the nicer bits of code
I've written, and I'm still quite proud of it, years after leaving that job.

I was the principal dev on that project. After a couple of weeks of building a
complete application with a deceptively simple architecture that did all the
heavy lifting with ease, I took a day off.

It was one day. It was a Friday, which meant that for the people there a
quarter of the day was taken up with meetings. Somehow, in the midst of this,
disaster struck.

When I came back on Monday, I discovered that the boss and a co-worker had
decided they would just replace all the guts of the application with a pile of
libraries designed for MVC, but bend them into a Flux shape, kinda, sorta. The
result was slower to build (q.v. JavaScript "build" crapola), slower to
deploy, slower to test, and slower to operate. It was slower to debug, slower
to extend, and generally miserable. It required fixing or changing something
in the plumbing almost every time a feature had to get added. My work on a
small, beautiful, efficient architecture was destroyed, and nothing we ever
did with that application ever actually required any of what they did to it.

They told me I hadn't documented how to use the architecture in place well
enough, so they had to rewrite it to get anything done, but the result was
half-broken, and I had to finish what they started to be able to continue
myself on Monday, and they never actually did anything with what they created
that justified that claim.

A couple months later, I learned they hadn't actually looked at the
documentation I wrote at all. They just decided that my bespoke implementation
must be wrong because I didn't use existing tools. Well, shit, I didn't need
existing tools. The whole dispatcher was something like twenty lines of code.
The rest of the basic structure was in parts even smaller than that. The
"rewrite" of the system was probably a thousand lines of library code (I'm
guessing; I didn't count) and close to two hundred lines of junk around them
to make things fit together, all so we could write a bunch of boilerplate for
every single thing we wanted to do thereafter.

(Note that my references to all this code excludes the React tools themselves,
installed directly from npm because yarn wasn't available yet.)

long story short:

I think I understand what you mean about a pattern, as opposed to a framework
or toolset. Also, even if the origins of Flux (and, thus, ultimately of Redux)
were in some Facebookers possibly grossly misunderstanding how to apply the
MVC pattern, Flux as a pattern was an excellent approach to addressing some
specific needs for application architecture.

------
Crazyontap
My comment is a little tongue in cheek but Here is "How I became a more
productive by becoming a worse programmer"

\- I stopped worrying about best practices and just do it.

\- I hardly refactor my code unless I'm using the same thing for the fifth
time. I just copy-paste it instead.

\- I never think about optimizing code until I really really need to.

\- I write what gets the shit done quickly. I don't care if writing a Class
would have been better than a function.

\- I love old boring technologies and believe you can still make amazing
websites with just PHP and jQuery.

\- I don't come up with clever one-liners anymore. I write a 10 line _for_
loop which I could easily replace with a clever one-line code golf.

\- Instead of writing my own code, I usually search Stackoverflow first to see
if I can do some copy-paste it instead.

~~~
kovac
Not to be rude or anything but if you continue down this road productivity
might be the only thing going for you and you'll soon realise you are the only
one who can work with your code.

Substitute software engineering with any other engineering descipline with "I
stopped worrying about best practices" and you will be able to see what's
wrong with your approach. But then again, if it's php, your domain doesn't
require too much care.

~~~
readme
Exactly. I had coworkers like this, and their code was impossible to
understand. To make a simple change to it, it would require days of
refactoring just to know you weren't going to introduce a bug.

It's not being more productive, it just seems that you're getting things done
faster because you're taking out a loan on the quality of your software (i.e.
technical debt) with every line you write.

~~~
kovac
"It's not being more productive, it just seems that you're getting things done
faster because you're taking out a loan on the quality of your software (i.e.
technical debt) with every line you write." This. When someone does this in a
hurry or because they didn't know better, it's understandable. But when
someone thinks that this style of working is superior, that's a huge problem.

~~~
Drakar1903
Paying down tech debt is like brushing your teeth, if you don't do it
regularly, you'll end up with more pain and a higher bill at the end.

------
kqr
The points on the fluff in particular resonate with me because idespite being
a fairly good software engineer, I would say it was only recently I truly
started seeing past the fluff.

However, typing this out, I realise I would have said the same thing 10 years
ago, and 5 years ago, and I probably will again another 5 years from now.

I think the truth is that we're _always_ missing the forest for all the trees
-- only at increasing levels of abstraction: at first, everything is foreign,
then syntax becomes fluff, then APIs become fluff, then patterns, then
languages, then compilers, then ... I look forward to learning what the next
level of fluff will be.

> The majority of the stuff being released every day is just a rehash of the
> same ideas. Truly revolutionary stuff only happens every few years.

Maybe not even that often. I can recommend Old Is the New New by Kevlin Henney
for a good, historical perspective on how little actually changes sometimes:
[https://youtube.com/watch?v=AbgsfeGvg3E](https://youtube.com/watch?v=AbgsfeGvg3E)

Edit: now this was more interesting than I anticipated. What _is_ the next
level of fluff? Concurrency? Advanced data structures? Phrasing problems for
SMT solvers? Probabilistic modeling?

Or are the things I picture as fluff just specific techniques, because the
next level of fluff is so meta I wouldn't even recognise it now?

~~~
MaxBarraclough
> then languages

Perhaps a slight digression, but: I think there are very few people who can
really say they can 'see through' the difference between languages.

C++, Erlang, Prolog, and Haskell, are very different languages, all the way
from the shallow matter of syntax, through the type system, and even down to
the fundamental model of computation. When I hear someone say _If you learn to
program in one language, it 's easy to learn another_, I assume that person
doesn't know much about programming.

~~~
echelon
> If you learn to program in one language, it's easy to learn another, I
> assume that person doesn't know much about programming.

This is flat out wrong.

If you know Python, it'll be easier to learn Rust than having to learn Rust
from zero. Engineering is about problem solving and formulating solutions with
algorithms and data structures. If you don't know what those are yet, it'll
take much longer to learn.

Learning one of _anything_ makes learning the next one easier. Programming
languages, spoken languages, musical instruments, sports cars, martial arts,
sports, weapons, drawing, etc. Your brain builds a rich scaffold you can hang
new concepts from.

~~~
bcrosby95
Sure, but it will still be a while before you aren't just writing Python in
Rust.

~~~
jghn
However the more languages you know and the more they're spread across
different paradigms the shallower the learning curve will be for any language
one wants to pick up.

~~~
apotheon
Be fair to the original comment, which referenced people saying something
about learning _a language_ , and it making learning any others _easy_ , not
about learning _many languages_ , and it making learning any others _easier_.

------
movedx
Also learn how to run a business. A weird suggestion on the surface but
actually very powerful when understood.

In short by learning how a business operates, how cash flows and how expensive
things are (people, buildings, software, hardware, accountants, lawyers, ...)
you'll begin to understand why an MVP is a powerful tool. you'll also
appreciate Agile development practices more too.

With an MVP you're writing the least amount of code possible, and skipping
optimisations, whilst also providing some value to people who can tell you
what direction to go in next. That's a business thing - the business needs
something in the market ASAP and it needs feedback ASAP. Without this you'd
write your stack for three years and then release to a world that moved on two
years ago.

When you learn how a business is run you begin to understand that getting to
market with a less than ideal code base is actually desirable and something to
embraced. All of sudden you'll come to understand that money burns quickly so
you should learn to develop code to get to market and not to be the fastest
code it can be (yet, at least.)

I find the best programmers I've worked with are those that can produce
something quickly and optimise it later on.

~~~
einpoklum
I've found the ability to produce something quickly is almost orthogonal to
being a "good programmer" (unless you define goodness that way.) Some are good
quick-and-dirty implementers, some are deep design thinkers, some are just
good at reviewing and giving advice.

~~~
ratww
> Some are good quick-and-dirty implementers, some are deep design thinkers,
> some are just good at reviewing and giving advice.

Fred Brooks has a chapter in Mythical Man Month where he mentions different
programmers having different roles within "Surgical Software Team" but that
never took off.

I wonder if updating that to 2020 would make more sense to have a group of
people shipping features full-steam ahead, another reviewing the code for
mistakes, and then having other folks refactoring the mess, behind both of
them.

I would frankly enjoy being in just one the three positions, any of them, much
more than the position I'm currently: having to be all three at the same time.

~~~
hanifc
I've often thought about a similar idea.

I'm still relatively new to the industry (3 years programming, 1.5
professionally), but I've found that I'm a BIG fan of refactoring. To me, it's
like writing or communicating ideas in general, which I really enjoy. I love
taking a complicated idea and trying to explain it in the most simple and
readable of terms. It also pushes me to really understand the intent behind
the code/text.

To that extent, I enjoy editing and revision much more than creation. So,
taking a role as a 'refactorer' actually sounds great!

------
augustk
"The most experienced programmer uses hacks all the time; the important part
is that you're getting stuff done."

I couldn't disagree more, the grown up programmers use a strategic approach,
not a tactical one. As Jonh Ousterhout put it in his book A Philosophy of
Software Design "The first step towards becoming a good software designer is
to realize that working code isn't enough."

~~~
rooam-dev
100% agree. The "hacks" and "get stuff done" approach gains quick and short
benefit, which probably fits a freelancer/contractor role. Maintainable and
testable code should be implied.

It's not about how fast you get to code to production, it's about how fast
code/product can be adapted to new or unexpected requirements.

------
Twisol
> Here's a question I like to ask: do you spend most of your time making your
> code look "nice"? If so, I recommend not focusing on it so much. [...] It's
> better to focus hard on the core problems you're trying to solve and think
> hard about your layers of abstractions.

Absolutely. Modeling what you're trying to do in code is a critically
important task, and a most surface-level grime is forgivable if you have an
understandable foundation.

However, I worry that if you focus on the first half of this block, you might
think the abstractions aren't important. To a lot of new programmers,
abstractions and models are _themselves_ merely "nice" \-- if you can get it
done without them, clearly they're non-essential, right?

I believe that most code is read more often than it's written. (You pass
through a lot of code while tracing down bugs!) It pays to reduce the
brainpower necessary to understand a block of code, and good abstractions and
good models are key to this.

~~~
majormajor
> I believe that most code is read more often than it's written. (You pass
> through a lot of code while tracing down bugs!) It pays to reduce the
> brainpower necessary to understand a block of code, and good abstractions
> and good models are key to this.

Bad abstractions and models make it much harder to understand code, though. So
for junior devs, yeah, it would often be better to be very, very careful, and
think very, very hard about your abstractions before creating them.

Everyone wants to turn every problem into some sort of framework loaded with
interfaces and different implementations of them vs being ok with "feature X
needs to do thing A, B, and D; feature Y needs to do things A, B, C, and E;
let's just have them as two separate endpoints with separate biz logical
calling those methods sequentially instead of trying to coerce them together."

~~~
Twisol
> Bad abstractions and models make it much harder to understand code, though.

True! The point I'm trying to make is more that _code clarity_ is important
and worth striving for, regardless of the means you use to achieve it. Clarity
is a non-negotiable part of my definition of "nice". If it's also part of
others' idea of "nice" \-- especially those of novice developers who look to
more experienced developers for guidance -- then this paragraph might suggest
that clarity can be down-played. It can't.

If you're an experienced developer, you should be able to find good
abstractions for achieving clarity in-context. But novice developers can still
identify code that's unclear ( _to them_ , especially).

Blindly applying abstractions rarely helps with code clarity. Some developers
apply certain abstractions because "it's a best practice", rather than because
it's actually more clear. That's definitely not what I'm advocating for.

------
uk_programmer
Some of it this was spot on, especially doing research. Very rarely you will
be doing something completely novel and it always good to look at how other
people have solved a problem.

However the old "Learn C" and "Write a compiler" which are within meme
territory tbh. It is more important generally to understand what a particular
in whatever language you are using to know what the compiler / interpreter /
run-time is doing under the hood as most developers will be working with a
high level language.

I've seen a lot of "how to improve as a programmer" articles and IMO what
seems to be left out is learning how to do things as simply as possible. Many
of the software systems I've worked on is so over-engineered, many simple
websites are huge both client and server side and they usually don't warrant
it.

------
funylon
"I stick things on the global object until I know what I'm doing." Magical
sentence that.

------
cryptonector
> Understand continuations - Continuations are a low-level control flow
> mechanism.

Excellent advice right there!

> Scheme is the only language to implement them, and while you will never use
> them in production, they will change how you think about control flow. I
> wrote a blog post trying to explain them.

Hmm, well, many languages compile to a continuation passing style (CPS)
intermediate. And in many languages it is important to understand
continuations to understand how they work. For example, laziness in Haskell is
essentially all about continuations and continuation passing style.

What is CPS? Anyone who has been in callback hell knows. In CPS a continuation
is just the closure you pass to some function that it will call when it's
done. In fact, even in C, the act of returning from a function is very much
like the act of calling a continuation, except that by unwinding the stack,
the magic of Scheme continuations is lost.

~~~
PaulAJ
"... you will never use them in production ..."

I'm a Haskell programmer. Continuations are part of my everyday toolbox.

------
codr7
Once you know a handful of different programming languages, write an
interpreted language embedded in your preferred host language.

It doesn't have to be fancy, I recommend using Forth or Lisp as a starting
point; but write something real, do your thing.

I find that most compilers are toys and replicas of existing languages on top
of that, which misses the point of designing your own tool.

[https://github.com/codr7/gfoo](https://github.com/codr7/gfoo)

------
mit_cs
Your reasoning for learning C is biased (perhaps you don't know it well as you
suggested the others to know the basics)! At the end, hardware understands
only values. C is a minimal, efficient and readable language which survived
for decades although there are hundreds of other programming languages. It
remains an active programming language as long as there is a good compiler
support.

~~~
tjpnz
Many of the complaints I read about C these days often boil down to a lack of
understanding, I think you're right to suggest that the author doesn't know it
very well. I also suspect that they haven't taken the time to find and read
_good_ C code.

------
xwdv
I became a better programmer once I committed to mastering Vim.

Don’t know why, but the whole struggle of using it changed the way I thought
about code and I gained the power to code at the speed of thought.

~~~
fossuser
I think I actually became better when I stopped spending time messing around
with tools and environments and focused on just the programming part.

Sane defaults, know the tool and how to use it, but don’t waste time on
configuration. When possible choose the standard tool for the job (IntelliJ
for me).

It’s still fun to yak shave, mess with things, play with the terminal etc. but
at least for me I found that the time spent doing that was the opposite of
productive.

~~~
hombre_fatal
Like playing an instrument or learning a language, learning Vim/Emacs is
something you're glad younger-you did because now you certainly couldn't be
bothered.

Then again, these days I just use whatever vim-mode solution there is in
VSCode, IntelliJ, etc. and move on. Kind of like how I prefer a GUI for Git
these days.

It would blow the mind of my younger self. I just have so many other things
going on in my life and on my plate.

------
dang
Discussed at the time:
[https://news.ycombinator.com/item?id=13918888](https://news.ycombinator.com/item?id=13918888)

------
non-entity
> But you shouldn't do that until you've done some cursory research about how
> people have solved it before. Spending a few days researching the topic
> always completely changes how I am going to solve it.

Personally this typically ends up in me just dropping the problem altogether

------
jacobush
How _I_ became a bitter programmer. (1995-2020)

------
sp527
Doesn’t expound upon two of the most important things: (1) focus on business
value over technical challenge (if anything this preaches the opposite) and
(2) learn how to get as close as possible to the global optimum in the 3D
space formed by time, cost, and quality, depending on the situation.

~~~
kqr
And (3) read Deming to find out that the 3D space formed by time, cost, and
quality does not look like one might think it does – for anything but the
quickest of prototypes, increased quality reduces total time and cost!

------
collyw
One thing that helped me a to was to build a system myself and maintain it for
a few years. That way you see what areas come back and cause you trouble over
and over again.

If I didn't understand a bit of code I wrote a few months ago, it was probably
too complex and worth refactoring. As it was my own system, I couldn't blame
anyone else's poor design decisions.

I noticed that keeping the logic as close to the database was generally the
way to go. Avoiding changing the database schema and making up for it at the
application level was basically adding technical debt.

------
yagodragon
I've heard so many things about Clojure. I am a CS student with some
experience in the most used languages (JS, java, python). Can someone explain
in simple cs terms why Clojure is sooo hyped? What can I do with this language
that would be harder with other languages? From what I've gathered it's used
in data wrangling and manipulation in general but most data-oriented tools are
written in Python.

~~~
teataster
I believe it's hyped because is a more practical/modern lisp.

I don't think it provides more fundamental benefits than any other lisp than
access to a plethora of standard Java libraries. E.g. I cannot Java, but
knowing clojure has allowed me to maintain a large inherited Java codebase.
Afaik I could not have done that in common lisp (and not only because I don't
know cl).

I think almost everything is harder when you are not using lisp. Also lisp
tends to bring joy to its users for some reason, so there is that.

Finally there is a huge difference between Python and clojure data wrangling.
Pandas and spark are fundamentally table oriented, but if you are using nested
dictionaries (clojure maps) you do not have those tools to help you. No matter
what I was doing in clojure, it always involved processing nested maps, it's
just the natural approach in the language, kinda like using classes in Java.

Hope I managed to clarify something :)

~~~
hcarvalhoalves
> I don't think it provides more fundamental benefits than any other lisp

Concurrency primitives and immutable data structures are part of the core
language. This is probably more interesting than the lisp part itself, which
is kind of a bonus. Rich Hickey's talks stress the former aspects a lot more
than the later.

~~~
teataster
Well, those are so ingrained in clojure that I forgot about them :). I think
you made a great point.

------
gchamonlive
SICP is really cool! I would follow up with Practical Common Lisp right after,
for insight into a more usable Lisp dialect.

------
LessDmesg
TIL Scheme is the only language that implements continuations.

------
marta_morena_23
"Don't spend much time on making your code look nice"...

Well, thanks a lot. You just made your code much harder to read, improve,
change and check for correctness. This is actually a self-contradiction. If
the code changes often, then its even more important to make it "look nice".
This is something that beginner programmers don't get on several levels: Nice
code

* can be reviewed more quickly (broadcasting effect)

* can be checked for correctness much more easily

* is pleasant to work with

* can be changed more easily

* can often even compiled into more efficient machine code

The reason why beginners (and this is not about time invested! Many
programmers still are beginners after 30 years in the field) think code
doesn't need to look nice is mostly because

1\. They don't consider that most of the cost of code comes from maintenance.
Writing it is really A FRACTION of the time people will spend with your code
over time.

2\. They don't consider that creating bugs is one of the most expensive parts
of software development.

3\. They don't consider that code is read far more often than it is being
written.

4\. They are simply not ABLE to produce good code and doing so would take them
a lot of time.

Now giving the advice to not focus on good/nice code is a recipe for staying a
beginner for the rest of your life and making every project your work on a
nightmare for everyone else involved.

~~~
jspash
FYI - the author of the blog post created
[https://prettier.io/](https://prettier.io/) which is a very opinionated
(automatic) javascript code formatter. His assertion about "nice code" was
that you shouldn't spend effort on making it look nice. Let a tool do that for
you.

Personally I dislike _some_ the default formats that prettier have chosen but
if it prevents a single minute of discussion on my team about how the should
be formatted, it pays dividends over time. And eventually we, as humans seem
to get used to just about anything.

------
justlexi93
I feel like learning is a continuous process, technology changes from time to
time so might stay updated with all the latest trend.

