<?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: Robert Rees</title>
    <description>The latest articles on DEV Community by Robert Rees (@rrees).</description>
    <link>https://dev.to/rrees</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%2F132143%2Fefaefcec-ced7-45f7-ae7d-531b5c4d9aa1.jpeg</url>
      <title>DEV Community: Robert Rees</title>
      <link>https://dev.to/rrees</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rrees"/>
    <language>en</language>
    <item>
      <title>The e-commerce coding challenge vs. the real world</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Sun, 18 Aug 2024 10:43:39 +0000</pubDate>
      <link>https://dev.to/rrees/the-e-commerce-coding-challenge-vs-the-real-world-4gn3</link>
      <guid>https://dev.to/rrees/the-e-commerce-coding-challenge-vs-the-real-world-4gn3</guid>
      <description>&lt;p&gt;Creating an outline online shop seems quite a popular coding challenge. Even in businesses that don't seem to have any relation to this business model.&lt;/p&gt;

&lt;p&gt;However defining the behaviour for how an online shop should handle orders is really complex. For the purpose of coding challenges I think that most organisations who set it really just want to handle concurrent ordering in simple ways with a quantity on the data entity representing the inventory item (the row or the document typically).&lt;/p&gt;

&lt;p&gt;I get the impression that most people who set this problem want stock quantity to operate in serial. Each order attempts to assign stock to fulfil it when the order processing happens. Ideally people are ordering different things and the orders can happen in parallel but if there's a conflict it is first come, first served according to the process that first acquired the lock (rather than when the order was placed).&lt;/p&gt;

&lt;p&gt;I think basically people are asking for a table or database lock with a row or document lock for each item in the order as being a solution less likely to cause performance issues or deadlocking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inventory = Stock - Orders
&lt;/h2&gt;

&lt;p&gt;I've actually worked in a grocery business though and this model is not at all how the inventory system actually worked. I've also attended some interesting talks about how to implement allocation or auction systems for retail systems where items are potentially unique (such as Etsy or vintage fashion) or very small (fashion "drops").&lt;/p&gt;

&lt;p&gt;None of these systems combine the inventory with the definition of the item.&lt;/p&gt;

&lt;p&gt;For the system I actually worked on it recorded the following things separately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the quantity of items that had actually been checked in and shelved in the warehouse&lt;/li&gt;
&lt;li&gt;the orders with suppliers and the orders from customers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our terms and conditions meant that orders were actually requests from customers and we would only honour them if stock was available. Similarly if we had "buy one get one free" (BOGOF) style promotions we would allocate stock to orders to try and maximise the fulfilment of promotions but once the stock ran out we would then go to substitution logic to try and fulfil the desired quantity of the order.&lt;/p&gt;

&lt;p&gt;The concept of our inventory then was actually quite complex and was basically the quantity on hand for the exact Stock Keeping Unit (SKU) code minus the customer orders for those SKUS. This meant our inventory quantities could be negative.&lt;/p&gt;

&lt;p&gt;For negative inventory our buyers would be expected to try and purchase just enough supply before the fulfilment deadline to match the demand.&lt;/p&gt;

&lt;p&gt;If we got to the fulfilment time and the stock could not be "picked" (transferred from the warehouse shelves to the transport container) then we would "short" the order and if necessary refund the customer.&lt;/p&gt;

&lt;p&gt;I believe we had this setup because the order was considered a kind of asset and therefore we could borrow money in the form of a short-term overdraft to do the necessary purchasing to fulfil the order. The less inventory we had on had in the warehouse the more, perhaps paradoxically, we could sell as we didn't need to store the full amount for all orders.&lt;/p&gt;

&lt;p&gt;Amazon seems to do the same thing offering items that might be fulfilled in the future or a substitute in the shopping experience. They obviously must be in a different league for how they manage this and allocate purchases between their own inventory and partners.&lt;/p&gt;

&lt;p&gt;The system delivered "fairness" in order fulfilment by using an ordered queue where each order was processed based on its submission time. Our orders didn't have to be fulfilled in real-time (which is like quite a few real-world systems) so the time to actually place the order didn't matter. Even if your order was first placed it might not be completed in full though, for reasons explained in the next section.&lt;/p&gt;

&lt;p&gt;I'm not sure the queue idea would be accepted as a solution in a coding challenge though as it creates a bottleneck if orders are disjunct. You'd probably get dinged for not scaling (despite it working in the real world).&lt;/p&gt;

&lt;h2&gt;
  
  
  Allocating stock
&lt;/h2&gt;

&lt;p&gt;In our fulfilment process, stock was allocated across all orders for the ordering period to try and ensure that the maximum number of customers received some fulfilment of the order. This makes sense from a wholesale perspective because the customer will just try and order more in the next order cycle (or source from elsewhere if they can).&lt;/p&gt;

&lt;p&gt;I'm trying to remember if BOGOF was assigned as a unit to each customer. I'm not sure but I think it was because again you want to try and maximise the number of customers who get the benefit of the discount rather than allocating all of it to the earliest bulk orders.&lt;/p&gt;

&lt;p&gt;It is a very different model from Etsy though. I imagine there each order is allocated stock according to the time of its receipt but it is clear that something in your basket can be out of stock when you order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing requirements
&lt;/h2&gt;

&lt;p&gt;Often with these tests you get a hand-waving statement that your ability to deal with ambiguous requirements is also part of the test. Well that might be true but since you are often assessed on whether you implemented the ambiguous requirements "correctly" it feels like there is often hidden information. The kind of thing that in the real world you try and flush out with prototypes, workshops and conversations between all the project stakeholders. Those of kind of skills aren't actually being tested here.&lt;/p&gt;

&lt;p&gt;You could allow a refinement phase of questions that are answered after the problem statement has been given but I haven't seen that much myself and on the other side I've seen candidates asking questions about how a problem should be solved classified as "problematic".&lt;/p&gt;

&lt;p&gt;So really I think if you want to use the e-commerce shop as a test then you also have an obligation to explain how you want inventory and orders to be handled. You need to explain whether orders can be partially fulfilled. You need to say how the concept of being out of stock works for your case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is this is a shop?
&lt;/h2&gt;

&lt;p&gt;But my other thought is that perhaps this is a poor kind of problem to set. It is too fraught with interpretation and assumptions of how things should work.&lt;/p&gt;

&lt;p&gt;Maybe a problem domain that is much less ambiguous would work better. For example booking a theatre seat makes it clearer that the inventory is limited and that you can't sell the same item twice. Of course theatres and cinemas have their own twists in the form of not allowing single seats between bookings.&lt;/p&gt;

&lt;p&gt;Maybe using an antiques shop as the example is clearer, each item is unique and therefore stock is not a concern. Each item in an order is equally desirable so you don't need to worry about partial or total fulfilment.&lt;/p&gt;

&lt;p&gt;A little more thought in the problem statement makes it easier to push the candidate towards the skills you want them to demonstrate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I think sometimes you can be cursed with too much knowledge of a problem. That is why abstract problems are sometimes seen as preferable despite the bias it creates towards prior knowledge.&lt;/p&gt;

&lt;p&gt;The reason I wrote this was to let off a little steam but I'm also interested in the views of both candidates and employers. Why does this problem get used by employers that really don't do meaningful retail? How stressful is it for candidates to deal with these ambiguous requirements? Is this in any way a good coding test? What are the key things it demonstrates?&lt;/p&gt;

</description>
      <category>interview</category>
      <category>hiring</category>
    </item>
    <item>
      <title>Spartan</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Sun, 28 Jul 2024 13:17:15 +0000</pubDate>
      <link>https://dev.to/rrees/spartan-5525</link>
      <guid>https://dev.to/rrees/spartan-5525</guid>
      <description>&lt;p&gt;&lt;a href="http://portal.mozz.us/spartan/spartan.mozz.us/" rel="noopener noreferrer"&gt;Spartan&lt;/a&gt; (&lt;a href="https://github.com/michael-lazar/spartan" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;) is a hobbyists' protocol that returns to plain text over network sockets.&lt;/p&gt;

&lt;p&gt;This is where HTTP started but as the requirements for a protocol that basically underpins the global information and service system has grown it has been increasingly impractical for an individual to implement a reasonably complete HTTP 2 or 3 server.&lt;/p&gt;

&lt;p&gt;But what if, instead of selling things you were just interested in sharing information and had an interest in understanding more of your protocol stack? Well Spartan is for you.&lt;/p&gt;

</description>
      <category>spartan</category>
      <category>protocols</category>
    </item>
    <item>
      <title>Typescript tuples aren't tuples</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Tue, 16 Jul 2024 13:53:17 +0000</pubDate>
      <link>https://dev.to/rrees/typescript-tuples-arent-tuples-28kj</link>
      <guid>https://dev.to/rrees/typescript-tuples-arent-tuples-28kj</guid>
      <description>&lt;p&gt;I came across some surprising behaviour recently. One of the defining features of tuples is that they can be considered equal if each member of the tuple in the equivalent position is equal.&lt;/p&gt;

&lt;p&gt;So the tuple &lt;code&gt;[1, 3]&lt;/code&gt; should be equal to the tuple &lt;code&gt;[1,3]&lt;/code&gt;, but in Typescript they are not because tuples in Typescript are a way of describing the types of heterogeneous arrays (which normally take a single type for all the elements within them).&lt;/p&gt;

&lt;p&gt;Arrays are only equal if they are the same reference and there are no special rules for value equality for them in Javascript, which ultimately what we're writing here.&lt;/p&gt;

&lt;p&gt;I'm not sure what a better name for what Typescript &lt;a href="https://www.typescriptlang.org/play/?#example/tuples" rel="noopener noreferrer"&gt;calls tuples&lt;/a&gt;, maybe typed arrays, but the current name does carry some inconvenient expectations for those of us coming from other languages.&lt;/p&gt;

</description>
      <category>typescript</category>
    </item>
    <item>
      <title>Server-side rendered Web Components</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Sun, 05 May 2024 14:49:44 +0000</pubDate>
      <link>https://dev.to/rrees/server-side-rendered-web-components-34pl</link>
      <guid>https://dev.to/rrees/server-side-rendered-web-components-34pl</guid>
      <description>&lt;p&gt;I recently wrote a post about &lt;a href="https://dev.to/rrees/why-are-web-components-interesting-1p53"&gt;why I thought Web Components were finally having a moment&lt;/a&gt; and the comment thread was filled with a lot of discussion about server-side rendering that I felt missed the point that Web Components are primarily about adding interactivity to web pages rather than being a component system for building them. When I wrote the post I assumed that people would create the content using server-side rendering as they would normally.&lt;/p&gt;

&lt;p&gt;However since I wrote that post the &lt;a href="https://enhance.dev/wasm" rel="noopener noreferrer"&gt;Enhance WASM&lt;/a&gt; (&lt;a href="https://github.com/enhance-dev/enhance-ssr-wasm" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;) actually allows you to server-side render Web Components which makes the question more than an odd hypothetical.&lt;/p&gt;

&lt;p&gt;I'm still not sure that most organisations and developers actually have a use case for needing server-side rendered Web Components. I feel that often server-side rendered React is mostly about developers not having to learn another templating language on top of JSX, but if it matters to you then it is now at least possible.&lt;/p&gt;

</description>
      <category>enhancewasm</category>
      <category>webcomponents</category>
      <category>ssr</category>
    </item>
    <item>
      <title>Why are Web Components interesting?</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Mon, 11 Mar 2024 12:29:46 +0000</pubDate>
      <link>https://dev.to/rrees/why-are-web-components-interesting-1p53</link>
      <guid>https://dev.to/rrees/why-are-web-components-interesting-1p53</guid>
      <description>&lt;p&gt;I've been increasingly interested in Web Components and trying to understand how I can rewrite my historic code to use this standard. Most developers I talk to though are pretty much &lt;code&gt;frontend===React&lt;/code&gt;: what is this strange thing you're talking about?&lt;/p&gt;

&lt;p&gt;The dominance of virtual DOM frontends with complex lifecycles and associated tool chains means that people have invested a lot of intellectual and emotional effort into these tools and genuinely think they are the best way to deliver web experiences to people. This post is not going to change their views and I think it is genuinely hard to do that. Enterprise computing is probably going to be using React, Angular and other frameworks for a while yet.&lt;/p&gt;

&lt;p&gt;If you are not particularly wedded to a particular frontend approach then Web Components have a few things that make them interesting. Firstly, they are standards compliant. They are available in all browsers, work consistently and require no libraries, bundles or WASM compilers to run. It is easier to re-use Web Components because of this standards approach as the baseline functionality is clear across all deployments. This simply isn't true of VueJS and React. When you make a choice of what is essentially a mini-language you are then stuck in that ecosystem with no shared runtime. Weirdly I've seen Web Components used as bridge between different components in production and it actually worked quite well, allowing different rendering and event handling approaches but co-ordinating state.&lt;/p&gt;

&lt;p&gt;Web Components offer the opportunity to try and get back to &lt;a href="https://www.gov.uk/service-manual/technology/using-progressive-enhancement" rel="noopener noreferrer"&gt;progressively enhanced experiences&lt;/a&gt; that with reduced dependency on virtual rendering and Javascript could be &lt;a href="https://developer.mozilla.org/en-US/blog/introduction-to-web-sustainability/" rel="noopener noreferrer"&gt;more sustainable&lt;/a&gt;. They are easy to add on top of regular HTML and seem to fail with more safety than virtual rendering which tends to completely fail on a problem leaving a blank page or component.&lt;/p&gt;

&lt;p&gt;The final thing that is interesting is that Web Components are a lower-power solution, they literally just allow you to create new elements and encapsulate behaviour. They are not also trying to provide a styling, state or templating solution so you are able to compose them with other technologies. Some people like ShadowDOM, some don't but by having smaller modules of standards-based behaviour people can use a common-base to take different approaches.&lt;/p&gt;

&lt;p&gt;If you haven't looked at Web Components it doesn't take long to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements" rel="noopener noreferrer"&gt;work through the basics&lt;/a&gt; and I would really recommend knowing them alongside any preferred virtualised framework you may have learnt or used day to day.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webcomponents</category>
      <category>webstandards</category>
    </item>
    <item>
      <title>Make your Faker unit tests run faster with this one weird tip</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Thu, 07 Mar 2024 07:24:58 +0000</pubDate>
      <link>https://dev.to/rrees/make-your-faker-unit-tests-run-faster-with-this-one-weird-tip-4mbc</link>
      <guid>https://dev.to/rrees/make-your-faker-unit-tests-run-faster-with-this-one-weird-tip-4mbc</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/faker-js/faker" rel="noopener noreferrer"&gt;FakerJS&lt;/a&gt; has a &lt;a href="https://github.com/faker-js/faker/issues/1791" rel="noopener noreferrer"&gt;bug&lt;/a&gt; that is a classic example of over-eager initialisation.&lt;/p&gt;

&lt;p&gt;Naively importing the library as per the Readme can lead to a massive slowdown in tests that are often meant to be some of the fastest in your suite.&lt;/p&gt;

&lt;p&gt;In my case I was importing string functionality to tests content boundaries so even though I was actually trying to create &lt;em&gt;any&lt;/em&gt; localised data I was initialising &lt;em&gt;all&lt;/em&gt; of the localised content leading to my tests timing out for a simple validation.&lt;/p&gt;

&lt;p&gt;The weird tip is simply to import the &lt;code&gt;en&lt;/code&gt; locale (unless you specifically what a specific localised set of data)&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;faker&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;@faker-js/faker/locale/en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The English locale is also loaded for other languages so this genuinely seems the quickest import.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>fakerjs</category>
      <category>testing</category>
    </item>
    <item>
      <title>Validating Dependabot files</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Sun, 12 Nov 2023 10:37:20 +0000</pubDate>
      <link>https://dev.to/rrees/validating-dependabot-files-13j9</link>
      <guid>https://dev.to/rrees/validating-dependabot-files-13j9</guid>
      <description>&lt;p&gt;If your branch contains a Dependabot change then a Github action should kick in and validate it. However this seems quite erratic and I'm not sure about the logic as to when and if it happens.&lt;/p&gt;

&lt;p&gt;If you view the configuration file you should see a validation badge in the file's header. Therefore the easiest way to validate the file is actually just to edit it directly on the main branch and check the validation on the badge (which is linked to a Github Action run.&lt;/p&gt;

&lt;p&gt;It would be really nice to have an official CLI validator for the file format, particularly as it is becoming more and more complex.&lt;/p&gt;

</description>
      <category>github</category>
      <category>dependabot</category>
      <category>ci</category>
    </item>
    <item>
      <title>How to use Jekyll's link tag with data values</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Tue, 10 Oct 2023 22:17:36 +0000</pubDate>
      <link>https://dev.to/rrees/how-to-use-jekylls-link-tag-with-data-values-k6p</link>
      <guid>https://dev.to/rrees/how-to-use-jekylls-link-tag-with-data-values-k6p</guid>
      <description>&lt;p&gt;Jekyll's &lt;a href="https://jekyllrb.com/docs/liquid/tags/#link" rel="noopener noreferrer"&gt;link tag&lt;/a&gt; is one of the gems of Jekyll for me. It makes it almost impossible to create broken links. However until recently I was not sure how to combine it with data values either from data files or from front matter. It wasn't clear to me how identities were resolved. The good news is that for the most part these work exactly as you might hope and you should always be to pass a reference to a data value to the tag and have it resolve during the build as you would expect.&lt;/p&gt;

&lt;p&gt;My first case was a data-file driven navigation bar where depending on the categories a post has I want to select a navigation root item. The relevant categories are simply keys in a data file with the path to the navigation root and the display name for the link being the value. The code is below and the only thing worth commenting on is that the &lt;code&gt;assign&lt;/code&gt; makes the data lookup clean and gives a simple name to reference the fields in the structure that has been found.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight liquid"&gt;&lt;code&gt;    &lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;category&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;categories&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
    &lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;navigation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;contains&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;category&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
    &lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;assign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;navigation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;navigation&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;category&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
    &amp;lt;p&amp;gt;&amp;lt;a href="&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;navigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;"&amp;gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;navigation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
    &lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;endif&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
    &lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;endfor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My other use case is similar, where I want pages to link back to a root or core page I want to be able to describe the name and path of the page in my front matter. The link is then part of an include that has a conditional check on the top-level front matter key existing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight liquid"&gt;&lt;code&gt;&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;hub_page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
&amp;lt;p&amp;gt; Part of &amp;lt;a href="&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;hub_page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;"&amp;gt;&lt;span class="cp"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;hub_page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="cp"&gt;}}&lt;/span&gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;endif&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much simpler than the previous example and better illustrates how tags and variable substitution can be combined.&lt;/p&gt;

</description>
      <category>jekyll</category>
      <category>ruby</category>
      <category>liquid</category>
    </item>
    <item>
      <title>Media Queries Level 4</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Sat, 09 Sep 2023 07:09:19 +0000</pubDate>
      <link>https://dev.to/rrees/media-queries-level-4-59eb</link>
      <guid>https://dev.to/rrees/media-queries-level-4-59eb</guid>
      <description>&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries" rel="noopener noreferrer"&gt;Media Queries Level 4&lt;/a&gt; may sound like possibly the worst D&amp;amp;D character class but offer a huge simplification on how to specify page-size responsive CSS.&lt;/p&gt;

&lt;p&gt;It introduces the ability to write media queries using the "&amp;lt;=&amp;gt;" operators.&lt;/p&gt;

&lt;p&gt;The previous way of writing conditions was based on &lt;code&gt;min-width&lt;/code&gt; and &lt;code&gt;max-width&lt;/code&gt;. And the thing I found confusing about it is that the max option meant "up to this width" and the min option meant "from this width".&lt;/p&gt;

&lt;p&gt;This may not be too hard to understand when you have one size that triggers a change but typically you have a few ranges where different layouts and configurations of viewable elements apply. Writing these as a set of max widths and making it maintainable amongst multiple people felt like an art.&lt;/p&gt;

&lt;p&gt;With the new standard though you can now write selectors in the following form: &lt;code&gt;@media (400px &amp;lt;= width &amp;lt;= 700px) { … }&lt;/code&gt;. I think this is very easy to understand and is closer to what you would intuitively expect to be writing. It also closes the gap between pixel pushing designs and the code you're writing to implement it.&lt;/p&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>Programming Languages (March/April 2023)</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Mon, 17 Apr 2023 07:54:18 +0000</pubDate>
      <link>https://dev.to/rrees/programming-languages-marchapril-2023-4abb</link>
      <guid>https://dev.to/rrees/programming-languages-marchapril-2023-4abb</guid>
      <description>&lt;p&gt;I've been trying a few new languages recently trying to decide if there's anything I want to try and pivot to using in the longer term.&lt;/p&gt;

&lt;p&gt;I recently had a chance to use Go but people have also recommended Rust and I would that the languages are similar enough and target enough of the same problems that the language communities feel quite strongly about one another. I've only scratched the surface of Rust currently but things I like so far are the greater explicitness in things like type casting and while I don't love strict compilers generally the error messages are actually some of the best I've seen in a long while.&lt;/p&gt;

&lt;p&gt;I tend to enjoy working in dynamic languages so I have also tried &lt;a href="https://elixir-lang.org/" rel="noopener noreferrer"&gt;Elixir&lt;/a&gt; and initially the experience was very positive but I hit a bit of a wall when it came to &lt;a href="https://inquisitivedeveloper.com/lwm-elixir-23/" rel="noopener noreferrer"&gt;pattern matching function dispatch&lt;/a&gt;, while pattern matching for destructuring is as I would expect the number of different ways that people structure their dispatch, particularly on recursive functions made me feel like I wasn't able to understand how to structure a problem. I also hit a wall with binary and string destructuring, where as lists behave in a LISPy way I ended up in a rabbit hole of type mismatch when trying to pull apart strings and differentiate between binary representations and characters. Go was equally horrible with its use of Runes for most things and ASCII for default loops.&lt;/p&gt;

&lt;p&gt;I ultimately felt I needed a better guide to the language and have paused it for now as it isn't a very popular language (even though it might have one of the &lt;a href="https://www.phoenixframework.org/" rel="noopener noreferrer"&gt;best web frameworks&lt;/a&gt; about currently).&lt;/p&gt;

&lt;p&gt;I already know Clojure but haven't been using JVM languages recently. &lt;a href="https://babashka.org/" rel="noopener noreferrer"&gt;Babashka&lt;/a&gt; is a Clojure subset that can be installed via asdf and doesn't require a JVM setup. I'm still working through the tutorial but it was a reminder of how great programming Clojure is and how simple setup can be made.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://deno.land/" rel="noopener noreferrer"&gt;Deno&lt;/a&gt; is a Typescript-based alternative to Node and it is a pretty good programming environment with a decent tutorial. However as a scripting or CLI language it suffers from asynchronous IO which adds lots of tedium compared to synchronous alternatives or simply languages that wrap their IO in better abstractions. I think I need to try and get onto the web programming side of things to see something that is maybe a stronger fit.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>deno</category>
      <category>babashka</category>
    </item>
    <item>
      <title>Using Shortcut as a project management tool</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Fri, 24 Feb 2023 14:28:06 +0000</pubDate>
      <link>https://dev.to/rrees/using-shortcut-as-a-project-management-tool-3i7f</link>
      <guid>https://dev.to/rrees/using-shortcut-as-a-project-management-tool-3i7f</guid>
      <description>&lt;p&gt;I recently had the chance to work with a group that were using the &lt;a href="https://www.shortcut.com/" rel="noopener noreferrer"&gt;Shortcut&lt;/a&gt; project management tool which I hadn't used before.&lt;/p&gt;

&lt;p&gt;I came away with a positive impression, as the tool combines the flexibility of Trello with some of the reporting features you get with Jira but without the nightmare complexity of configuration.&lt;/p&gt;

&lt;p&gt;The basic structure of the tool is pretty much the same as Trello, you have columns and cards and the cards can be organised into a hierarchy of epics and stories and assigned to teams, tagged and so on.&lt;/p&gt;

&lt;p&gt;Work moves across the board in a Kanban-style with automatic tracking as the card progresses through the stages. It's possible to integrate with things like Github but its not that sophisticated so a Story is assumed to equate to a single PR by default for example. Although I haven't tried to do anything with it there is an API that you can use to integrate with existing CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;The features that make Shortcut stand out over Trello is that all boards exist within the same projects so multiple views into the work can be consolidated in "Roadmap" and planning views that actually provide a handy overview of overall progress and across multiple streams of work.&lt;/p&gt;

&lt;p&gt;The reporting may be slightly fixed in its format but it's actually enough to be actionable and compared to trying decode what people have setup in Jira it is a bit of a dream to have an opinionated standard setup.&lt;/p&gt;

&lt;p&gt;Building a product backlog is less elegant, you can pile every idea into a card and have a work process to move an idea into a state where it is ready to icebox or work on. I didn't use this area enough to really get a handle on it but it felt that something was lacking here, like a more dedicated review and collaboration screen.&lt;/p&gt;

&lt;p&gt;Overall though Shortcut brings everything that is good about lightweight management tools with a richer feature set and less Atlassian cruft.&lt;/p&gt;

</description>
      <category>delivery</category>
      <category>agile</category>
      <category>tools</category>
    </item>
    <item>
      <title>How to find an SRI hash on jsdelivr</title>
      <dc:creator>Robert Rees</dc:creator>
      <pubDate>Wed, 18 Jan 2023 14:05:53 +0000</pubDate>
      <link>https://dev.to/rrees/how-to-find-an-sri-hash-on-jsdelivr-4c2f</link>
      <guid>https://dev.to/rrees/how-to-find-an-sri-hash-on-jsdelivr-4c2f</guid>
      <description>&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity" rel="noopener noreferrer"&gt;Sub-resource integrity hashes&lt;/a&gt; are something that make using content from public CDNs that little be more secure but the common ones don't make it easy to find out what the hash should be.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.jsdelivr.com/" rel="noopener noreferrer"&gt;jsdelivr&lt;/a&gt; is used in the Bootstrap documentation but the quickstart unhelpfully doesn't include the SRI by default.&lt;/p&gt;

&lt;p&gt;The simplest way to get the hash is to search for the package you're using via the search function on &lt;a href="https://www.jsdelivr.com/" rel="noopener noreferrer"&gt;the main site&lt;/a&gt;. You can then get an option to copy the SRI to your clipboard as one of the options from the Install box.&lt;/p&gt;

&lt;p&gt;However you can also see the value in the jsdeliver API by taking the resource path and replacing the start with &lt;code&gt;https://data.jsdelivr.com/v1/package/&lt;/code&gt; and removing the path element relating to the distributed file. This will show the all the API information for the entire package including the hash (which is &lt;strong&gt;SHA 256&lt;/strong&gt;). See the &lt;a href="https://data.jsdelivr.com/v1/package/npm/bootstrap" rel="noopener noreferrer"&gt;Bootstrap entry&lt;/a&gt; as an example.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>cdn</category>
      <category>sri</category>
    </item>
  </channel>
</rss>
