atheken

@atheken@programming.dev
0 Post – 100 Comments
Joined 1 years ago

Cue the first post about the exploit that leads to leaking AWS keys. I’ll wait.

This is an professional experience thing.

Types support “programming at scale” - scale in the sense of larger code based or multiple people contributing.

If you’re hacking away at a script for a web page, then yeah, have at it.

If you’re supporting more than a few hundred lines of code or working on a team, you need types to codify and communicate information that can be verified with a compiler.

Whenever you see a larger codebase that is not strongly (or statically) typed, you generally will see unit tests that are verifying the types/structure of outputs.

1 more...

I’ve used the git cli exclusively for more than a decade, professionally. I guess it varies wildly by team, but CLIs are the only unambiguous way to communicate instructions, both for humans and computers. That being said, I still don’t mess around with rebase for anything, and I do use a gui diff tool for merge conflict resolution. Practically everything you need to do with git can be done with like 10 commands (I’m actually being generous here, including reset, stash, and tag).

3 more...

You might have a look at “CONTRIBUTING.md” files in repos.

  • Set quality standards (no giant PRs, follow documented coding style, include tests for changed functionality, etc).
  • Establish a way to discuss contributing work before they do it. Generally, have them open an issue discussing the proposed change and get buy-in from the maintainer (you) before starting work.
  • document any high-level goals and non-goals in the README.md for the repo, and refer to that when discussing changes. You can always amend it as you discover more about what should be built.

Initially, contributors can fork and send a pull request for you to review and merge. You do not need to give them any write access to the main repository. Be respectful of their time and review PRs promptly.

If multiple people want to collaborate on a branch, they can do that in their fork. In my experience, this is pretty rare, usually you don’t want multiple people committing to the same branch (except for merges to master/main/stable, etc).

If you have a few dedicated contributors that have a history of submitting good quality patches, and alignment with you on your project’s goals, you can invite them to have more control in the main repository, at which point there should be minimal concern about granular controls.

Unicode is thoroughly underrated.

UTF-8, doubly so. One of the amazing/clever things they did was to build off of ASCII as a subset by taking advantage of the extra bit to stay backwards compatible, which is a lesson we should all learn when evolving systems with users (your chances of success are much better if you extend than to rewrite).

On the other hand, having dealt with UTF-7 (a very “special” email encoding), it takes a certain kind of nerd to really appreciate the nuances of encodings.

2 more...

I believe the setting is user.email so maybe confirm that’s what you have set in both? Git will silently ignore settings that aren’t used/defined.

6 more...

This one is a bit tricky, because you have to think about logging as an output or a side-effect. And as an industry, we’ve been learning that we should limit the amount of side-effects that our code generates.

If logging is getting ingested by downstream systems like CloudWatch, or other structured logging systems, it is potentially going to be used to detect service issues and track overall service health. These are logs that are serving a functional purpose that is not purely a side-effect, or for debugging forensics.

If this is the case, then you should have a unit test asserting that a log entry is emitted when a method is called. If writing that test is a low or non-priority, then even if it’s a “breaking change,” then that’s a sign that it’s not actually going to break anyone.

I’m sure there’s some monadic view of how to package up the “side-effect” logging as part of a function’s output, but it’s probably annoying to implement in most languages.

Yeah, dropping typescript and then codifying type information in jsdoc is comical.

The only thing I would say about your experience is that “dropping TS for go” is a little bit misleading, and it doesn’t really sound like it bears on the general debate of “TS vs. JS” - go and other static languages generally fit a different niche in my opinion, and can be a better option for certain kinds of systems.

If you’re building anything of even moderate complexity, or with more than one person, you really need the types and modularity that TS provides.

I guess it’s also worth noting that JS has actually been influenced/adopted some key features from TS over the years, so it’s possible to do a few things with it to make stuff that’s a bit more maintainable.

Sure, you can make it 10x faster by optimizing the complexity, but I can improve throughput by 1000x by putting it on 1000 machines.

In practice, it’s a bit of both. Paying attention to Big-O and understanding the gross relative cost of various operations goes a long way, but being able to run an arbitrarily large number of them can get you out of a lot of jams.

1 more...

Important/generalized patterns reveal themselves over time. I generally push for people to just write the specific thing they need for the given context and then if the same pattern shows up elsewhere, promote the code to a shared library. It’s really hard to anticipate the correct abstraction right from the start, and it’s easy to include a bunch of “just in case” parameterization that bloats the interface and adds a lot of conceptual overhead.

That being said, with low-leverage/complexity code like html views, repetition isn’t as problematic. Although, I do think that HTML components have matured enough to be the correct unit of abstraction, not CSS classes.

So your fix is “convince all the people that want/need the better handling to use a specific editor?” - perhaps it’s a smaller number of people, but do you not see the irony there?

I honestly don’t care about tabs vs. spaces, but if there’s a low cost change in my setup that makes it easier on others, why not?

11 more...

Just to add, I’d argue dotnet has one of the best sets of guidance on style. It goes beyond just naming and towards how to structure code for easier consumption and consistency. People love to dump on MSFT, but the dotnet platform is superb.

https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/

1 more...

I used to be full on the ORM train. Now I’m a little less enthusiastic. What I actually think people need most of the time is something closer to ActiveRecord. Something that can easily map a result set into a collection of typed objects. You still generally write parameterized SQL, but the work of translating a db decimal into the correct target type on a record object in your language is handled for you (for example). In .net, Dapper is a good example.

I also think most people overemphasize or talk about how other programmers “suck at SQL” waaayy too much.

IMO, for most situations, these are the few high-level things that devs should be vigilant about:

  • parameterize all sql.
  • consider the big-o of the app-side lookup/write methods (sometimes an app join or pulling a larger set and filtering in memory is better than crafting very complex projections in sql). This is a little harder to analyze with an ORM, but not by much if you keep the mappings simple and understand the loading semantics of the ORM.
  • understand the index coverage of queries and model table keys properly to maintain insert performance (monotonically increasing keys).
  • stop fixating on optimizing queries that run in a few seconds, a few times a day. Optimize the stuff that you run on every transaction - if you need to.

On most of those points, if you don’t have aggregate query counts/metrics on query performance on your clusters, starting to get cute with complex queries is flying blind, and there’s no way to prioritize what to optimize.

For the vast majority of cases, simple, obvious selects that don’t involve special db features are going to do the job for most applications. When the database becomes a bottleneck, there are usually much more effective ways to handle them than to try to hand optimize all the queries.

Lastly, I have a little bit of a theory that part of the reason people do/do not like looking at SQL in code is because it’s a hard context switch from one language to another, often requiring the programmer to switch to “stringly-typed” mode, something we all learn causes huge numbers of headaches in our first few months of programming. Some developers accept that there’s going to be different languages/contexts and not all of them are going to be as fluent or familiar, but accept that this is par for the job. Others recoil from the unfamiliar and want to burn it down. IMO, the former attitude is a lot more productive.

1 more...

Demo videos are not “documentation.” They are “demos.”

If you want someone to repeat your steps, it should be code or CLI commands. You can write more descriptive text, but as soon as you reference pictures to show something, you’re introducing ambiguity that text/code can avoid.

UIs change faster than videos and screenshots, as you said, can’t be searched, and are generally less accessible than text.

The source files for documentation should also live side-by-side with the code in the repo. As soon as it goes anywhere else, it immediately goes out of date.

I don’t know the specifics of the golf problems, but I’m mostly in c#, also notorious for “having too much boilerplate,” and it looks like it’s 3rd by char count.

My guess is that languages with comprehensive standard libraries can do more with less custom code. As you should expect.

And, they are actually more convenient because then entire login process is one step with minimal keyboard input, rather than two.

3 more...

The problem is that when you are alerted for trivial/non-actionable stuff it contributes to “alert-fatigue” and you just start ignoring all of the alerts.

As far as I’m aware, there’s also no way to triage an alert from an install other than to upgrade the offending package, which means you can’t really discriminate on the basis of “acceptable risk”

I’ve tumbled down this rabbit hole on more than one occasion.

This line of thinking can lead you to the conclusion that the only ecologically just thing to do is for humans to cease to exist.

It’s a trap that can lead to despair.

Do your part to be mindful, respectful, and conservative with resources, but don’t give in to nihilism.

I think you’ll have better luck with podcasts. Technical books tend to have long tracts of code that would be excruciating to listen to.

You might enjoy:

  • co-recursive
  • software unscripted
  • this developer’s life

Breaking larger tasks down effectively removes uncertainty.

My general rule of thumb in planning is that any task that is estimated for longer than 1 day should be broken up.

Longer than one day communicates that the person doing the estimate knows it’s a large task, but not super clear about the details. It also puts a boundary around how long someone waits before trying to re-scope:

A task that was expected to take one week, but ends up going 2x is a slide of a week, but a task that is estimated at one day but takes 3x before re-scope is a loss of 2 days.

You can pick up one or two days, but probably not one or two weeks.

I’d rather they ask me a question on something for which I’m an expert (myself) and that I can prepare for, than to fire off leetcode question.

Yeah, it’s a little bit redundant, but it can break the initial tension and get the conversation going. You can also use the time to emphasize some specific aspect of your work history that you think matches up with the job req, or shows why you actually want to work there.

If they don’t ask this question/prompt, what question would you want them to ask?

The problem with the article is that it’s confusing hard realtime and low latency requirements. Most UIs do not require hard realtime, even soft realtime is a nice to have and users will tolerate some latency.

I also think the author handwaves “too many blocking calls end up on the main thread.”

Hardly. This is like rule zero for building gui apps. Put any non-trivial or blocking work on a background thread. It was harder to do before mainstream languages got good green thread/async support, but it’s almost trivial now.

I agree that there are still calls that could have variable response times (such as virtual memory being paged in or out), but even low-end machines are RAM-rich and SSDs are damn fast. The kernel is likely also doing some optimization to page stuff in from disk for the foreground app.

It’s nice to think through the issue, but I don’t think it’s quite as dire as the author claims.

3 more...

Hello fellow old person. I mostly agree, and I think we’re starting to see some convergence on the core patterns that will define the “best way” to deliver web apps for years to come. The various offshoots of React are really just evolutions to see what fat we can trim and tighten it up. But functional-reactive UIs as a general thing are here to stay and better than all the other ways we’ve wired up GUIs to date.

Also, as far as I can tell, they’re talking about devs that are building on the Roblox platform, not devs that are building the platform.

In other words, random devs of varying skill levels getting name-squatted.

It’s not good, but including Roblox in the title is definitely misleading/clickbait.

6 more...

As an end result, maybe. But it also means that you get specific feedback on how to properly author it correctly and fix it before pushing it live.

IDK, I lived through that whole era, and I’d attribute it more to the fact that HTML is easy enough to author in any text editor by complete novices. XHTML demands a hell of a lot more knowledge of how XML works, and what is valid (and, more keystrokes). The barrier to entry for XHTML is much, much, higher.

1 more...

I loathe this line of reasoning. It's like saying "unless you wrote assembly, compiling your code could change what it does."

Guess what, the CPU reorders/ellides assembly, too! You can't trust anything!

2 more...

Along with this, once you’ve dealt with enough kinds of problems, you end up developing an intuition for how something was probably implemented.

This can help you anticipate what features are probably included in a framework/library, as well as how likely they are to work efficiently/correctly (you know that XYZ is a hard problem vs. ABC which is pretty easy for a journeyman to get right.)

As an example, a friend of mine reported a performance issue to a 3rd-party vendor recently. Based on a little bit of information he had on data scale and changes the 3rd-party made to their query API, he basically could tell them that they probably didn’t have index coverage on the new fields that could be queried from the API. That’s with almost no knowledge of how the internals of their API were implemented, other than that they were using Postgres (and he was right, by the way).

That’s not always going to happen, but there are just a lot of common patterns with known limitations that you can start to anticipate stuff after awhile.

That’s interesting. Usually when I see people talking about Rust, they really like it. Are there specific parts that make it less enjoyable than go for you?

2 more...

We used JIRA effectively at my last job, the things that made it work for us:

  • stop adding shitloads of required fields. Title, description, branch, priority (defaulted), status (defaulted), type (bug/feature). We might have had some others, but that was all I remember being required.

  • stop writing shitty descriptions: spend more time writing something that your co-worker can use. Respect their time enough to try to include enough detail for them to actually use the ticket. Be available to answer questions when they are assigned a ticket you wrote.

  • you don’t need extremely granular statuses: the functional role of the assignee is enough to determine what “state” it’s in, trying to codify a unidirectional flow of tickets is maddening and overly complicated. Work is messy, it flows back and forth, you do not need a “rejected by qa” status. Just leave it open and reassign to the developer with a comment. Managers find out when individuals are submitting half-assed work on a regular basis, you don’t need JIRA for that (unless you need metrics to fire them… different problem).

I agree with the premise of the article, JIRA is a communication tool, not a management tool.

You should do some research on wasm.

You can run frickin’ docker containers in the browser now.

I don’t make the rules.

Probably the more important question is whether DHH is your boss.

It’s fine to look for people with real experience/opinions on the internet, but at the end of the day, you have to build your own product.

I also am going to just say that I’m betting the kinds of stuff rails does in JS doesn’t really need a lot of complex JS. My guess is a lot of it paints on behavior similarly to what htmx does now, which doesn’t really require a ton of js code anymore. I don’t much see the point removing TS for the vast majority of projects.

I haven’t made a UML diagram in years. Or an ER diagram, for that matter.

Getting a schema dump and/or generating a diagram from an existing system would be useful, it won’t be UML, but can convey similar information. At a certain point, keeping an updated UML diagram is extra work that is almost guaranteed to go out of data instantly.

1 more...

I’ve had ohmyzsh installed for years. TBH, I still don’t know what it gives me over bash. In your experience, what is the “killer feature” of zsh?

Which is what putting most of this stuff on the background accomplishes. It necessitates designing the UX with appropriate feedback. Sometimes you can’t make things go faster than they go. For example, a web request, or pulling data from an ancient disk that a user is using - you as an author don’t have control over these, the OS doesn’t even have control over them.

Should software that depends on external resources refuse to run?

The author is talking about switching to some RTOS due to this, which is extreme. OS vendors have spent decades trying to sort out the “Beachball of Death” issue, that is exceedingly rare on modern systems, due to better multi-tasking support, and dramatically faster hardware.

Most GUI apps are not hard RT and trying to make them so would be incredibly costly and severely limit other aspects of systems that users regularly prefer (like keeping 100 apps and browser tabs open).

1 more...

I generally find that writing code that requires a lot of “accounting” is very prone to mistakes that are easier to avoid with recursion. What I mean by this is stuff where you’re tracking multiple counters and sets on each iteration. It’s very easy to produce off by one errors in these types of algos.

Recursion, once you get the hang of it, can make certain kinds of problems “trivial,” and with tail-call recursion being implemented in many languages, the related memory costs have also been somewhat mitigated.

Loops are simpler for beginners to understand, but I don’t think recursion is all that hard to learn with a bit of practice, and can really clean up some otherwise very complicated code.

My general opinion is that we are all beginners for a short part of our journey, but our aim shouldn’t be to make everything simple enough that beginners never need to advance their skills. We spend most of our careers as journeymen, and that’s the level of understanding we should be aiming for/expecting for most code. Recursion in that context is absolutely ok from a “readability/complexity” perspective.

🙈🙉🙊

I know, but I didn’t want to scare the children.

I also chose to pretend it’s just little gnomes moving the bytes around. Less magic.

I mean, the inverse is probably more productive. Specify the observable behaviors you want and let the “AI” build the software.

1 more...

You can stage individual chunks of a file.

Useful if you have a large set of changes you want to make separate commits for. I also just find that it’s a good way to do a review of each chunk before committing changes blindly.

Give it a shot some time, worst case is you stage some stuff that you don’t want to commit, but it’s non-destructive.

1 more...

I use git on the CLI exclusively. I almost never rebase, but otherwise get by with about 5-10 commands. One that will totally change your experience is git add -p

I also have my diff/mergetool configured to use kaleidoscope, but still do everything else in the CLI.

5 more...

I think it’s a double negative: “against not using”

As in, use a bundler.