<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jono M</title>
    <description>The latest articles on DEV Community by Jono M (@binarykoan).</description>
    <link>https://dev.to/binarykoan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1001447%2F839d032d-360a-4bd3-a9d8-532aa55e0a0a.jpeg</url>
      <title>DEV Community: Jono M</title>
      <link>https://dev.to/binarykoan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/binarykoan"/>
    <language>en</language>
    <item>
      <title>Joys and woes of monorepos</title>
      <dc:creator>Jono M</dc:creator>
      <pubDate>Fri, 17 Nov 2023 21:03:55 +0000</pubDate>
      <link>https://dev.to/binarykoan/joys-and-woes-of-monorepos-o5c</link>
      <guid>https://dev.to/binarykoan/joys-and-woes-of-monorepos-o5c</guid>
      <description>&lt;p&gt;&lt;a href="https://monorepo.tools/"&gt;Monorepos&lt;/a&gt; are a great concept, especially in environments like Node.js which encourage having many small packages.&lt;/p&gt;

&lt;p&gt;There are some very obvious advantages to this: not having to have a bunch of folders open and not having to push to seventeen different repos when you update a shared library is very nice. There are also some less obvious advantages, and as you get deeper into monorepos certain disadvantages start rearing their ugly heads as well. These are just a few good and bad points I've found in my own work that might be worth thinking about.&lt;/p&gt;

&lt;p&gt;I've mainly used Yarn 1 workspaces as monorepo tooling so the benefits and problems may not apply to other tools, but I assume the underlying ideas are similar and I'm curious to try out other tools to compare.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standardised tooling
&lt;/h2&gt;

&lt;p&gt;One of the greatest things about a monorepo is that you can centralise a lot of tooling configuration. For example, chuck a &lt;a href="https://prettier.io/"&gt;&lt;code&gt;.prettierrc&lt;/code&gt;&lt;/a&gt; in the root of your monorepo and you'll never have arguments about code style again. Put a few base &lt;code&gt;tsconfig&lt;/code&gt;s in the there to extend, and suddenly TypeScript behaves with beautiful consistency across all your packages. Add formatting, linting and &lt;a href="https://typicode.github.io/husky/"&gt;husky&lt;/a&gt; as dependencies in the root of your workspace and you no longer need to work through upgrading everything individually when a new version comes out.&lt;/p&gt;

&lt;p&gt;This is especially true in a team, and even more especially true if you often spin up new packages. Keeping the tooling consistent makes it vastly easier to jump back and forth between packages your team and other teams have worked on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies within the repo just work
&lt;/h2&gt;

&lt;p&gt;Something I discovered embarrassingly recently is that if you have a monorepo package that depends on other packages in that repo, and you don't need to publish it (for example, it's a frontend app you bundle anyway), you can add non-published packages as dependencies and &lt;em&gt;it just works&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let's say you have a design system and several frontend apps which depend on it. Those frontend apps are just bundled into single JS files and deployed somewhere, so they don't need to be published. That means you can just put your design system somewhere in the monorepo with &lt;code&gt;"name": "my-design-system"&lt;/code&gt; in its &lt;code&gt;package.json&lt;/code&gt; and then add &lt;code&gt;"my-design-system": "*"&lt;/code&gt; to any packages which depend on it - no need to deal with any package registries. Run &lt;code&gt;yarn&lt;/code&gt; and you're set.&lt;/p&gt;

&lt;p&gt;The way this works is that Yarn will symlink all your workspace packages into &lt;code&gt;node_modules&lt;/code&gt; automatically, so they'll be found by the module resolution algorithm anywhere within your monorepo. A very neat idea.&lt;/p&gt;

&lt;p&gt;This does however mean that if you try to publish a package that &lt;em&gt;depends on a non-published package&lt;/em&gt; everything will work fine in CI because it's in the monorepo, but it'll break horribly on NPM because that non-published dependency can't be found. Bear that in mind!&lt;/p&gt;

&lt;h2&gt;
  
  
  Hoisting dependencies can cause problems
&lt;/h2&gt;

&lt;p&gt;This is a thorny enough issue that I wrote a &lt;a href="https://dev.to/binarykoan/dependency-hoisting-in-yarn-monorepos-279i"&gt;separate article about it&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  The editor conundrum
&lt;/h2&gt;

&lt;p&gt;Monorepos can grow to be massive and can contain a large number of disparate projects, which raises a conundrum: opening the whole monorepo in your editor makes finding files tricky because there are simply so many, but opening subfolders individually can kill many of the advantages of using a monorepo in the first place.&lt;/p&gt;

&lt;p&gt;This is of course a problem with all large projects, but it's especially true of monorepos since their point is to become large and somewhat heterogeneous.&lt;/p&gt;




&lt;p&gt;I guess my overall point is that monorepos should be managed with care: they're a great idea and often the only reasonable way of managing projects in environments like Node, but diving in without being aware of the pitfalls can end up causing you endless pain with everything from debugging dependencies to navigating the code.&lt;/p&gt;

&lt;p&gt;Best of luck with your own monorepo journey!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Dependency hoisting in Yarn monorepos</title>
      <dc:creator>Jono M</dc:creator>
      <pubDate>Fri, 17 Nov 2023 21:02:52 +0000</pubDate>
      <link>https://dev.to/binarykoan/dependency-hoisting-in-yarn-monorepos-279i</link>
      <guid>https://dev.to/binarykoan/dependency-hoisting-in-yarn-monorepos-279i</guid>
      <description>&lt;p&gt;I ran into a strange problem the other day which demonstrates one of the problems with monorepos, at least when using Yarn 1.&lt;/p&gt;

&lt;p&gt;I noticed that adding &lt;code&gt;@testing-library/react&lt;/code&gt; to one of our packages caused tests in another unrelated package to suddenly start failing. This turned out to be a weird quirk of how Yarn "hoists" dependencies.&lt;/p&gt;

&lt;p&gt;As a general rule, if you only have one version of a dependency in a workspace, Yarn will put it in &lt;code&gt;node_modules&lt;/code&gt; at the top level. This avoids duplicating packages unnecessarily. However, sometimes different packages will depend on different versions of a library, in which case Yarn will put the version &lt;em&gt;used by the majority of packages&lt;/em&gt; at the top level and create separate &lt;code&gt;node_modules&lt;/code&gt; folders in the individual package directories for packages which depend on a different version.&lt;/p&gt;

&lt;p&gt;The cause of the failing tests turned out to be this strange issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In our monorepo, we have several packages built in React 18 and several built in React 17&lt;/li&gt;
&lt;li&gt;This means we have packages depending on &lt;code&gt;@testing-library/react&lt;/code&gt; versions 14 and 12, which are compatible with the respective React versions&lt;/li&gt;
&lt;li&gt;We had more packages using React 18, but more packages using &lt;code&gt;@testing-library/react&lt;/code&gt; version 12 (compatible with React 17)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This meant that we ended up with directories like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules/
  @testing-library/
    react/ -- v12
      node_modules/
        react/ -- *v17, because the top level package is 18*

  react/ -- v18

packages/
  some-unrelated-package/
    node_modules/
      react/ -- v17
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll notice there are two copies of React 17 here - one because the package itself depends on React, and one because the testing library at the top level &lt;em&gt;depends on a different version of React than the top level one&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The end result was that both versions of React were loaded in tests (one by the code and one by the testing library), which of course got React super confused and caused a bunch of strange errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions
&lt;/h2&gt;

&lt;p&gt;The best solution here would obviously be to upgrade everything to the same version of React. In fact, I'd say the moral of this story is to keep your dependencies in sync as much as possible in monorepos to avoid this kind of problem from the start.&lt;/p&gt;

&lt;p&gt;But a couple of workarounds I found were&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Just test more packages. If every package with React is tested with that library, the number of packages depending on each version matches and the right versions get hoisted&lt;/li&gt;
&lt;li&gt;Use the &lt;a href="https://classic.yarnpkg.com/blog/2018/02/15/nohoist/"&gt;&lt;code&gt;nohoist&lt;/code&gt; property&lt;/a&gt; in &lt;code&gt;package.json&lt;/code&gt; to force &lt;code&gt;@testing-library/react&lt;/code&gt; not to be put at the top level. This means there will always be a copy per package, which will always use the nearest &lt;code&gt;react&lt;/code&gt; (i.e. the same one as the package itself)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one of the trickier pitfalls I've run into with monorepos, and one you should absolutely try to avoid!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>yarn</category>
    </item>
    <item>
      <title>Functional immutable game state</title>
      <dc:creator>Jono M</dc:creator>
      <pubDate>Tue, 17 Jan 2023 04:31:45 +0000</pubDate>
      <link>https://dev.to/binarykoan/functional-immutable-game-state-2fal</link>
      <guid>https://dev.to/binarykoan/functional-immutable-game-state-2fal</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/binary-koan/all-seeing-wizards" rel="noopener noreferrer"&gt;All-Seeing Wizards&lt;/a&gt; is a fun little game project I’ve been coming back to occasionally for some years now. I was originally inspired by Jackbox Games and thought I’d have a go at making that style of party game, with one big screen to show the board and players joining on their phones. I've struggled to get into some of Jackbox's games in the same way as a group board game though, so I was aiming to create something in that Jackbox style but with more traditional card-based and turn-based gameplay.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxs3gyqt4ewmhgluj04dd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxs3gyqt4ewmhgluj04dd.png" width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;
I'm not an artist, but pulled together enough simple assets for a proof-of-concept!



&lt;h2&gt;
  
  
  The overall idea
&lt;/h2&gt;

&lt;p&gt;The core concept of the game is that the players play action cards to move around the map, attack each other, defend, and so on. The catch is that each turn the players secretly choose 4 action cards per turn, but then everyone's first card activates together, followed by everyone's second card, etc. This means that in order to win you need to predict where your opponents will move this turn, when they will attack, and so on.&lt;/p&gt;

&lt;p&gt;(there's a bit more about &lt;a href="https://github.com/binary-koan/all-seeing-wizards#how-to-play" rel="noopener noreferrer"&gt;how to play&lt;/a&gt; on GitHub)&lt;/p&gt;

&lt;p&gt;This also means that it's important to be able to "preview" a set of actions in the player view while people are choosing cards, then gradually apply those actions to the game state and animate them in the host view so everyone understands what just happened.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftgkz2vzguci74xjxtgbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftgkz2vzguci74xjxtgbv.png" width="800" height="1731"&gt;&lt;/a&gt;&lt;br&gt;A player in the middle of picking cards sees a semi-transparent preview of their actions
  &lt;/p&gt;

&lt;p&gt;The issue with this is that game programming traditionally uses mutable state and imperative programming, meaning the game state is updated in place each time it changes and there's no easy way to "preview" and "revert" updates. There are of course ways around this, but I like functional programming and this seemed like an interesting place to try a non-traditional approach with immutable state handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Immutable basics
&lt;/h2&gt;

&lt;p&gt;Enter &lt;a href="https://immutable-js.com/" rel="noopener noreferrer"&gt;Immutable.js&lt;/a&gt;, a library for creating and updating immutable state in JavaScript. With usual mutable JavaScript objects you might write something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gameState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;players&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;character&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;darkLord&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;hp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;gameState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;hp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Immutable.js you might write it more like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fromJS&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;immutable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gameState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fromJS&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;players&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;character&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;darkLord&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;hp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newGameState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gameState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setIn&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;players&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that in the first example the original game state was lost, but in the second example we now have both the original and modified game state.&lt;/p&gt;

&lt;p&gt;This approach is more performant than it looks; Immutable.js will reuse existing objects wherever possible, so rather than creating a clone of the entire state, it only clones the objects needed to express the new properties. If you have 4 players and modify one of them, the same object references will be returned for the other three.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/immutable-js/immutable-js" rel="noopener noreferrer"&gt;Immutable.js README&lt;/a&gt; has a much more complete description of immutability and why you might want to use the library. Also worth mentioning that &lt;a href="https://immerjs.github.io/immer/" rel="noopener noreferrer"&gt;Immer&lt;/a&gt; is an alternative which is a bit easier to get started with.&lt;/p&gt;

&lt;h2&gt;
  
  
  In the game
&lt;/h2&gt;

&lt;p&gt;The way this works in practice is a bit more complex, but follows the same idea. The core piece of logic is a function called &lt;a href="https://github.com/binary-koan/all-seeing-wizards/blob/master/common/src/performTurn.ts" rel="noopener noreferrer"&gt;&lt;code&gt;performTurn&lt;/code&gt;&lt;/a&gt;, which takes a game state including players who have each picked cards to play that turn, and returns the new game state after the turn is complete (plus a list of what actions happened during the turn).&lt;/p&gt;

&lt;p&gt;In vastly simplified terms the function looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;game_state = original_game_state

for i in 1 to 4:
  game_state = apply cards placed in slot i

game_state = discard picked cards and draw next hands

return game_state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important thing about this is that it's a &lt;em&gt;pure function&lt;/em&gt;; it doesn't change the original game state and just returns a new altered state. This means I can easily do all the following&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Display the current game state on the player and host screens&lt;/li&gt;
&lt;li&gt;Overlay the expected movements and attacks on the player screen when they pick cards, by calling &lt;code&gt;performTurn&lt;/code&gt; with the cards they picked&lt;/li&gt;
&lt;li&gt;Remove that overlay when they deselect cards&lt;/li&gt;
&lt;li&gt;Immediately compute and persist the new game state on the server once all players have picked cards (to maintain data consistency - the server could crash at any point and the game would always be in a state where you can continue playing)&lt;/li&gt;
&lt;li&gt;Gradually compute and display the new game state on the host display once the server has updated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because all the functions involved are pure and idempotent (the same input will always result in the same output), the server and client can trust that the same actions applied to the same initial state will definitely get the same results, so each client can safely apply the actions without needing constant confirmation from the server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvefh1irl9j5ri1upjrtf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvefh1irl9j5ri1upjrtf.png" width="800" height="1246"&gt;&lt;/a&gt;&lt;/p&gt;
The host display plays through all players' actions and shows their effects



&lt;h2&gt;
  
  
  Side note: Shared logic
&lt;/h2&gt;

&lt;p&gt;This setup is doubly convenient because the core game logic is actually shared between the server and client. Since the whole project is built in TypeScript, I realised that rather than having the server and client constantly communicate about game states (increasing latency and network usage) I could just put the game logic in a shared folder and import it into both the server and client code.&lt;/p&gt;

&lt;p&gt;Obviously it's still important to make sure the server has the "master" copy of the data and prevent clients from making arbitrary modifications, but with a clearly defined websocket interface I think overall this has the best of both worlds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;This project setup was inspired by a screencast by Gary Bernhardt (of &lt;a href="https://www.destroyallsoftware.com/talks/wat" rel="noopener noreferrer"&gt;"Wat"&lt;/a&gt; fame) called &lt;a href="https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell" rel="noopener noreferrer"&gt;"Functional Core, Imperative Shell"&lt;/a&gt;. This sounded hard to implement in most production applications but a great idea in concept, so I wanted to try it in a smaller project which already has a conveniently clear boundary between the core (game logic) and shell (client, network and database handling).&lt;/p&gt;

&lt;p&gt;By the way, I can highly recommend his Destroy All Software screencasts in general - as well as specific techniques they have a ton of valuable insights for how to think about code.&lt;/p&gt;

&lt;h2&gt;
  
  
  And finally
&lt;/h2&gt;

&lt;p&gt;My general point here is that there's always more than one way to approach a problem in any field, and sometimes you can get surprising advantages from going against whatever approach is standard in that field. Imperative and functional programming each have their tradeoffs, and each sometimes finds value in unlikely places.&lt;/p&gt;

</description>
      <category>devmeme</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Yet another post about SolidJS vs React</title>
      <dc:creator>Jono M</dc:creator>
      <pubDate>Thu, 12 Jan 2023 21:11:47 +0000</pubDate>
      <link>https://dev.to/binarykoan/yet-another-post-about-solidjs-vs-react-3i1a</link>
      <guid>https://dev.to/binarykoan/yet-another-post-about-solidjs-vs-react-3i1a</guid>
      <description>&lt;p&gt;I've recently been working on a &lt;a href="https://github.com/binary-koan/sconet"&gt;little personal finance app&lt;/a&gt; as a way of learning and experimenting with &lt;a href="https://bun.sh/"&gt;Bun&lt;/a&gt; and &lt;a href="https://www.solidjs.com/"&gt;SolidJS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I originally built it in &lt;a href="https://redwoodjs.com/"&gt;RedwoodJS&lt;/a&gt;, but wasn't super happy with the TypeScript integration and found React a bit slow and hard to optimise on mobile. (Yes, it was probably my fault for writing a slow UI. But hey, it's a personal project, so sometimes it's more fun to try a different framework than optimise the current one.)&lt;/p&gt;

&lt;p&gt;In the JavaScript ecosystem a new framework comes out every other day, so why bother with Solid? Nothing the framework does felt super revolutionary to me - Svelte already had a "compile JSX to DOM operations" approach, Vue already had an observable reactivity model, and there are many frameworks that look like React but are smaller and/or perform better. Where Solid stood out was in combining those into a simple(ish - we'll get to that), coherent and minimal-but-fully-featured package.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cost of reactivity
&lt;/h2&gt;

&lt;p&gt;If you're coming from React, the way Solid works takes a bit of wrapping your head around. But once you figure it out you have a moment of epiphany and wonder "why doesn't React work like this?"&lt;/p&gt;

&lt;p&gt;Let's look at a simple example to illustrate this. In React you might write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNumber&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;squared&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;squared&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;squared&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A couple of things about this are suboptimal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each time &lt;code&gt;number&lt;/code&gt; gets updated, the &lt;em&gt;whole function body is re-executed&lt;/em&gt;. This won't be noticeable now, but when you have a big component tree and something changes at the top, it can be tricky to avoid those extra milliseconds executing every function in the tree&lt;/li&gt;
&lt;li&gt;Re-executing the function isn't the only work that will be done when &lt;code&gt;number&lt;/code&gt; is updated. React will also &lt;em&gt;build a whole tree of JavaScript objects&lt;/em&gt; for the elements on the page and use its Virtual DOM to create a diff and apply the updates to the page&lt;/li&gt;
&lt;li&gt;There's a subtle issue with the &lt;code&gt;onClick&lt;/code&gt; handler - because we create a new function every time this component is rendered, it will &lt;em&gt;remove and re-add an event listener on the element every time&lt;/em&gt;. This is yet more unnecessary work. We can avoid that with &lt;code&gt;useCallback&lt;/code&gt;, but in my experience that trick is not obvious or easy to remember for most developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's try converting this to Solid then. Solid has &lt;code&gt;createSignal&lt;/code&gt; which on the surface works pretty similarly to &lt;code&gt;setState&lt;/code&gt;, so we can naively try this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNumber&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;squared&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;squared&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;squared&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running it gives us:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HxsPNzKf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j28eft8vno2dq0o8f13t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HxsPNzKf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j28eft8vno2dq0o8f13t.png" alt="Output: 0 squared is NaN" width="308" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well that didn't work. One key difference between Solid's &lt;code&gt;createSignal&lt;/code&gt; and React's &lt;code&gt;useState&lt;/code&gt; is that when we reference the state we need to use a function call, i.e. &lt;code&gt;number()&lt;/code&gt; instead of &lt;code&gt;number&lt;/code&gt;. This is because it's not just a number; it's an observable reactive value, which means when it changes Solid can detect the change and work out which exact parts of the page need to be updated with the new value.&lt;/p&gt;

&lt;p&gt;So let's find and replace &lt;code&gt;number&lt;/code&gt; with &lt;code&gt;number()&lt;/code&gt; and see what happens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4JvWJGYw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fytyd3dhwui2octks2m0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4JvWJGYw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fytyd3dhwui2octks2m0.png" alt="Output: 4 squared is 0" width="266" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a lot closer, but something is still not right. It's now incrementing the number correctly, but &lt;code&gt;squared&lt;/code&gt; is not responding.&lt;/p&gt;

&lt;p&gt;Let's extrapolate the same rule: using reactive values should look like function calls. So what if we make &lt;code&gt;squared&lt;/code&gt; a function as well? Let's try &lt;code&gt;squared = () =&amp;gt; number() * number()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AQXz6USx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9gbvtskm40mwkblw307.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AQXz6USx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9gbvtskm40mwkblw307.png" alt="Output: 4 squared is 16" width="288" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Success! Now we have the same reactive UI, written in a style which is subtly different but recognisably the same idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNumber&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createSignal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;squared&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt; &lt;span class="nx"&gt;squared&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;squared&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://playground.solidjs.com/anonymous/dd6cb6dc-aaef-4e41-a26c-166c68150d23"&gt;Try it on Solid Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In comparison to the three issues with React above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The function body is &lt;em&gt;only executed once&lt;/em&gt;

&lt;ul&gt;
&lt;li&gt;We know this because &lt;code&gt;squared&lt;/code&gt; didn't update in our second attempt&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;number&lt;/code&gt; is updated, &lt;em&gt;only the text in the element will be updated&lt;/em&gt;; there's no big JavaScript object tree and expensive diffing calculation

&lt;ul&gt;
&lt;li&gt;We can sort of see this by looking at the generated output code on Solid Playground. There are a couple of calls to Solid's internal &lt;code&gt;insert&lt;/code&gt; function, which basically watches a reactive value and does a single DOM update when it changes&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The event handler is &lt;em&gt;only created once&lt;/em&gt;

&lt;ul&gt;
&lt;li&gt;We can see this in the output on Solid Playground as well. There's a line looking like &lt;code&gt;_el$.$$click = () =&amp;gt; setNumber(number() + 1)&lt;/code&gt;, and reading through the code around it we can see that it's in a function that's created and then immediately executed once&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So Solid's reactivity works something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some Solid functions like &lt;code&gt;createSignal&lt;/code&gt; return special reactive values&lt;/li&gt;
&lt;li&gt;We can get the current value with a function call, and any UI which depends on that will be reactively updated&lt;/li&gt;
&lt;li&gt;To compute values while maintaining reactivity, we need to create functions; then the function will be automatically re-executed when the underlying reactive state changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cool knock-on effects
&lt;/h2&gt;

&lt;p&gt;This reactivity system also makes side effects and global state much nicer.&lt;/p&gt;

&lt;p&gt;To do side effects, in React you might write something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number was updated to&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But because Solid can watch reactive values and re-run functions when they change, in Solid you can just write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number was updated to&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No need to specify a list of dependencies and add ESLint plugins to make sure you don't forget any. Just use those reactive values and you're done.&lt;/p&gt;

&lt;p&gt;For global state, in React you probably need a helper function from a library like &lt;code&gt;createGlobalState&lt;/code&gt; from &lt;a href="https://github.com/streamich/react-use"&gt;react-use&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But in Solid, you can just call &lt;code&gt;createSignal&lt;/code&gt; at the top level to create global reactive state - it's convention to call it in components but it works the same anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  That seems so simple and consistent!
&lt;/h2&gt;

&lt;p&gt;Well ... yes and no.&lt;/p&gt;

&lt;p&gt;This function-call-style essentially exists to get around the limitations of JavaScript's primitive values (numbers, booleans, and so on). Once you start dealing with objects, constructs like Proxies exist which can fulfil the same purpose entirely transparently.&lt;/p&gt;

&lt;p&gt;Because of this, props and stores (more complex state management) break this function call convention and just look like regular objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Numberer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;myContrivedStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStore&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createStore&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;oneLess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
    &lt;span class="na"&gt;oneMore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;oneLess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;oneMore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;oneLess&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;setStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;oneMore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;One&lt;/span&gt; &lt;span class="na"&gt;less&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;myContrivedStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;oneLess&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nx"&gt;one&lt;/span&gt; &lt;span class="na"&gt;more&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;myContrivedStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;oneMore&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Either of these systems would be fine on their own, but in combination they can get confusing. It also means that instead of natively destructuring props you need to use the somewhat awkward &lt;code&gt;splitProps&lt;/code&gt; helper function.&lt;/p&gt;

&lt;p&gt;To be honest I wish everything just consistently used function calls, but that has its own drawbacks such as becoming increasingly awkward and heavy with deeply nested objects. I wonder if it would be possible to build an editor plugin that detects and highlights which variables are reactive (JavaScript is too dynamic to do that perfectly, but with TypeScript it ought to be possible to highlight typed variables at least).&lt;/p&gt;

&lt;p&gt;Anyway, all this means Solid's reactivity system takes a bit of wrapping your head around - you need to get used to remembering which variables are reactive vs regular objects - but once you get the hang of it the framework feels more natural and expressive than React while also generally being &lt;a href="https://krausest.github.io/js-framework-benchmark/index.html"&gt;only a few percentage points slower than vanilla JS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is React bad then?
&lt;/h2&gt;

&lt;p&gt;No, of course not. There are huge numbers of companies using React in production and their apps work just fine. There's also a giant ecosystem around React, while Solid is still relatively young and doesn't have the same number of supporting libraries and frameworks.&lt;/p&gt;

&lt;p&gt;But Solid does seem to be gathering momentum (at least looking at GitHub stars!) and it might just be in the sweet spot of "simple enough and similar enough to React to learn easily, but different enough to be worth learning".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://star-history.com/#solidjs/solid"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--05pb99Jb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/skhbei4ithyudb7rjqn6.png" alt="SolidJS star history - sharply spiking coming into 2022/23" width="880" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can't say whether Solid is the right choice for your next giant enterprise project, but it's something to keep an eye on and I'm definitely rooting for it to succeed.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>solidjs</category>
    </item>
    <item>
      <title>Adventures learning Python</title>
      <dc:creator>Jono M</dc:creator>
      <pubDate>Wed, 11 Jan 2023 21:01:59 +0000</pubDate>
      <link>https://dev.to/binarykoan/adventures-learning-python-21jh</link>
      <guid>https://dev.to/binarykoan/adventures-learning-python-21jh</guid>
      <description>&lt;p&gt;I've recently been looking at some open source Python projects and thinking I should give it a go again. I last seriously did Python during university, and since then I've basically been on the Ruby train. But reading through some open source code, I was pleasantly surprised by how readable Python is - enough that I thought I'd try and build a little project in it.&lt;/p&gt;

&lt;p&gt;It's been quite a fun journey: Python is similar enough to my most used languages that it doesn't take a huge amount of effort to pick up, but different enough that the differences really stand out and take some thought and research to work around.&lt;/p&gt;

&lt;h2&gt;
  
  
  The good
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Python has types now!
&lt;/h3&gt;

&lt;p&gt;This was quite an exciting find, and made picking the language back up again a lot easier than I expected. It was especially nice to have auto-complete, auto-import and explanatory inline documentation for most of the libraries I added (yes, not all of those require a type system, but they're enhanced by having one).&lt;/p&gt;

&lt;p&gt;The usability of the type system feels somewhere between TypeScript (awesome) and Ruby (underwhelming). It's nice to have built-in syntax for parameter and return types - doing this in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is much nicer than the equivalents in Ruby type checkers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Sorbet, struggling to coerce a type system into Ruby syntax&lt;/span&gt;
&lt;span class="n"&gt;sig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;x: &lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# or RBS, putting the signature in a separate file&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;x: &lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;

&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, there are still some places where type checking feels tacked-on rather than a core feature of the language. It's weird to me that types like &lt;code&gt;str&lt;/code&gt; and &lt;code&gt;int&lt;/code&gt; can be used without imports, but the &lt;code&gt;Any&lt;/code&gt; type requires &lt;code&gt;from typing import Any&lt;/code&gt;. The idea of having an opt-in typing package like that is nice, but TypeScript seems to have a more sensible distinction between built-in and imported types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Named parameters
&lt;/h3&gt;

&lt;p&gt;I was ambivalent on named parameters last time I used Python, but my concern for readability has increased a lot since then and they're now one of my favourite features. JavaScript's explicit object syntax is awkward, Ruby's implementation with separate positional and named parameters better, Swift's internal and external names are fun but clunky, but Python's "any parameter can be used with a name" is a wonderfully simple and flexible implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'127.0.0.1'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;# can be used like
&lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'0.0.0.0'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# easily override any parameter
&lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# if it's easy to read, omit the name
&lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# if it seems a bit unclear, add the name
# and many more combinations
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where in other languages you need to carefully think "when this is used, will the parameters be easy to understand?" while writing a function, in Python you just give the parameters sensible names and let whoever is using the function decide what will read best.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 50/50
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Imports
&lt;/h3&gt;

&lt;p&gt;I remember when I used to like Ruby's &lt;code&gt;require&lt;/code&gt; system where everything gets dumped into the global namespace. After working on some huge Rails projects, I'm now much more of a fan of JavaScript/TypeScript's import system which neatly isolates everything with none of Ruby's name clashes or weird namespacing errors. So I was happy to find that Python's imports work much the same way.&lt;/p&gt;

&lt;p&gt;That said, I still don't really understand the import system. I especially don't understand why other projects I've seen can use &lt;code&gt;from ..some.relative.looking.folder import ...&lt;/code&gt; and I can't. But I can use &lt;code&gt;from some.absolute.path.in.my.project import ...&lt;/code&gt;, which seems more convenient anyway, so I don't know why some projects seem to avoid using that. I also find it a bit weird that imports use dots but effectively refer to folders and files.&lt;/p&gt;

&lt;p&gt;So I guess I'm ambivalent. I like the isolation of Python's module system compared to Ruby, but it doesn't feel as immediately understandable as ES Modules - as a relative beginner it takes more background knowledge and context to work out how to create a &lt;code&gt;models/__init__.py&lt;/code&gt; and then do &lt;code&gt;from models import stuff&lt;/code&gt; compared to just creating &lt;code&gt;models.js&lt;/code&gt; and do &lt;code&gt;import stuff from './models.js'&lt;/code&gt;. But I have to assume Python's import rules are something you learn once and then aren't a big deal in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bad
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lambdas are awkward
&lt;/h3&gt;

&lt;p&gt;I'm very used to doing nice functional data manipulation in JavaScript and Ruby, and it's sad to see that Python still can't do that level of expressive data manipulation. Where in Ruby I can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;users_by_email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;group_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in Python I need to write out the lambdas with somewhat verbose syntax, import one of the functions, and write it "backwards" because these are functions rather than methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;users_by_email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see how this would get complex with longer chains of methods. Obviously you can write this in different ways, but to me it makes the most sense to think in terms of small pieces of logic and visualise the data gradually changing as it flows through a pipeline, and expressing that is frustratingly awkward in Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  No safe navigation
&lt;/h3&gt;

&lt;p&gt;In web development there's often a lot of interaction with third party APIs where the response structure is ambiguous or changeable, and as far as I've found data access in Python is relatively awkward.&lt;/p&gt;

&lt;p&gt;Unlike JavaScript's safe navigation syntax (&lt;code&gt;response?.data?.user?.id&lt;/code&gt;) or Ruby's &lt;code&gt;dig&lt;/code&gt; method (&lt;code&gt;response.dig(:data, :user, :id)&lt;/code&gt;), Python's default dict access feels very limiting. You seem to end up doing a bunch of things like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s"&gt;"data"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="c1"&gt;# or
&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;both of which feel long and complex compared to JavaScript and Ruby.&lt;/p&gt;

&lt;p&gt;It's a similar story with objects: if you have an object which may or may not be present, there's no easy way to &lt;/p&gt;

&lt;p&gt;Libraries like &lt;code&gt;glom&lt;/code&gt; seem to alleviate the problem a bit for dicts and arrays, but the general lack of built-in null checking (or None checking, I suppose) feels worrying to me coming from the safety of TypeScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Procedural or OO?
&lt;/h3&gt;

&lt;p&gt;One of my favourite things about Ruby is how consistent it is - "everything is an object" is a powerful concept which makes doing pretty much anything in Ruby feel nice and consistent with everything else.&lt;/p&gt;

&lt;p&gt;Python doesn't have this, so for someone like me who isn't used to the language it feels confusing why some things are methods on objects and others are just functions. Why is &lt;code&gt;list.count()&lt;/code&gt; a method but &lt;code&gt;filter()&lt;/code&gt; is a function?&lt;/p&gt;

&lt;h2&gt;
  
  
  Overall
&lt;/h2&gt;

&lt;p&gt;If you count things up, it seems I have more gripes about Python than things I enjoy. That doesn't tell the full story though; there are plenty of things I didn't mention because they're good enough to just work and stay in the background, which at the end of the day is how things should be in a language.&lt;/p&gt;

&lt;p&gt;So although it's still early days, I have a more positive view of Python and I'm curious enough to keep looking for solutions or workarounds for some of those annoyances.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
    </item>
  </channel>
</rss>
