Ask HN: Do you ever go back and admire a piece of code you wrote?

257 points by grimwall ↗ HN
I switched careers and got into coding about five years ago and I have always wondered about this and am a little embarrassed about it.

Sometimes after finishing a big implementation, I just go back and read my own code ... and I like it! I feel proud that I translated some kind of abstract problem solving into a concrete solution, and somehow it works!

I feel like I created something that flows according to my ideas and it’s a joy to look at. Are there analogous feelings in other creative pursuits you practice?

Of course not everything is like this, only novel problems I encountered have potential to give this feeling, CRUD back-end endpoints are routine by now. Also I don't feel like an exceptional programmer, feel more like an impostor, so please don't read this as bragging.

266 comments

[ 3.7 ms ] story [ 184 ms ] thread
I don't feel proud of my code if it works but I do feel terrible about it if it doesn't work perfectly. As soon as I realize that there is any problem in any of my projects, I need to drop everything and fix it immediately or else I can't sleep or think about anything else.

I guess not being able to carry on with my life if I know that my code has the slightest issue means that I assume it is perfect and therefore I'm idolizing it.

Sounds like a perfect case of perfectionism.
Yes, I do this sometimes. I feel proud of most of the things that I wrote but not about stuff that was written by multiple people and where I just added some things.
Not really. If you remove the algorithm part (which can be drawn very nicely and admired on paper) you have code. And code age, and it ages fast. Python 2 is not Python 3. C++11 is not C++20. I see the changes that need to be done instead of the beauty of the work.

There has been some exceptions, mainly in my Haskell-code, a monad still seems to be a monad and I start to see it with a more "math-focused-lens" and then I start to find some small admiration.

That's just how some people are. For what it's worth, I can't look at anything I make and be happy with it; I only see the flaws, omissions, and infelicities. If you can be proud of what you make, then great!

Nobody cares either way, though; code ultimately has its own notion of quality, and human aesthetics are totally unrelated to code quality. We all must learn to think like computers and appreciate code like computers do.

I find it differently... I look at the old code and look at the lessons I learned as I wrote items on top of each other... my projects are basically layers on top of each other.
It depends on what you code. For me there must be three things for me to be proud of some codebase:

  1. I could use my creativity (it was not entirely defined problem which just needed to be translated to code).
  2. I have enough time to make it good, not rushed.
  3. Problem was a little over my current competence level, so I could learn something new.
If you only make CRUD forms day in/day out it's hard to be proud of what you do. Creating map display engine which is more performant than anything you have seen to date IS a thing to be proud of (I'm still proud of that one thing, but it's other firm's internal tool, so I can't show you). Unfortunately, for most developers being able to work on such things is very rare. I had maybe 5 such things over my 20 year career.
Yes, i still like how we were able to run 72 voicemail lines on one machine under a ms-Dos environment with 5Mb coax network. Written under Pascal, still got the code.
Yes. Early on in my career, I needed a function that produced a range of dates, given a start and end date. After it was all said and done, it boiled out like so:

  def daterange(start,end):
      while start<=end:
          yield start
          start +=timedelta(days=1)
Though simplistic and straightforward, I admire the solution. I am sure there may be “better” ways to achieve the same result, and posting this here may result in cowboys trashing it or pointing out a fallacy - oh well... at the time, I was pretty satisfied with it and am still to this day.
Are you proud of using a generator to create dates as you need? Just trying to understand the logic
Not trying to trash it, but doing

  dt = timedelta(days=1)
outside the loop and using it inside would make it a bit more efficient.
What's cool about this is now that you have a date generator, you can apply all kinds of fun things to your date ranges with Python's standard library.

Apply generator expressions, format them with map, filter out weekends, anything in itertools (dropwhile, takewhile), etc.

I wrote a datepicker to demonstrate some concepts like lazy evaluation with JavaScript generators and it was fun coming up with the test cases.

https://github.com/gumballhead/datepicker/blob/master/src/it...

I'm struggling to understand how this is special... isn't it basically just the normal 2-argument range function, but with date instead of int?

    def range(start, end):
     while start < end:
      yield start
      start += 1
Or is it more about the beauty of the algorithm than this specific code?
I think it's just the relative simplicity of code that handles date logic compared to other languages:

https://stackoverflow.com/questions/4345045/javascript-loop-...

I hate dealing with date math, but I have to admit that Python makes date math much more elegant. I've written the functional equivalent of the OP function several times, and it's just so nice to be able to loop over dates just like they were any other generic sequence.

Edit: plus you can enhance it pretty to make arbitrary increments with ease:

    def daterange(start, stop, increment='days', step=1):
         start = datetime.fromisoformat(start)
         stop = datetime.fromisoformat(stop)
         inc = {increment: step}
         while start <= stop:
             yield start
             start += timedelta(**inc)
         
    > list(daterange('2020-01-01', '2020-01-14'))
    [datetime.datetime(2020, 1, 1, 0, 0), datetime.datetime(2020, 1, 2, 0, 0), datetime.datetime(2020, 1, 3, 0, 0), [...], datetime.datetime(2020, 1, 14, 0, 0)]
    > list(daterange('2020-01-01', '2020-01-14', 'weeks', 1))
    [datetime.datetime(2020, 1, 1, 0, 0), datetime.datetime(2020, 1, 8, 0, 0)]
Python's date handling is meh. Some languages have dates as first class primitives and are a dream to work with.
I generally admire the architecture and and some nice and elegant tricks on my past code, but not the code itself. I always feel like things could be cleaner, with better names, with a more consistent coding style (I am quite severe to my self on this point).

Much older code is generally neither smart neither beautiful though.

well, that's the path to coding enlightenment! hahaha, just keep climbing for a few years more
The only thing I have ever gone back and admired is when I wrote the following snippet of code:

  long time; // no see
I came across this gem recently:

    catch (Exception up)
    {
        throw up;
    }
Truly genius code

  try
     ToastTheGenius;
  except
   On Glass: Exception do
     raise(Glass);
  end;
(comment deleted)
Or in Python:

  except Exception as the_roof:
      raise the_roof
Code puns, yay!

Mine:

    const makeEmptyPromise = () => Promise.resolve([]);
Hehe, well if we're going here there are various go-to shell commands / filenames / hostnames I inevitably end up using at some point just for the wry smile:

    $ PONG=1.1.1.1; ping $PONG
    $ more cowbell
    $ cat dog | tee hee
And my favourite choice of empty file:

    $ touch me
Also I was fairly please years ago when I briefly re-aliased cd to something that could do "the right thing" (TM):

    $ cd ...
    $ cd ..../src/
etc..
"cd ..." etc. worked in 4DOS, an alternative (and extended) DOS shell: https://en.wikipedia.org/wiki/4DOS.
I think it was standard DOS, from maybe DOS 5 upwards?
I was thinking it worked in MS DOS after some point, but I was remembering more like Windows 95 era. I don't think it worked in MS DOS 6.x, because IIRC that's when I was using 4DOS. However, it doesn't work in Windows 10 CMD.EXE.
I wrote a generic bash function to spin up a mongodb instance called `mongo`. I couldn't resist adding

`echo "Mongo only pawn in game of life"`

You would get bonus points if you wrapped the mongodb process so that when it receives a SIGKILL it logs out "Mongo like candy!"
LOL - thanks for sharing this. Especially "$ more cowbell".

I am SO gonna steal that.

:-D

But was this in C?
It was in Java...but I C where you are going with this.
Well, actually, the fact that it wasn't in C kinda makes it work even better, from one point of view. :-D
That's worth printing on a t-shirt. :)
This gem in a Flash frame (Actionscript)

    stop(); // hammer time
was there an actual hammer involved in the game at this point? I think then it would be great, most of these cute, funny bits of code are making me feel annoyed by proxy.
I wrote the following, completely innocently:

  return when.all(promises).yield(true);
Except for the return to happen when that's true, you'd need an await. At least in JS.
Not if it's returned by an async function. In JS, async functions automatically await promises that are returned.
(comment deleted)
That's not actually right. An async function will always return a promise, so if you return a promise directly it's indeed pretty much the same as if you return a promise that waits on that promise; it's the calling function that actually awaits on the returned promise.

The main difference would be error handling: if you have a catch block that returns a different value, returning the promise directly would actually throw in the calling function, whereas if you "return await", it's going to get caught in your catch block, resolving the promise to your own custom value.

Found a detailed explanation here: https://jakearchibald.com/2017/await-vs-return-vs-return-awa...

I once came across a function that declared this:

    int ofTheJedi;
I was a bit confused until I got at the bottom of that function and saw this:

   return ofTheJedi;
That's when I recognized a coworker's style, haha
I once came across some code, written by a coworker, that consisted of deeply nested blocks. I added a comment that simply contained a URL:

  // http://photos3.meetupstatic.com/photos/event/4/b/c/2/600_436939394.jpeg
I don't know if anyone ever noticed this comment and followed the URL, but I hope they did and were amused. (The code was eventually refactored/rewritten, so the comment no longer exists in the codebase.)
Well, I followed the URL and was amused. So it wasn't a complete loss (even if I never did see the code). Thanks for sharing!
Remember timecube guy? Seen on a 16-bit DSP...

    struct timecube {
        uint16_t millisecond_of_minute;
        uint16_t minute_of_month;
        uint16_t month_and_year;
    };
That's clever. I might steal that at some point. Or combine into a millisecond_of_month on a 32 bit processor.

For people that don't play with bits often: Unsigned 16-bit integers have their max as 65,536. Storing data often wastes most of the bits, since a field that goes from 0-1000 doesn't fit in an 8-bit integer, and C doesn't have native integers between 8 and 16 bits long. (You can mask out relevant fields, but that's annoying.)

So there are 1000 * 60 = 60,000 milliseconds in a minute, which is an impressively good use of the space available. There are also a max of 60 * 24 * 31 = 44,640 minutes in a month, which is pretty good usage of the second value as well. The final 16 bits are probably 4 bits for month and 12 bits for the year, going up to 4096. Alternatively it could be using it as something like month_of_common_era to get it out to year 65536/12 = 5461.

It also cooperates with leap seconds, by counting faithfully up to 61,000 on such a minute.

IIRC, month and year was a 4-bit and 12-bit bitfield just as you describe.

Every time I implement an action class, I make sure to make an empty parent class to subclass it from.

    class Action(Lawsuit): ...
I have a Notion database of code Snippets for this purpose.

Described this in a recent blog post: https://tkainrad.dev/posts/managing-my-personal-knowledge-ba...

It's nice to take a moment after finishing a project, a challenging task, or whenever you feel like it and preserve snippets that you are proud of. Going through these pieces of code later brings back memories of these past projects, teams, tasks,...

+1 for db of code snippets - things like:

cat ~/src/example-code/py/numpy-masked-array.py

save me tons of time for those hairy things that I had to eat an hour to figure out and then use infrequently

I immediately think of my very simple 17-line constraint satisfaction problem solver which has saved me so much work.
Would you mind sharing it? I am really curious.
I can't share the code.

It is just a really dumb search for a random solution. (I don't want to get the same solution or solutions each time.) The domains (which are always pretty small) for the variables are randomly shuffled first, so the search can just iterate through the domains.

The problems mostly have a large number of solutions out of the total space, so finding a solution is fast.

The real beauty is then being able to write short declarative code, which is very easy to write, read and modify (I'm not always sure in advance exactly what the constraints should be). None of which would be the case for the code which would construct a solution, even though it might run a little faster.

Programming isn't unique in allowing you swing between moods of "this feels great :D" and "I'm so dumb". (I think most people feel like either at times, even hours apart).

But Fred Brooks makes a good point with:

"""The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination. Few media of creation are so flexible, so easy to polish and rework, so readily capable of realizing grand conceptual structures....

Yet the program construct, unlike the poet's words, is real in the sense that it moves and works, producing visible outputs separate from the construct itself. […]

The magic of myth and legend has come true in our time. One types the correct incantation on a keyboard, and a display screen comes to life, showing things that never were nor could be."""

When I started my first programming job the CEO told me that programming is 59 minutes of feeling like an idiot and 1 minute of feeling like a genius. It's really stuck with me, and has so far proven true.
59:1 is pretty good. Sometimes debugging gets me really down
That's when you hack and slash and debug by friction. : p

Forging ahead thoughtfully, incrementally, and modularly balances the ratio a lo--oh hey a foreign codebase designed in an overengineered byzantine Lovecraftian fractal of thought death. 9999999:1

I find it reassuring to read these accounts. Even though I've been in the industry for years, I still have times (like this week), where I spend way too much time trying to do something that I feel shouldn't be that hard to do and imposter syndrome kicks in hard. A lot of what I see on hacker news is people at the top of their game, so it's nice to see people talking about actually struggling.
What's awful are those bad days when it's actually hours and hours of feeling like an idiot, draining you away, and then when you figure it out you still feel like an idiot because first off it was so simple and second of all solving something in minutes is not going to wash away hours of feeling like an idiot.

Luckily as I have gotten older I have gotten fewer and fewer of those days.

I learn to accept when I am tired and need to take a break. Sometimes hours of needling through code can be solved in minutes on a fresh brain. I used to be stubborn and wouldn’t stop until I had made some progress and that went on making a tired day into an exercise in frustration. Took a while to have the confidence to shut down and start fresh the next day.
This hit me real hard, thank you I need to become better at this.

Just had a few frustrating days at work, lo and behold problem solved elegantly in 1 hour on a Great Prayer Day where I was supposed to be off-work.

The simple solution was just writing out a truth-table and then implementing it using the new C# switch expression to make sure I had all combinations taken into consideration.

I once had an issue where it appeared my servers were leaking less than a byte of memory per request (WTF? less than a byte?).

It took months to find the bug. Turns out it started leaking once the filesystem quota was reached, the log tried to roll and failed. All logging messages were just building up in a queue. It was a definite face-palm moment once found, but yeah, took months to get there.

I had a similar issue w/ a high-res timer that was causing spurious socket timeouts. Only found because...logs were saying operations were taking +200 years to complete. That was about 6 weeks of time during development.

Only if I go back to a language that I haven't used for a few years where I don't remember how the solutions are implemented.
I often return to things with reluctance, assuming massive technical debt, only to be pleasantly surprised (sometimes I am pleasantly offended!). I'll usually attempt a "haut-syntactica" refactor, only to fall back into the flow and elegance of the original work ... tho I definitely have a tendency towards over-engineering in the first instance.

On an aside, someone here mentioned that python 2 isn't python 3, in that the code itself gets old quick. But I don't think that really comes into it. Unless you're spaghetti-plugging holes in clients, there's a lot of joy to be had in manipulating any language or system to a desired end, especially when it's hard won, and I would think too when you return and see yourself in the result.

No. I really don't have that courage.
Not entirely mine but beautiful nonetheless:

    @dataclass
    class Node:
        id: str
        children: List[Node] = field(default_factory=list)

        # beautiful Python: traverse a tree depth-first, pre-order (stack based)
        def __iter__(self):
            stack = [self]
            while stack:
                node = stack.pop()
                yield node
                stack = node.children + stack
No, I mostly go back and surrender to not understanding why I wrote what I wrote. Yes, I am in awe. But because it's a like a third person wrote it.

Regardless of comments.

Haha. I'm always proud of myself when I look at code that I don't understand, and I see some comment clarifying it and making obvious the reason why it couldn't be simpler and why I did something the way I did it. And then I'm like: "hey, you can trust yourself"

When that doesn't happen, I just spend the time to understand it again and add the comments. It eventually gets better.

we call this code review
A code review consists of reading a piece of code written recently by someone else, which is not what is asked by OP.
I admire my old code when I go back to that code and by reading the code, see some idiosyncratic behaviour. Then a pay slightly more attention and see my own comment in the code saying that the author knows about it and that was the assumption made in the first place.

Otherwise code can always be made better.

I'm opposite. Never ever I felt proud of my code, I always am critical of it and thinking in the back of my head "I know how to refactor it even better". It's a never-ending story for me. And whenever happen to do maintenance of a old project of mine from years ago I cringe of the way I implemented some stuff and plenty of times I have to restrain myself to not refactor it since the client wants only a simple change while the refactoring would eat away my free time.
I wouldn't say admire. When I stumble upon code from many years ago I (somewhat painfully) realize I've lost a lot of the ingenuity I used in my early days. I read the code and find myself thinking "how the hell did I come up with that solution". I didn't care about finding the optimal algo/ds, I would just use whatever I knew at that moment without a second thought. Now I have to care a lot more about writing code that looks smart and learning "new" frameworks.
All the time. I put pride in my code. I worked in various teams and codebases and came to appreciate the quality of my code.
I do reminisce,but do the opposite of admire, perhaps because my day job has never been primarily to write code.
One of my very first was Inna domain parking app, that it tried to "fertilize" any domain that was pointed to the server. It would obtain feeds piped via Yahoo feeds for keywords from the domain, and sell the domains later at higher price for the slightly better SEO value.

I still love the domain parser I had there. I actively tried to avoid regex by the time, and I had a huge validator that brings tears to my eyes. I admire it because this can be written with a single regex, but I am sure I spent an hour or two working on this, carefully planning about public suffixes, IDN conversion, host headers, etc.

I do hope you stopped doing this. Parked domains have frustrated me so often!
I do sometimes go back and stare at this wonder I crafted once:

  s=>s[0]+/.*( .|z)|...s.s?|T..|M[i-t]+|[AFINOUW][^o]v?|.*/.exec(s)[0].slice(-1).toUpperCase()
It does something pretty useful, that has surely been written many times over. But unlikely ever as succinctly as this. :)
I can get this feeling with non-novel code when I slot something into a larger framework (following the paradigm). I find that easier to walk away from than writing novel code, as it takes longer to feel satisfied with the latter.