@develwithoutacause@techhub.social avatar

develwithoutacause

@develwithoutacause@techhub.social

Overly opinionated software developer on the Angular team at Google. Web development is hard, so I build tooling that makes it easier. I love forcing web tools to do things they were never supposed to do.

This profile is from a federated server and may be incomplete. Browse more on the original instance.

develwithoutacause, to javascript
@develwithoutacause@techhub.social avatar

#JavaScript #CodeReview: Always use === over ==.

=== applies much more reasonable behavior for operands of different types, mainly by not coercing them together like == does.

A lot of developers will tell you to learn the rules of coercion and use it when appropriate, however I disagree for one key reason. Consider this example:

if (foo == bar) {  
 doSomething();  
}  

Question: Did the developer mean to use ==? Is the coercion intended or a typo?

It's incredibly difficult to know with any amount of certainty as this depends on the types and semantics of foo and bar.

If I was writing this intentionally, I would feel compelled to write a several line comment about how coercion behavior applies here in a desirable way. And if you need to write that much explanation, it would be much less confusing to actually codify the desired behavior with === and explicit type checks so devs don't have to understand that coercion.

develwithoutacause,
@develwithoutacause@techhub.social avatar

TL;DR: Even if you meant to write == and used it correctly to take advantage of useful coercion behavior, when I look at that line of code 6 months from now, I just can't trust you.

Therefore it's much safer to always use === so readers don't have to guess the original author's intent.

develwithoutacause,
@develwithoutacause@techhub.social avatar

@flensrocker Is that to handle the undefined == null case?

I still feel like that's complicated enough to justify a comment explaining that intention. Otherwise as a reader I have to guess whether you meant the undefined case to trigger the condition.

Personally I would find x === null || x === undefined to be much more clear to the reader, even if it is unfortunately verbose.

chriscoyier, to random
@chriscoyier@front-end.social avatar

Maybe we can get an interesting thread of examples here.

Less than 10 second videos of @container queries in action on websites.

Go!

develwithoutacause,
@develwithoutacause@techhub.social avatar

@chriscoyier This is cool, what does the container query actually look like here? Do you have to hard code a width or is it possible to trigger a change on line wrap?

develwithoutacause, to chrome
@develwithoutacause@techhub.social avatar

Anyone here seen extensions with panels just not display sometimes?

I'm seeing some really weird behavior recently I can't explain and would appreciate if anyone has experienced the same problem and could validate my sanity:

https://g-issues.chromium.org/issues/337104322

develwithoutacause, to til
@develwithoutacause@techhub.social avatar

#TIL any errors thrown in attributeChangedCallback get swallowed. They're not propgated to whoever called el.setAttribute('observed', 'data').

develwithoutacause, to javascript
@develwithoutacause@techhub.social avatar

#JavaScript #code #review

Prefer explicit .toString() over other string coercion methods.

Template literals (${foo}) or implicit conversion ("" + foo) have unclear developer intent and are difficult for readers to search when they don't understand. When presented with ${foo}, it is much harder for a developer to understand what this is or how to look it up if they don't already know the jargon of "template literals".

.toString() might be longer, but it is much clearer in its intent and much easier for developers to look up if they don't understand what's going on.

develwithoutacause,
@develwithoutacause@techhub.social avatar

@tbroyer Fair enough. In my experience, I'm almost never ok with String(null) and wish types would disallow that by default (logging libraries can support that in other ways).

If the value is non-null or you're doing String(x ?? '') then I think that's fine.

Personally, I'd probably do x?.toString() or x?.toString() ?? '' first in the nullable case, but I don't feel that strongly about it.

develwithoutacause,
@develwithoutacause@techhub.social avatar

@tbroyer Now that I think about it there is a general nullability argument here.

#TypeScript will happily accept ${maybeNull}, but maybeNull.toString() would be a type error, so that's another reason to avoid the template literal.

String(maybeNull) does have the same problem in that TypeScript will accept it even if I didn't intend for that.

If you want null behavior then fine, but I would worry that it's too easy to accidentally make this mistake to trust that it is ever used correctly. As a reader I can't know if a String(maybeNull) was intentional or not. Maybe the value was non-null initially and then converted to nullable later without considering this string coercion.

I'd much rather see maybeNull?.toString() ?? 'null' or String(maybeNull ?? 'null') just to be explicit, even if it is redundant.

(That gets more complicated with undefined and null, but in that scenario stringifying is a more complicated problem and justified a more complicated solution.)

develwithoutacause, to javascript
@develwithoutacause@techhub.social avatar

#JavaScript #Code #Review

Prefer native for-of loops over Array.prototype.forEach.

.forEach is:

  • Slower
  • Specific to Array
  • Has confusing await behavior (returns a Promise)
  • Is not obvious that it contains side-effects unlike most other Array methods like map.

for-of loops are:

  • Faster
  • Work on Iterable and AsyncIterable.
  • await actually awaits.
  • Supports control flow statements like break, continue, return, and yield.
  • Clearly contains side-effects because there's no other use case for a loop and its hard to confuse with other syntax.
develwithoutacause, to Spotify
@develwithoutacause@techhub.social avatar

Apparently really thinks I'm into right now. My discover queue has 8/30 songs from the Sonic series.

I don't mind the occasional Sonic track, but this is a bit excessive.

develwithoutacause,
@develwithoutacause@techhub.social avatar

The rest of my queue consists of , , , and .

So apparently Spotify has just given up on me and is only recommending video game music now.

develwithoutacause, to programming
@develwithoutacause@techhub.social avatar

Are there any which have a built-in operator for "not null"?

It feels like it's far more common to check if I have something rather than not having something, which leads to significantly more "not" operators and double negatives. I'd much rather write:

if (exists(foo)) {  
 doSomethingWithFoo(foo);  
}  

Instead of:

if (foo != null) {  
 doSomethingWithFoo(foo);  
}  

But I can't think of any example syntax which does this. Surely some language already does this?

angelmunoz, to javascript
@angelmunoz@misskey.cloud avatar

Is there an html tagged template library to render html on the server? I'm currently exploring @ lit-labs/ssr but I'd like to be aware of alternatives
Note: I don't need hydrate or client stuff, just a plain html string to string/stream/etc templating library

develwithoutacause,
@develwithoutacause@techhub.social avatar

@angelmunoz Maybe #htm? I think you can use that on the server like regular #Preact.

https://github.com/developit/htm

develwithoutacause, to webdev
@develwithoutacause@techhub.social avatar
develwithoutacause, to til
@develwithoutacause@techhub.social avatar

does not prevent assigning a Readonly<T> to a T, which kind of makes the whole readonly concept fairly moot.

https://github.com/microsoft/TypeScript/issues/13347

And here I was trying to actually use readonly deliberately in my types. I've always thought it was a fairly underappreciated feature of TS, but now that I'm discovering this I feel like it just makes typing more painful for little to no real benefit.

develwithoutacause, to random
@develwithoutacause@techhub.social avatar

Are a contradiction?

An MFE which is too tightly coupled to other MFEs is just increased tech debt for minimal benefit.

An MFE which is completely decoupled from other MFEs provides no value. It may as well just be an independent application.

It feels like there is a very thin line where MFEs are a viable solution. Where your use case and UX are decoupled enough to be independently developed, but also coupled enough to require an MFE solution. How many apps fall into that spectrum where an MFE is the solution to their particular scalability problems and fit their use case?

I already have a blog post in the pipeline (only semi-technical this time) but I keep getting more topics on my mind and not enough time to devote to them. I've been wanting to talk about MFEs in different venues for a while but never pulled the plug on it. Maybe this is the time?

develwithoutacause, to Engineering
@develwithoutacause@techhub.social avatar

Found a great series of articles on whether or not #SoftwareEngineering is "real" #Engineering. What those differences may or may not be, and how the various disciplines can learn from each other. Very insightful stuff!

https://www.hillelwayne.com/post/are-we-really-engineers/

develwithoutacause, to mastodon
@develwithoutacause@techhub.social avatar

I keep seeing #Mastodon posts with rich text features, pike bulleted lists, different fonts, and hyperlinked text. Is there some mechanism for #Markdown formatting or other tricks I'm not aware of?

develwithoutacause, to til
@develwithoutacause@techhub.social avatar

#TIL #CSS calc can't add or subtract with a unitless 0. You must include units.

/* Doesn't work. */  
height: calc(0 + 100px);

/* Works. */  
height: calc(0px + 100px);  

https://stackoverflow.com/a/55406181/3995712

I can kind of see the argument why here, but it's strange to me that multiplication works, just not addition or subtraction. Definitely a foot gun to watch out for. I wonder how many linters would suggest unitless 0 here?

develwithoutacause, to windows
@develwithoutacause@techhub.social avatar

I had to install #Git on a #Windows machine today and OH MY GOD I forgot how complex of a set up process it is. I went through it again just to count the unbelieveable number of steps it took:

  1. License agreement.
  2. Which components to install (includes proper nouns like "Git Bash", "Git LFS", and "Scalar"). Notably does not enable automatic updates by default.
  3. Default editor for Git (doesn't include #Emacs as an option).
  4. Default branch name.
  5. How to configure the PATH.
  6. Which #OpenSSH to use.
  7. Which #SSL / #TLS library to use.
  8. How to handle CRLF / LF line endings.
  9. Which terminal emulator to use.
  10. Whether to use merge or rebase by default.
  11. Whether to enable the credential helper.
  12. Extra options:
  • File system caching.
  • Symbolic links.
  1. Experimental options:
  • Pseudo consoles (?)
  • File system monitor (?)

This is utterly absurd and probably the most unnecessarily complicated install experience I can think of.

develwithoutacause,
@develwithoutacause@techhub.social avatar

I've been doing #Git for the better part of a decade and my day job is dealing with tools which directly deal with some of these problems. Yet even I don't understand some of these questions.

How is a new Git user supposed to understand any of this? How much background knowledge do you expect a Git user to have?

Worst of all, the most critical piece of information is lost: You need to log out and back in to apply the PATH change and use git on the command line.

If the user is following any kind of tutorial odds are it looks like:

  1. Install Git here.
  2. Run git init # ...

Any new user is going to immediately fail at step 2.

My suggestion: Just use the default options for everything. Shove all this nonsense into an "Advanced options" section and put a "Restart" button / "Please log-out" message on the final screen.

This would make Git infinitely less intimidating and more approachable.

develwithoutacause,
@develwithoutacause@techhub.social avatar

@Paxxi @baldur It does default to #Vim, probably because that is the most popular option. Comes with a caveat that it might be difficult for new users who are unfamiliar with it, but context is pretty minimal.

develwithoutacause,
@develwithoutacause@techhub.social avatar

@Paxxi Still something it should say at the end the process.

Also I'm not sure that was true in my case, I definitely observed git is not a command. I think I opened that shell after install but I'm not sure.

develwithoutacause, to random
@develwithoutacause@techhub.social avatar

When a project refuses to update a dependency in a specific LTS version you're using, so you decide to find a security bug in the dependency to force the project to update to the version you want.

  • All
  • Subscribed
  • Moderated
  • Favorites
  • JUstTest
  • tacticalgear
  • DreamBathrooms
  • InstantRegret
  • magazineikmin
  • Youngstown
  • everett
  • anitta
  • slotface
  • GTA5RPClips
  • rosin
  • thenastyranch
  • kavyap
  • mdbf
  • Leos
  • modclub
  • osvaldo12
  • Durango
  • khanakhh
  • provamag3
  • cisconetworking
  • ngwrru68w68
  • cubers
  • tester
  • ethstaker
  • megavids
  • normalnudes
  • lostlight
  • All magazines