Core Developer @ Hudson River Trading
On 7/16/2021, 4:04:09 PM
The first eight weeks of my internship, I was in much confusion. The turning point of my internship from that confusion to understanding was about the point of that previous brain dump. Luckily, it was an upwards-facing turnaround rather than the other way.
At the beginning of the internship, I was very much focused with: how can I change things and respect everyone else's code? At the end, both my mentor and my boss were on vacation (by unfortunate coincidence), and I was left much to my own devices without guidance. There was a radical change in mindset that can be roughly summarized by the principle of asking forgiveness rather than permission. Rather than asking the team about every little change that I should be making, and waiting for a response, it's more of a process of keeping everyone informed but also charging ahead. Keep moving -- move fast and break things. In the end, I was able to accomplish much more at the end of the internship by being confident in my changes -- rather than trying to explain every decision and wait for responses to every question, make educated guesses in the correct direction. Of course, a lot of backtracking also occurred, but the road was paved and greater ideas that are clearer as the sum of many small changes were not hindered.
In the end, I was able to successfully present my project, first to my intern group, then as a functional and architectural overview to the greater team, and then as a code-walkthrough and Q&A session with the team I was interacting with. Especially in the latter, I was able to explain many design decisions and receive feedback on them as well. I only really realized then that the team was looking for me to make my own decisions, so they could see how an outsider would tackle the problem, and this further strengthens my conviction.
Of course, good things build upon good things. Since I was able to be more productive, more feedback came pouring in. Some of my team members were able to reach out to me and suggest the use of their tool, something that I was previously unaware of. This partially addresses the question that was the main object of my earlier confusion: how do you learn about the things that you don't know you don't know? In this case, the answer is: put enough effort in and show it to others, and feedback will be the way you learn.
It feels like a simple lesson, but I was previously too timid to understand it.
Time to point out a few more quirks in Javascript, and a few good points of Python:
Javascript's class getter and setters are highly-unintuitive syntax magic to me. This is the same reason why I don't like Python's magic keywords1 intuitive (because there is no obvious connection to their effects -- it is an internal detail of the interpreter that is opaque to the user).
Javascript package import system has had too many changes over time. Luckily, it seems that the syntax has mostly normalized to ES6 import
and export
keywords, but there are a confusing number of historical systems, notably the CommonJS require
(used in Node.js) and AMD define
syntax (used in Angular 1 and Dojo). Unfortunately, there's a good chance of encountering packages with legacy import statements that make the imports messier. This is almost as bad as Python 2's persistence.
In Javascript, most definitions are hoisted, but class definitions are not.
Javascript doesn't have operator overloading; it's operators are predefined. However, their operators with their unchangeable behavior may be type-flexible to a fault: a commonly-noted example are equality comparisons of arrays or objects with primitives, which clearly produce nonsensical values.
Python has some features with its class syntax that may either be good or bad, depending on the programmer. I already mentioned static methods and class methods in the previous post -- the distincion may be confusing to the beginner but useful to the niche user. Python's methods, like Rust and Go (and unlike C++ and Java), have an explicit self
parameter. This means that a method can be called either using the dot syntax (obj.method()
) or as a regular function with an explicit target object ObjectClass.method(obj)
. The dot syntax is very convenient and inevitable in an OO language, but confuses elementary programmers about how methods work.
Newer versions of Python have pretty good support for typing (and type-checking). This mostly refers to type hints and the typing package (which defines generic builtin container types). This is a gradual type system that is probably equipotent as Typescript.
I don't have much to say about this, except that it is so essential. I mentioned the term "programmer intent" in the previous brain dump, and that term ("intent") will likely be the star of my M.Eng. thesis: an "intentional programming" framework, which at its core enforces a literate programming style. More on this soon in a future blog post.
Similarly, I began tutoring a freshman CS student today, and she was almost enlightened by the fact of commenting each step of her program (in her case, matching each homework subquestion number to the relevant line(s) of code). I wish more students would have that sort of epiphany, but unfortunately our world tends towards spaghetti2.
1. I learned that these special methods are called Dunder methods.
2. This is a statement of the second law of thermodynamics, right?
© Copyright 2023 Jonathan Lam