HNHacker News
TopNewBestAskShowJobs

aastronaut

124 karma · joined May 2, 2016

https://blog.whilenot.dev/
submissionscomments
aastronaut··on Using the switch(true) pattern in JavaScript
I think I didn't make my point quite clear. Let's consider the case where version 3.1 needs to return something different than version 3.

A good (IMHO) early-return pattern would look like this:

  if (version >= 3.1) {
    return "result_3_1";
  }

  if (version >= 3) {
    return "result_3";
  }
  
  // ...
...but in the wild I often see it developed into something like this:

  if (version >= 3) {
    if (version === 3.1) {
      return "result_3_1";
    }
    return "result_3";
  }
  
  // ...
...probably because people like to see major version numbers packaged together in blocks.

With the switch-true on the other hand I could make good use of this 'stepping through ranges'-problem and could even make use of the fallthrough, in case it should fall back to a different value:

  switch (true) {
    case version >= 3.1:
       return "result_3_1"; // just comment this out if you need the result of version 3 instead
    case version >= 3:
      return "result_3";
    // ...
  }
aastronaut··on Using the switch(true) pattern in JavaScript
This style gets the label 'poor-mans-pattern-matching' from me. If pattern matching would not be in my daily vocabulary, as it's also not available in JS, I'd consider it a misuse of switch/case and this post also makes an odd example for its usefulness.

The example I would pick is the following: Consider you need to switch depending on a version (of a specification in my case), but this version isn't represented as an enum in the codebase, but as a number instead. So our team had something like this in the codebase (early return):

  function foobar(version: number): string {
    if (version === 3.1 || version === 3) {
      return 'result_3';
    }

    if (version < 2 && version >= 1) {
      return 'result_1';
    }
  
    if (version >= 2) {
      return 'result_2';
    }
  
    throw new Error(`Cannot interpret version '${version}'`);
  }
I read it as "people don't care about branching order that much, so how can I make my wish for better readability more clear?".... my end goal then was to bring it into this state (a distinct enum as discrete value of the version):

  enum Version {
    _1_1 = 1.1,
    _2   = 2,
    _3   = 3,
    _3_1 = 3.1,
  };

  function foobar(version: Version): string {
    switch (version) {
      case Version._3_1:
      case Version._3:
        return 'result_3';
      case Version._2:
        return 'result_2';
      case Version._1_1:
        return 'result_1';
      default:
        (function (val: never): never {
          throw new Error(`Exhaustiveness reached: ${val}`);
        })(version);
    }
  }
...and my interim solution that made it into the PR in time turned out to be something like this (switch true):

  function foobar(version: number): string {
    switch (true) {
      case version >= 3:
        return 'result_3';
      case version >= 2:
        return 'result_2';
      case version >= 1:
        return 'result_1';
      default:
        throw new Error(`Cannot interpret version '${version}'`);
    }
  }
My PR was flagged by the team for misuse of the switch statement, we had some discussion and I changed it back to the simple if/else branching from above.
aastronaut··on Vald: A Highly Scalable Distributed Vector Search Engine
Had exactly the same question and found this short clip (from Weaviate, an alternative vector search engine): https://www.youtube.com/watch?v=SDOl9fRObVg In a distributed nature with Vlad I think the aim is to reduce a single point of failure.
aastronaut··on CLIs are reified UIs (2017)
I use tldr[0] for that.

[0]: https://github.com/tldr-pages/tldr/

aastronaut··on Building a patient monitoring system with Go and Vue in 3 days
I think you're misunderstanding the critique of the parent... In the software world we often tend to interpret "The perfect is the enemy of the good." as "If it's the only software solution it most certainly must be a good one.". But sometimes there are non-software solutions that are even better suited to solve the problem - engineering wise that MUST(!) also be taken into account.

What makes you think the team covered enough edge-cases to be "good enough" software? Do you think the presentation in a single blog post is enough information about a system to determine its quality and reliability?

aastronaut··on Eloquent JavaScript 3rd Edition (2018)
Unfortunately not. DDD is a design concept on how to match the business domain in source code - the design step is language independent and the practical implementation is very business dependent. I'm also keen to find a good practical reference, but can also understand why there might never be one. The book above on F# is very approachable, as F# in the predecessor of TS and the first half of the book is even language independent. Learning some SOA (service oriented architecture) terminology will be of some help as well.

I highly encourage you to not solely stick around JS/TS for patterns. For me, JS/TS is the "most" multi-paradigm language in usage to date, thus is not one of those languages that needs to be written in a certain way. Other languages can give you patterns more clearly and those are for the most parts adaptable to JS/TS. Haskell made it click for me on how to model with types, Elixir has the interesting concurrency/resilience pattern with supervisors etc... There are also good JS libraries whose usage still feels like programming and less "using a framework"-like - RxJS has an interesting approach for events/subscriptions and I feel like redux-saga showed me a very good use case for generators.

aastronaut··on Eloquent JavaScript 3rd Edition (2018)
A project in TypeScript is not much different from one in JavaScript structure wise. The biggest difference might be the explicit work on types and modeling your problem to make good use of composite types. In the source code you'll have some type definitions where implementation and usage sit close to each other (to enforce a local implementation), and others where a type is more like a serializable DTO (data transfer object) between different domains and seen more global throughout your application. You'll get a feeling when mapped types should alter a type or when a local type definition might be better (TS is structurally typed for a reason).

Domain modeling can feel close to "type driven modeling" here. A good book in that regard is "Domain Modeling Made Functional"[0]. I see types and a functional paradigm closely related, but keep in mind that this is just one approach in your toolbox... there might be the case where a GoF OOP pattern works good as well[1]. I think it's also important not to try to trick the TS compiler into something, but rather to work with it. Keep in mind that the TS dev team is giving you a lot of freedom by not striving for a provable correct type system[2].

To really take advantage of TypeScript I think it's good to know where a type system is coming from, what it is that it's trying to solve and how it is doing that. I think it's helpful to have a look into other languages with a "strong" type system (Haskell[3], OCaml, rust) and see how they are doing it. Then you may get to see how Haskells phantom types will conflict with TypeScripts type inference, and OCamls type inference seems to work in fascinating ways compared to TypeScript. After working through the advanced types[4] in TypeScript it's good to understand what a "good abstraction" in case of a type system is and what isn't... this is when you discover the similarities to other languages through the common language of abstract mathematics (and abstract data types). In every program you'll encounter effects and monads are quite helpful to work with them, this is were a sound type system can really shine.

I feel with every JS/TS project you will build a lot of the projects toolchain yourself and you kind of need to discover what fits best. It's good to be able to catch possible bugs early with the TS compiler, quicktype[5] can help you in building some typed contracts to other projects.

A separation into packages with lerna[6] should encourage a good separation into packages and is seen in a lot of open source projects. Speaking of, reading into good open source packages will be a mandatory way to go in order to learn more.

[0] https://fsharpforfunandprofit.com/books/ [1] http://loredanacirstea.github.io/es6-design-patterns/ [2] https://github.com/Microsoft/TypeScript/wiki/TypeScript-Desi... [3] http://learnyouahaskell.com/ (a bit dated though) [4] https://www.typescriptlang.org/docs/handbook/advanced-types.... [5] https://quicktype.io/ [6] https://lerna.js.org/

aastronaut··on Eloquent JavaScript 3rd Edition (2018)
I think the sentiment of "you dont know what you dont know" is especially cumbersome with JS, since its usability is so much defined by its extensions (WebAPIs, runtimes etc.)

Reading into specs (ECMAScript[0], W3C[1]), some more approachable explanations[2] of them and some implementations[3, 4] of embedded engines seem to be my approach.

[0]: https://tc39.es/ecma262/2020/ [1]: https://github.com/w3c [2]: http://dmitrysoshnikov.com/ecmascript/javascript-the-core-2n... [3]: https://bellard.org/quickjs/ [4]: https://v8.dev/docs/embed

aastronaut··on My NixOS Desktop Flow
Unfortunately I have to disagree.

I tried to setup a simple NixOS machine this week. From this experience I couldn't manage to install any GNOME extensions via the browser plugin because of some Firefox manifest location that conflicts with the way the NixOS store handles it - there is some workaround in some tickets, but it made me wonder how many other applications are in need for specific workarounds. I then enabled flatpak via the OS configuration, but the first installed app couldn't launch because of some obscure error with gstreamer. I changed to fedora and could setup anything without any of those issues.

I really want to like NixOS (I still do), but I now consider it more for a server environment than a casual desktop environment.

aastronaut··on CoreJS: State of the project? Looks like dead. Any official fork?
IMHO there is no reason to bring an unrelated GitHub issue discussion into this comment thread.
aastronaut··on Why do so many developers get DRY wrong?
I assume your API can be expressed as this function signature:

  parseDataFromHTMLResource :: Resource -> HTMLRaw -> Maybe Data
...and assuming we validate the HTML:

  validateHTML :: HTMLRaw -> Maybe HTML
I think your question relies on the separation of 'Resource', as a domain separation like right below will probably create a lot of duplication (since any resource is free to structure their HTML within the standard however they want):

  parseDataFromGoogleHTML :: HTML -> Maybe Data
  parseDataFromGithubHTML :: HTML -> Maybe Data
  parseDataFrom...
Perhaps you can reduce the duplication by converging to different fingerprinted resources. So a HTML resource, fingerprinted by style, will then guarantee your data:

  data HTMLFingerprinted =
      HTMLStyleGoogle
    | HTMLStyleGithub
    | ...
  
  htmlFingerprintedFromHTML :: HTML -> Maybe HTMLFingerprinted -- So the Maybe will be here
  parseDataFromHTMLFingerprinted :: HTMLFingerprinted -> Data  -- ...not here
(Note that this may be what the parent means. It helps solving "For me it's usually, "Oh crap that thing I changed I had to change here and here too, whoops its good now... Wait no I also had to change it here... and here... now that we're done with that we should be fine... DAMMIT!"" with "I just create this abstraction".)

I would say if you're able to implement the function 'htmlFingerprintedFromHTML', you deserve the abstraction and thus DRY the codebase on the fly. And this "no pain no gain" mantra is what I personally really like on a 'functional core'. Code stays only duplicated where absolutely needed until you find a solution for the abstraction.

...and I guess implementations of fingerprinting HTML may vary a lot.

aastronaut··on Why do so many developers get DRY wrong?
My take on it would be the approach from SICP[0]: separate data (objects) from transformations (streams). On a personal note I would also like to add:

- keep data serializable

- cluster transformations accordingly (Keep things that belong to each other as close as possible to each other, in a literal meaning, same file/module/etc. A new coworker should have the feeling of entering a public library - she'll know where to look for.)

- it will probably never be the case that you have to invent a new data structure or algorithm

Developers understand such terms like 'function' in very different ways (see top comment in this thread). Some have a more abstract approach and understand it as 'pure', where others have a more instruction-bundeling approach and understand it as 'procedure'. Either is valid, but are completely orthogonal to each other when it comes to its usage. I understand Gary Bernhards approach to 'functional core, imperative shell'[1] as a mean to talk about this - instructions demand for composable building blocks, and those building blocks come either from:

- built-in functions (with an already universally understood API)

- or your own (clustered) utils (and demand an easily understandable API).

[0]: https://mitpress.mit.edu/sites/default/files/sicp/index.html

[1]: https://www.destroyallsoftware.com/screencasts/catalog/funct...

aastronaut··on Web Graphics Done Right
Thomas Ruff comes to mind as a prominent artist (photographer) working with JPEG artifacts.
aastronaut··on Standard JS: npm install funding
Thanks for the link, I was indeed unaware of the term.

By looking through the ongoing discussion, it was interesting to find a reference to the core-js issue [0] from earlier this year. Its maintainer, with his established position in the npm community, makes use of a similar post-install script to open up a discussion and communicate his situation. This gives him a more direct communication channel to its users without directly helping his situation.

What I assume can be understood as a rent-seeking practice, is how fooreys intention, with the same political power in maintaining a popular package, seems not to be solely to raise awareness to his situation. But instead he's forced a solution to his problem by advertising unrelated 3rd party products. Whereas he interestingly also uses the term experiment, it did already render npm as a space for advertisement.

[0] https://github.com/zloirock/core-js/issues/548

aastronaut··on Standard JS: npm install funding
the maintainer uses rent seeking as intention himself. [0]

[0] https://github.com/feross/funding/issues/7#issuecomment-5245...

aastronaut··on Skills Poor Programmers Lack
Not GP, but the book 'Domain Modeling Made Functional' does explain advantages in modeling with types quite well.
aastronaut··on Ask HN: Why does front-end development change so often?
> How many apps require web storage? Are there sufficient requirements to implement web workers or service workers?

Most B2B apps and apps with monthly subscriptions.

aastronaut··on Ask HN: Why does front-end development change so often?
To come back to the OP: "Why does front-end development change so often?"

I think a lot of technology that was solely available to the backend for a long time is now possible to do in the frontend (including machine learning with Tensorflow) ...it's a quite new and limited (but save) form, but the advantages in using those capabilities are clear to me.

As everything is quite young there isn't an established pattern yet and a lot of active research is happening. Just in the last 5 years alone we got quite an amount of additional languages: Elm, TypeScript, Flow, ReasonML, PureScript. I personally like the functional approach of React to transform the interaction of the imperative DOM to a declarative one, but there is still a lot to be done until we reach something like an MV* pattern for SPAs. If I were to make a guess, I would guess that all the active change in the frontend (including the urge for WebAssembly from some) is truly because of the hope for an MV* pattern that combines all those technologies with the advantages of the web.

If you were to take on some tech dept, please make sure to keep it interesting for the future development. The essence of the web is to not find a common agreement, and I think the active development on the frontend mirrors this sentiment quite well. ;)

aastronaut··on Ask HN: Why does front-end development change so often?
> "Honestly, none of the real value was in any of the web apps. The value was in the backend logic (if there was any significant business logic at all) and more so in data and real system design, balancing between function, redundancy, resiliency, extensibility, and some notion of scalability depending on who the customer was and what expected or unexpected scenarios could arise and how our systems would behave."

These are all responsibilities on the frontend as well... Website =/= Webapp. It almost seems that a lot of backend developers are not making this distinction nowadays, even though SPAs are already out there for years.

In the frontend there is the ever-responsive UI workload, the option for web workers, and service workers are on the rise. To keep your state there are JavaScript objects, web storage (session- and localstorage) and IndexedDB. WebGL anyone...? Newly developed JavaScript should sometimes work in the browser as well as in Node.js. I am solely mentioning technology here, not any implementation - this is thanks to the frontend of the web, as sandboxed app platform (and JavaScript), being so versatile. Next to the system design of the app there is also the gap to its UI/UX design to fill. ...All should work reliable on devices with very limited resources, as there is no option to scale on the client side.

"How to reach offline functionality?" Is a question with all of the complexity belonging to the frontend. Whereas the frontend is the data's real-time interaction, the backend becomes more the reliable async distribution of data. I'm sorry, but frontend app development is everything except from boring for me.

aastronaut··on The Elements of UI Engineering
Your approach seems to create an abstraction on top of react where the next step could only be a DSL. This is a first indicator for me that the developer will loose those programming capabilities that react carefully tries to retain and I'm not sure if this is a good approach. I think this doesn't solve the problems of entropy that Dan mentioned in his post and please let me explain a bit further...

I think of JSX as a declarative way to redefine HTML and to make it fit to the desired design. Sometimes it's quite possible to find a common behavior of a component and it can become part of a library, but that's not always the case. I like to use react components as a slim layer and prefer to do the work (side-effects, data processing etc.) somewhere else (purely functional modules, redux-saga etc.). My goto-rule to create components became the following: "if I start naming my component with something else than with layout-related terms, then I'm using react as the wrong tool for the job". React is just the view layer, a data processor that puts the view-data into the DOM. And as such a view layer it's sole responsibility is to render conditionally, the responsibility that your linked library tries to extract. I personally prefer to read through early returns in the render method of a component as opposed to following the order of an array.

There are behavioral UI problems in an SPA that are not related to the DOM itself. React can't do much about that and I think the problem of entropy stems from there: In the app at work one of the biggest struggles was to keep a global lock for a modal. This modal can pop-up to the user and show a notification, confirmation, form etc. Modals should never overlap with each other, give the user all the time she needs, but should also follow priorities (i.e. a push-notification to cancel the session being one of the highest). The difficulty in managing this lock was that actions from everywhere can pop-up that modal, be it a push notification over websockets, functions called from the native side, failed/succeeded API calls or behavioral inputs that should work differently all over the app (i.e. barcode scanning a product will search for a product in one view, will add it to the cart in another, or will prompt for a follow-up action if no product could be found). Thanks to redux-saga, we can make use of actions not solely to update the store state, but can additionally (if ignored by the reducers) use them like a message bus in a concurrent system. So with redux-saga (and inspired by elixir) I could make use of the actor-pattern and build a supervisor saga that keeps this behavior maintainable, but there is way to much complexity in this.

Point being, react and redux do a great job at managing entropy as long as it's used in the correct way. I think each component that doesn't take props can in fact be the starting point into it's own (micro-)application. But I think the biggest difficulties are external influences for an SPA - those interconnected influences that make the web so attractive for an application.

EDIT: typo

aastronaut··on V8n – Fluent validation library for JavaScript
...and its lightweight counterpart for the browser: https://github.com/jquense/yup
aastronaut··on To become a good C programmer (2011)
i think fefes cms is written in C... [1]

[1] http://www.fefe.de/poweredby.html

← PreviousPage 3 of 3